Browse code

builder: fix escaping for ENV variables.

Docker-DCO-1.1-Signed-off-by: Erik Hollensbe <github@hollensbe.org> (github: erikh)

Erik Hollensbe authored on 2014/10/18 04:15:07
Showing 2 changed files
... ...
@@ -10,13 +10,25 @@ var (
10 10
 	// `\$` - match literal $
11 11
 	// `[[:alnum:]_]+` - match things like `$SOME_VAR`
12 12
 	// `{[[:alnum:]_]+}` - match things like `${SOME_VAR}`
13
-	tokenEnvInterpolation = regexp.MustCompile(`(\\\\+|[^\\]|\b|\A)\$([[:alnum:]_]+|{[[:alnum:]_]+})`)
13
+	tokenEnvInterpolation = regexp.MustCompile(`(\\|\\\\+|[^\\]|\b|\A)\$([[:alnum:]_]+|{[[:alnum:]_]+})`)
14 14
 	// this intentionally punts on more exotic interpolations like ${SOME_VAR%suffix} and lets the shell handle those directly
15 15
 )
16 16
 
17 17
 // handle environment replacement. Used in dispatcher.
18 18
 func (b *Builder) replaceEnv(str string) string {
19 19
 	for _, match := range tokenEnvInterpolation.FindAllString(str, -1) {
20
+		idx := strings.Index(match, "\\$")
21
+		if idx != -1 {
22
+			if idx+2 >= len(match) {
23
+				str = strings.Replace(str, match, "\\$", -1)
24
+				continue
25
+			}
26
+
27
+			stripped := match[idx+2:]
28
+			str = strings.Replace(str, match, "$"+stripped, -1)
29
+			continue
30
+		}
31
+
20 32
 		match = match[strings.Index(match, "$"):]
21 33
 		matchKey := strings.Trim(match, "${}")
22 34
 
... ...
@@ -15,6 +15,61 @@ import (
15 15
 	"github.com/docker/docker/pkg/archive"
16 16
 )
17 17
 
18
+func TestBuildEnvEscapes(t *testing.T) {
19
+	name := "testbuildenvescapes"
20
+	defer deleteAllContainers()
21
+	defer deleteImages(name)
22
+	_, err := buildImage(name,
23
+		`
24
+    FROM busybox
25
+    ENV TEST foo
26
+    CMD echo \$
27
+    `,
28
+		true)
29
+
30
+	out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-t", name))
31
+
32
+	if err != nil {
33
+		t.Fatal(err)
34
+	}
35
+
36
+	if strings.TrimSpace(out) != "$" {
37
+		t.Fatalf("Env TEST was not overwritten with bar when foo was supplied to dockerfile: was %q", strings.TrimSpace(out))
38
+	}
39
+
40
+	logDone("build - env should handle \\$ properly")
41
+}
42
+
43
+func TestBuildEnvOverwrite(t *testing.T) {
44
+	name := "testbuildenvoverwrite"
45
+	defer deleteAllContainers()
46
+	defer deleteImages(name)
47
+
48
+	_, err := buildImage(name,
49
+		`
50
+    FROM busybox
51
+    ENV TEST foo
52
+    CMD echo \${TEST}
53
+    `,
54
+		true)
55
+
56
+	if err != nil {
57
+		t.Fatal(err)
58
+	}
59
+
60
+	out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-e", "TEST=bar", "-t", name))
61
+
62
+	if err != nil {
63
+		t.Fatal(err)
64
+	}
65
+
66
+	if strings.TrimSpace(out) != "bar" {
67
+		t.Fatalf("Env TEST was not overwritten with bar when foo was supplied to dockerfile: was %q", strings.TrimSpace(out))
68
+	}
69
+
70
+	logDone("build - env should overwrite builder ENV during run")
71
+}
72
+
18 73
 func TestBuildOnBuildForbiddenMaintainerInSourceImage(t *testing.T) {
19 74
 	name := "testbuildonbuildforbiddenmaintainerinsourceimage"
20 75
 	defer deleteImages(name)