Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

os/exec: passing single quotes to cmd.Env creates some weird escaping #26823

Closed
drake7707 opened this issue Aug 6, 2018 · 2 comments
Closed
Labels
FrozenDueToAge NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Milestone

Comments

@drake7707
Copy link

Please answer these questions before submitting your issue. Thanks!

What version of Go are you using (go version)?

go version go1.10.3 linux/amd64

Does this issue reproduce with the latest release?

yes, with 1.10.3

What operating system and processor architecture are you using (go env)?

GOARCH="amd64"
GOBIN=""
GOCACHE="/root/.cache/go-build"
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/root/go"
GORACE=""
GOROOT="/usr/local/go"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build636672150=/tmp/go-build -gno-record-gcc-switches"

What did you do?

Passing in cmd.Env environment variables with single quotes get mucked up

Repro:

test.sh:

#!/bin/bash

echo "Testing $DIND_REGISTRY"
set

test.go:

package main

import (
        "bytes"
        "fmt"
        "io"
        "os"
        "os/exec"
        "log"
)

func main() {

        cmd := exec.Command("test.sh")
        cmd.Env = os.Environ()

        test := `DIND_REGISTRY='[ "docker.io", "192.168.254.1:5000" ]'`

        fmt.Println("Appling env var " + test)
        cmd.Env = append(cmd.Env, test)

        var stdBuffer bytes.Buffer
        mw := io.MultiWriter(os.Stdout, &stdBuffer)

        cmd.Stdout = mw
        cmd.Stderr = mw

        if err := cmd.Run(); err != nil {
                log.Fatal("Unable to run the script:" + err.Error())
        }
}

What did you expect to see?

I expected to see the literal environment variable as I specified it in the script:
DIND_REGISTRY='[ "docker.io", "192.168.254.1:5000" ]'

What did you see instead?

DIND_REGISTRY=''\''[ "docker.io", "192.168.254.1:5000" ]'\'''

@agnivade agnivade changed the title Passing single quotes in environment variables to child script process gain some weird escaping os/exec: passing single quotes to cmd.Env creates some weird escaping Aug 6, 2018
@agnivade agnivade added the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label Aug 6, 2018
@agnivade agnivade added this to the Go1.12 milestone Aug 6, 2018
@cuonglm
Copy link
Member

cuonglm commented Aug 6, 2018

It's normal and the right behavior. When you do:

DIND_REGISTRY='[ "docker.io", "192.168.254.1:5000" ]'

in environment, the variable DIND_REGISTRY has value '[ "docker.io", "192.168.254.1:5000" ]'. The single quote ' need to be quoted correctly, so when the shell interpret it, it will printed correctly..

In:

''\''[ "docker.io", "192.168.254.1:5000" ]'\'''
  • The first ' denotes start of string
  • The first '\'' is the single quote itself
  • The second '\'' is for the second single quote
  • The last ' denotes end of string

It depends on application to quote the value so the shell can understand it. Here go does it correctly.

@drake7707
Copy link
Author

@Gnouc Thanks for your explanation, I got confused with the multitude of single quotes.

I received the values in an array to set to apply and it worked until I encountered that particular one with the added single quotes.

Here is a snippet to remove the prefix and suffix single quote in case someone else encounters the same issue

        test := `DIND_REGISTRY='[ "docker.io", "192.168.254.1:5000" ]'`

        varParts := strings.Split(test, "=")

        if len(varParts) > 1 && len(varParts[1]) > 0 && varParts[1][0] == []byte(`'`)[0] {
          varParts[1] = strings.TrimPrefix(varParts[1], `'`)
          varParts[len(varParts)-1] = strings.TrimSuffix(varParts[len(varParts)-1], `'`)
        }
        test = strings.Join(varParts, "=")

@golang golang locked and limited conversation to collaborators Aug 6, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Projects
None yet
Development

No branches or pull requests

4 participants