Skip to content

Commit

Permalink
dockerfile: handle comments correctly
Browse files Browse the repository at this point in the history
I consulted the official Dockerfile parser, and this seems more correct.
Initial whitespace is ignored when parsing comments, which is done first
on every line. Dockerfile comments (as opposed to comments in any
embedded language) can only start a line, and are logically deleted from
the token stream. Except they're not because actually ignored because
they can contain parser directives.

The handling of leading spaces continues to be a divergence from the
official parser, because its behavior is bonkers.

Signed-off-by: Hank Donnay <hdonnay@redhat.com>
  • Loading branch information
hdonnay committed Dec 15, 2021
1 parent 467ad76 commit 5d08565
Show file tree
Hide file tree
Showing 8 changed files with 77 additions and 7 deletions.
18 changes: 12 additions & 6 deletions rhel/dockerfile/dockerfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,12 +95,15 @@ func (p *labelParser) Run() error {
return err
}
for _, kv := range pairs {
i := strings.IndexByte(kv, '=')
k, _, err := transform.String(p.unquote, kv[:i])
idx := strings.IndexByte(kv, '=')
if idx == -1 {
return fmt.Errorf(`invalid syntax: %+#q`, i.val)
}
k, _, err := transform.String(p.unquote, kv[:idx])
if err != nil {
return err
}
v, _, err := transform.String(transform.Chain(p.unquote, p.vars), kv[i+1:])
v, _, err := transform.String(transform.Chain(p.unquote, p.vars), kv[idx+1:])
if err != nil {
return err
}
Expand All @@ -127,12 +130,15 @@ func (p *labelParser) Run() error {
return err
}
for _, kv := range pairs {
i := strings.IndexByte(kv, '=')
k, _, err := transform.String(p.unquote, kv[:i])
idx := strings.IndexByte(kv, '=')
if idx == -1 {
return fmt.Errorf(`invalid syntax: %+#q`, i.val)
}
k, _, err := transform.String(p.unquote, kv[:idx])
if err != nil {
return err
}
v, _, err := transform.String(transform.Chain(p.unquote, p.vars), kv[i+1:])
v, _, err := transform.String(transform.Chain(p.unquote, p.vars), kv[idx+1:])
if err != nil {
return err
}
Expand Down
29 changes: 29 additions & 0 deletions rhel/dockerfile/itemkind_string.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 16 additions & 1 deletion rhel/dockerfile/lex.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ type item struct {

type itemKind int

//go:generate stringer -type itemKind $GOFILE

const (
itemError itemKind = iota
itemComment
Expand Down Expand Up @@ -118,13 +120,18 @@ func (l *lexer) consumeWhitespace() (err error) {
func (l *lexer) collectLine() (err error) {
var r rune
var sz int
var esc bool
var esc, inComment, started bool
Read:
for r, sz, err = l.rd.ReadRune(); err == nil; r, sz, err = l.rd.ReadRune() {
switch {
case inComment && r == '\n':
inComment = false
started = false
case inComment: // Skip
case esc && r == '\r': // Lexer hack: why do some things have DOS line endings?
case esc && r == '\n':
esc = false
started = false
case esc:
// This little lexer only cares about constructing the lines
// correctly, so everything else gets passed through.
Expand All @@ -134,9 +141,17 @@ Read:
_, err = l.sb.WriteRune(r)
case r == l.escchar:
esc = true
started = true
case !esc && r == '\n':
err = l.rd.UnreadRune()
break Read
case !started && !esc && r == '#':
inComment = true
case !started:
if !unicode.IsSpace(r) {
started = true
}
fallthrough
default:
_, err = l.sb.WriteRune(r)
}
Expand Down
9 changes: 9 additions & 0 deletions rhel/dockerfile/testdata/Dockerfile-Comments
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Normal comments are fine
FROM scratch

LABEL \
# This style of comment is buck wild, but allowed.
A=B \
C=D
# This comment is stripped despite the apparent continuation

4 changes: 4 additions & 0 deletions rhel/dockerfile/testdata/Dockerfile-Comments.want
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"A": "B",
"C": "D"
}
2 changes: 2 additions & 0 deletions rhel/dockerfile/testdata/Dockerfile-InvalidLabel
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
LABEL A=B \
C=D # Comments not allowed in this position
4 changes: 4 additions & 0 deletions rhel/dockerfile/testdata/Dockerfile-InvalidLabel.want
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"A": "B",
"C": "D"
}
1 change: 1 addition & 0 deletions rhel/dockerfile/testdata/Dockerfile-InvalidLabel.want.err
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
invalid syntax: `A=B C=D # Comments not allowed in this position`

0 comments on commit 5d08565

Please sign in to comment.