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

Fix quote strip behavior for ARG values #850

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Fix quote strip behavior for ARG values
* fixes issue 847
* previous implementation did not properly parse blank
values which were enclosed in quotes
  • Loading branch information
cvgw committed Nov 8, 2019
commit 006b4996cbceda2cdebb7a14ab49e80cde143bbb
3 changes: 3 additions & 0 deletions integration/dockerfiles/Dockerfile_test_arg_multi_empty_val
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
ARG VARIANT=""
ARG VERSION=1
FROM busybox${VARIANT}:1.3${VERSION}
65 changes: 52 additions & 13 deletions pkg/dockerfile/dockerfile.go
Original file line number Diff line number Diff line change
@@ -123,23 +123,13 @@ func Parse(b []byte) ([]instructions.Stage, []instructions.ArgCommand, error) {
// stripEnclosingQuotes removes quotes enclosing the value of each instructions.ArgCommand in a slice
// if the quotes are escaped it leaves them
func stripEnclosingQuotes(metaArgs []instructions.ArgCommand) ([]instructions.ArgCommand, error) {
dbl := byte('"')
sgl := byte('\'')

for i := range metaArgs {
arg := metaArgs[i]
v := arg.Value
if v != nil {
val := *v
fmt.Printf("val %s\n", val)
if (val[0] == dbl && val[len(val)-1] == dbl) || (val[0] == sgl && val[len(val)-1] == sgl) {
val = val[1 : len(val)-1]
} else if val[:2] == `\"` && val[len(val)-2:] == `\"` {
continue
} else if val[:2] == `\'` && val[len(val)-2:] == `\'` {
continue
} else if val[0] == dbl || val[0] == sgl || val[len(val)-1] == dbl || val[len(val)-1] == sgl {
return nil, errors.New("quotes wrapping arg values must be matched")
val, err := extractValFromQuotes(*v)
if err != nil {
return nil, err
}

arg.Value = &val
@@ -149,6 +139,55 @@ func stripEnclosingQuotes(metaArgs []instructions.ArgCommand) ([]instructions.Ar
return metaArgs, nil
}

func extractValFromQuotes(val string) (string, error) {
backSlash := byte('\\')
if len(val) < 2 {
return val, nil
}

var leader string
var tail string

switch char := val[0]; char {
case '\'', '"':
leader = string([]byte{char})
case backSlash:
switch char := val[1]; char {
case '\'', '"':
leader = string([]byte{backSlash, char})
}
}

// If the length of leader is greater than one then it must be an escaped
// character.
if len(leader) < 2 {
switch char := val[len(val)-1]; char {
case '\'', '"':
tail = string([]byte{char})
}
} else {
switch char := val[len(val)-2:]; char {
case `\'`, `\"`:
tail = char
}
}

if leader != tail {
logrus.Infof("leader %s tail %s", leader, tail)
return "", errors.New("quotes wrapping arg values must be matched")
}

if leader == "" {
return val, nil
}

if len(leader) == 2 {
return val, nil
}

return val[1 : len(val)-1], nil
}

// targetStage returns the index of the target stage kaniko is trying to build
func targetStage(stages []instructions.Stage, target string) (int, error) {
if target == "" {
10 changes: 9 additions & 1 deletion pkg/dockerfile/dockerfile_test.go
Original file line number Diff line number Diff line change
@@ -118,7 +118,7 @@ func Test_stripEnclosingQuotes(t *testing.T) {
success: true,
}, {
name: "blank value with enclosing double quotes",
inArgs: []instructions.ArgCommand{newArgCommand("MEOW", "\"\"")},
inArgs: []instructions.ArgCommand{newArgCommand("MEOW", `""`)},
expected: []string{""},
success: true,
}, {
@@ -144,6 +144,14 @@ func Test_stripEnclosingQuotes(t *testing.T) {
},
expected: []string{"Purr", "Mrow"},
success: true,
}, {
name: "multiple values, one blank, one a single int",
inArgs: []instructions.ArgCommand{
newArgCommand("MEOW", `""`),
newArgCommand("MEW", `1`),
},
expected: []string{"", "1"},
success: true,
}, {
name: "no values",
success: true,