Skip to content

Commit

Permalink
caddyfile: Do not replace import tokens if they are part of a snippet (
Browse files Browse the repository at this point in the history
…caddyserver#5539)

* fix variadic placeholder in imported file which also imports

* fix tests.

* skip replacing args when imported token may be part of a snippet
  • Loading branch information
WeidiDeng authored May 22, 2023
1 parent 5bd9c49 commit cee4441
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 5 deletions.
50 changes: 45 additions & 5 deletions caddyconfig/caddyfile/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ func (p *parser) addresses() error {

// special case: import directive replaces tokens during parse-time
if tkn == "import" && p.isNewLine() {
err := p.doImport()
err := p.doImport(0)
if err != nil {
return err
}
Expand Down Expand Up @@ -314,7 +314,7 @@ func (p *parser) directives() error {

// special case: import directive replaces tokens during parse-time
if p.Val() == "import" {
err := p.doImport()
err := p.doImport(1)
if err != nil {
return err
}
Expand All @@ -340,7 +340,7 @@ func (p *parser) directives() error {
// is on the token before where the import directive was. In
// other words, call Next() to access the first token that was
// imported.
func (p *parser) doImport() error {
func (p *parser) doImport(nesting int) error {
// syntax checks
if !p.NextArg() {
return p.ArgErr()
Expand Down Expand Up @@ -443,17 +443,57 @@ func (p *parser) doImport() error {
// copy the tokens so we don't overwrite p.definedSnippets
tokensCopy := make([]Token, 0, len(importedTokens))

var (
maybeSnippet bool
maybeSnippetId bool
index int
)

// run the argument replacer on the tokens
// golang for range slice return a copy of value
// similarly, append also copy value
for _, token := range importedTokens {
for i, token := range importedTokens {
// set the token's file to refer to import directive line number and snippet name
if token.snippetName != "" {
token.updateFile(fmt.Sprintf("%s:%d (import %s)", token.File, p.Line(), token.snippetName))
} else {
token.updateFile(fmt.Sprintf("%s:%d (import)", token.File, p.Line()))
}

// naive way of determine snippets, as snippets definition can only follow name + block
// format, won't check for nesting correctness or any other error, that's what parser does.
if !maybeSnippet && nesting == 0 {
// first of the line
if i == 0 || importedTokens[i-1].originalFile() != token.originalFile() || importedTokens[i-1].Line+importedTokens[i-1].NumLineBreaks() < token.Line {
index = 0
} else {
index++
}

if index == 0 && len(token.Text) >= 3 && strings.HasPrefix(token.Text, "(") && strings.HasSuffix(token.Text, ")") {
maybeSnippetId = true
}
}

switch token.Text {
case "{":
nesting++
if index == 1 && maybeSnippetId && nesting == 1 {
maybeSnippet = true
maybeSnippetId = false
}
case "}":
nesting--
if nesting == 0 && maybeSnippet {
maybeSnippet = false
}
}

if maybeSnippet {
tokensCopy = append(tokensCopy, token)
continue
}

foundVariadic, startIndex, endIndex := parseVariadic(token, len(args))
if foundVariadic {
for _, arg := range args[startIndex:endIndex] {
Expand Down Expand Up @@ -553,7 +593,7 @@ func (p *parser) directive() error {
} else if p.Val() == "}" && p.nesting == 0 {
return p.Err("Unexpected '}' because no matching opening brace")
} else if p.Val() == "import" && p.isNewLine() {
if err := p.doImport(); err != nil {
if err := p.doImport(1); err != nil {
return err
}
p.cursor-- // cursor is advanced when we continue, so roll back one more
Expand Down
21 changes: 21 additions & 0 deletions caddyconfig/httpcaddyfile/builtins_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,27 @@ func TestImportErrorLine(t *testing.T) {
return err != nil && strings.Contains(err.Error(), "Caddyfile:5 (import t1):2")
},
},
{
input: `
import testdata/import_variadic_snippet.txt
:8080 {
import t1 true
}`,
errorFunc: func(err error) bool {
return err == nil
},
},
{
input: `
import testdata/import_variadic_with_import.txt
:8080 {
import t1 true
import t2 true
}`,
errorFunc: func(err error) bool {
return err == nil
},
},
} {
adapter := caddyfile.Adapter{
ServerType: ServerType{},
Expand Down
9 changes: 9 additions & 0 deletions caddyconfig/httpcaddyfile/testdata/import_variadic.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
(t2) {
respond 200 {
body {args[:]}
}
}

:8082 {
import t2 false
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
(t1) {
respond 200 {
body {args[:]}
}
}

:8081 {
import t1 false
}
15 changes: 15 additions & 0 deletions caddyconfig/httpcaddyfile/testdata/import_variadic_with_import.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
(t1) {
respond 200 {
body {args[:]}
}
}

:8081 {
import t1 false
}

import import_variadic.txt

:8083 {
import t2 true
}

0 comments on commit cee4441

Please sign in to comment.