mirror of
https://github.com/caddyserver/caddy.git
synced 2025-01-14 14:56:27 +03:00
caddyfile: Prevent bad block opening tokens (#4655)
* caddyfile: Prevent bad block opening tokens * Clarifying comments
This commit is contained in:
parent
c9b5e7f77b
commit
134b805644
3 changed files with 77 additions and 2 deletions
|
@ -458,6 +458,60 @@ func (d *Dispenser) isNewLine() bool {
|
||||||
if d.cursor > len(d.tokens)-1 {
|
if d.cursor > len(d.tokens)-1 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return d.tokens[d.cursor-1].File != d.tokens[d.cursor].File ||
|
|
||||||
d.tokens[d.cursor-1].Line+d.numLineBreaks(d.cursor-1) < d.tokens[d.cursor].Line
|
prev := d.tokens[d.cursor-1]
|
||||||
|
curr := d.tokens[d.cursor]
|
||||||
|
|
||||||
|
// If the previous token is from a different file,
|
||||||
|
// we can assume it's from a different line
|
||||||
|
if prev.File != curr.File {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// The previous token may contain line breaks if
|
||||||
|
// it was quoted and spanned multiple lines. e.g:
|
||||||
|
//
|
||||||
|
// dir "foo
|
||||||
|
// bar
|
||||||
|
// baz"
|
||||||
|
prevLineBreaks := d.numLineBreaks(d.cursor - 1)
|
||||||
|
|
||||||
|
// If the previous token (incl line breaks) ends
|
||||||
|
// on a line earlier than the current token,
|
||||||
|
// then the current token is on a new line
|
||||||
|
return prev.Line+prevLineBreaks < curr.Line
|
||||||
|
}
|
||||||
|
|
||||||
|
// isNextOnNewLine determines whether the current token is on a different
|
||||||
|
// line (higher line number) than the next token. It handles imported
|
||||||
|
// tokens correctly. If there isn't a next token, it returns true.
|
||||||
|
func (d *Dispenser) isNextOnNewLine() bool {
|
||||||
|
if d.cursor < 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if d.cursor >= len(d.tokens)-1 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
curr := d.tokens[d.cursor]
|
||||||
|
next := d.tokens[d.cursor+1]
|
||||||
|
|
||||||
|
// If the next token is from a different file,
|
||||||
|
// we can assume it's from a different line
|
||||||
|
if curr.File != next.File {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// The current token may contain line breaks if
|
||||||
|
// it was quoted and spanned multiple lines. e.g:
|
||||||
|
//
|
||||||
|
// dir "foo
|
||||||
|
// bar
|
||||||
|
// baz"
|
||||||
|
currLineBreaks := d.numLineBreaks(d.cursor)
|
||||||
|
|
||||||
|
// If the current token (incl line breaks) ends
|
||||||
|
// on a line earlier than the next token,
|
||||||
|
// then the next token is on a new line
|
||||||
|
return curr.Line+currLineBreaks < next.Line
|
||||||
}
|
}
|
||||||
|
|
|
@ -494,6 +494,13 @@ func (p *parser) directive() error {
|
||||||
for p.Next() {
|
for p.Next() {
|
||||||
if p.Val() == "{" {
|
if p.Val() == "{" {
|
||||||
p.nesting++
|
p.nesting++
|
||||||
|
if !p.isNextOnNewLine() && p.Token().wasQuoted == 0 {
|
||||||
|
return p.Err("Unexpected next token after '{' on same line")
|
||||||
|
}
|
||||||
|
} else if p.Val() == "{}" {
|
||||||
|
if p.isNextOnNewLine() && p.Token().wasQuoted == 0 {
|
||||||
|
return p.Err("Unexpected '{}' at end of line")
|
||||||
|
}
|
||||||
} else if p.isNewLine() && p.nesting == 0 {
|
} else if p.isNewLine() && p.nesting == 0 {
|
||||||
p.cursor-- // read too far
|
p.cursor-- // read too far
|
||||||
break
|
break
|
||||||
|
|
|
@ -191,6 +191,20 @@ func TestParseOneAndImport(t *testing.T) {
|
||||||
|
|
||||||
{``, false, []string{}, []int{}},
|
{``, false, []string{}, []int{}},
|
||||||
|
|
||||||
|
// Unexpected next token after '{' on same line
|
||||||
|
{`localhost
|
||||||
|
dir1 { a b }`, true, []string{"localhost"}, []int{}},
|
||||||
|
// Workaround with quotes
|
||||||
|
{`localhost
|
||||||
|
dir1 "{" a b "}"`, false, []string{"localhost"}, []int{5}},
|
||||||
|
|
||||||
|
// Unexpected '{}' at end of line
|
||||||
|
{`localhost
|
||||||
|
dir1 {}`, true, []string{"localhost"}, []int{}},
|
||||||
|
// Workaround with quotes
|
||||||
|
{`localhost
|
||||||
|
dir1 "{}"`, false, []string{"localhost"}, []int{2}},
|
||||||
|
|
||||||
// import with args
|
// import with args
|
||||||
{`import testdata/import_args0.txt a`, false, []string{"a"}, []int{}},
|
{`import testdata/import_args0.txt a`, false, []string{"a"}, []int{}},
|
||||||
{`import testdata/import_args1.txt a b`, false, []string{"a", "b"}, []int{}},
|
{`import testdata/import_args1.txt a b`, false, []string{"a", "b"}, []int{}},
|
||||||
|
|
Loading…
Reference in a new issue