瀏覽代碼

builder: fix escaping for ENV variables.

Docker-DCO-1.1-Signed-off-by: Erik Hollensbe <github@hollensbe.org> (github: erikh)
Erik Hollensbe 10 年之前
父節點
當前提交
cf23053eb1
共有 2 個文件被更改,包括 68 次插入1 次删除
  1. 13 1
      builder/support.go
  2. 55 0
      integration-cli/docker_cli_build_test.go

+ 13 - 1
builder/support.go

@@ -10,13 +10,25 @@ var (
 	// `\$` - match literal $
 	// `[[:alnum:]_]+` - match things like `$SOME_VAR`
 	// `{[[:alnum:]_]+}` - match things like `${SOME_VAR}`
-	tokenEnvInterpolation = regexp.MustCompile(`(\\\\+|[^\\]|\b|\A)\$([[:alnum:]_]+|{[[:alnum:]_]+})`)
+	tokenEnvInterpolation = regexp.MustCompile(`(\\|\\\\+|[^\\]|\b|\A)\$([[:alnum:]_]+|{[[:alnum:]_]+})`)
 	// this intentionally punts on more exotic interpolations like ${SOME_VAR%suffix} and lets the shell handle those directly
 )
 
 // handle environment replacement. Used in dispatcher.
 func (b *Builder) replaceEnv(str string) string {
 	for _, match := range tokenEnvInterpolation.FindAllString(str, -1) {
+		idx := strings.Index(match, "\\$")
+		if idx != -1 {
+			if idx+2 >= len(match) {
+				str = strings.Replace(str, match, "\\$", -1)
+				continue
+			}
+
+			stripped := match[idx+2:]
+			str = strings.Replace(str, match, "$"+stripped, -1)
+			continue
+		}
+
 		match = match[strings.Index(match, "$"):]
 		matchKey := strings.Trim(match, "${}")
 

+ 55 - 0
integration-cli/docker_cli_build_test.go

@@ -15,6 +15,61 @@ import (
 	"github.com/docker/docker/pkg/archive"
 )
 
+func TestBuildEnvEscapes(t *testing.T) {
+	name := "testbuildenvescapes"
+	defer deleteAllContainers()
+	defer deleteImages(name)
+	_, err := buildImage(name,
+		`
+    FROM busybox
+    ENV TEST foo
+    CMD echo \$
+    `,
+		true)
+
+	out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-t", name))
+
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if strings.TrimSpace(out) != "$" {
+		t.Fatalf("Env TEST was not overwritten with bar when foo was supplied to dockerfile: was %q", strings.TrimSpace(out))
+	}
+
+	logDone("build - env should handle \\$ properly")
+}
+
+func TestBuildEnvOverwrite(t *testing.T) {
+	name := "testbuildenvoverwrite"
+	defer deleteAllContainers()
+	defer deleteImages(name)
+
+	_, err := buildImage(name,
+		`
+    FROM busybox
+    ENV TEST foo
+    CMD echo \${TEST}
+    `,
+		true)
+
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-e", "TEST=bar", "-t", name))
+
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if strings.TrimSpace(out) != "bar" {
+		t.Fatalf("Env TEST was not overwritten with bar when foo was supplied to dockerfile: was %q", strings.TrimSpace(out))
+	}
+
+	logDone("build - env should overwrite builder ENV during run")
+}
+
 func TestBuildOnBuildForbiddenMaintainerInSourceImage(t *testing.T) {
 	name := "testbuildonbuildforbiddenmaintainerinsourceimage"
 	defer deleteImages(name)