Skip to content

Commit 10053f7

Browse files
caddyfile: Loosen heredoc parsing (#5761)
1 parent 0a6d333 commit 10053f7

File tree

2 files changed

+61
-15
lines changed

2 files changed

+61
-15
lines changed

caddyconfig/caddyfile/lexer.go

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -137,18 +137,28 @@ func (l *lexer) next() (bool, error) {
137137
}
138138

139139
// detect whether we have the start of a heredoc
140-
if !inHeredoc && !heredocEscaped && len(val) > 1 && string(val[:2]) == "<<" {
141-
if ch == '<' {
142-
return false, fmt.Errorf("too many '<' for heredoc on line #%d; only use two, for example <<END", l.line)
140+
if !(quoted || btQuoted) && !(inHeredoc || heredocEscaped) &&
141+
len(val) > 1 && string(val[:2]) == "<<" {
142+
// a space means it's just a regular token and not a heredoc
143+
if ch == ' ' {
144+
return makeToken(0), nil
143145
}
146+
147+
// skip CR, we only care about LF
144148
if ch == '\r' {
145149
continue
146150
}
151+
147152
// after hitting a newline, we know that the heredoc marker
148153
// is the characters after the two << and the newline.
149154
// we reset the val because the heredoc is syntax we don't
150155
// want to keep.
151156
if ch == '\n' {
157+
// check if there's too many <
158+
if string(val[:3]) == "<<<" {
159+
return false, fmt.Errorf("too many '<' for heredoc on line #%d; only use two, for example <<END", l.line)
160+
}
161+
152162
heredocMarker = string(val[2:])
153163
if !heredocMarkerRegexp.Match([]byte(heredocMarker)) {
154164
return false, fmt.Errorf("heredoc marker on line #%d must contain only alpha-numeric characters, dashes and underscores; got '%s'", l.line, heredocMarker)

caddyconfig/caddyfile/lexer_test.go

Lines changed: 48 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -322,15 +322,59 @@ EOF same-line-arg
322322
},
323323
},
324324
{
325-
input: []byte(`heredoc <EOF
325+
input: []byte(`escaped-heredoc \<< >>`),
326+
expected: []Token{
327+
{Line: 1, Text: `escaped-heredoc`},
328+
{Line: 1, Text: `<<`},
329+
{Line: 1, Text: `>>`},
330+
},
331+
},
332+
{
333+
input: []byte(`not-a-heredoc <EOF
326334
content
327-
EOF same-line-arg
328335
`),
329336
expected: []Token{
330-
{Line: 1, Text: `heredoc`},
337+
{Line: 1, Text: `not-a-heredoc`},
331338
{Line: 1, Text: `<EOF`},
332339
{Line: 2, Text: `content`},
333-
{Line: 3, Text: `EOF`},
340+
},
341+
},
342+
{
343+
input: []byte(`not-a-heredoc <<<EOF content`),
344+
expected: []Token{
345+
{Line: 1, Text: `not-a-heredoc`},
346+
{Line: 1, Text: `<<<EOF`},
347+
{Line: 1, Text: `content`},
348+
},
349+
},
350+
{
351+
input: []byte(`not-a-heredoc "<<" ">>"`),
352+
expected: []Token{
353+
{Line: 1, Text: `not-a-heredoc`},
354+
{Line: 1, Text: `<<`},
355+
{Line: 1, Text: `>>`},
356+
},
357+
},
358+
{
359+
input: []byte(`not-a-heredoc << >>`),
360+
expected: []Token{
361+
{Line: 1, Text: `not-a-heredoc`},
362+
{Line: 1, Text: `<<`},
363+
{Line: 1, Text: `>>`},
364+
},
365+
},
366+
{
367+
input: []byte(`not-a-heredoc <<HERE SAME LINE
368+
content
369+
HERE same-line-arg
370+
`),
371+
expected: []Token{
372+
{Line: 1, Text: `not-a-heredoc`},
373+
{Line: 1, Text: `<<HERE`},
374+
{Line: 1, Text: `SAME`},
375+
{Line: 1, Text: `LINE`},
376+
{Line: 2, Text: `content`},
377+
{Line: 3, Text: `HERE`},
334378
{Line: 3, Text: `same-line-arg`},
335379
},
336380
},
@@ -365,14 +409,6 @@ EOF same-line-arg
365409
},
366410
},
367411
},
368-
{
369-
input: []byte(`heredoc <<HERE SAME LINE
370-
content
371-
HERE same-line-arg
372-
`),
373-
expectErr: true,
374-
errorMessage: "heredoc marker on line #1 must contain only alpha-numeric characters, dashes and underscores; got 'HERE SAME LINE'",
375-
},
376412
{
377413
input: []byte(`heredoc <<<EOF
378414
content

0 commit comments

Comments
 (0)