Skip to content

Commit 543b91b

Browse files
authored
fix(caddyfile): bump expansion limits (#9)
A single maxSnippetExpansions of 1000 could be too low for some real world scenarios. Snippet-based configuration can be used broadly across large CoreDNS Corefiles. We cannot implement a pure “import depth” integer with the current splice-then-continue parser because imports are expanded by lexing and splicing tokens into the stream, not by recursive function calls. Instead, we introduce high default per-directive caps for snippet and file imports, keeping globs counted as one. Prevent trivial snippet self-import. Add tests that lower caps to validate failure on cycles and success with large glob imports. This should present a good enough middleground, instead of rewriting the parser. Signed-off-by: Ville Vesilehto <[email protected]>
1 parent fabd98a commit 543b91b

File tree

2 files changed

+38
-2
lines changed

2 files changed

+38
-2
lines changed

caddyfile/parse.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,12 @@ type parser struct {
6060
}
6161

6262
// maxSnippetExpansions is a hard cap to prevent excessively deep or cyclic snippet imports.
63-
const maxSnippetExpansions = 1000
63+
// set as a variable to allow modifications for testing
64+
var maxSnippetExpansions = 10000
65+
66+
// maxFileExpansions is a hard cap to prevent excessively deep or cyclic file imports.
67+
// set as a variable to allow modifications for testing
68+
var maxFileExpansions = 100000
6469

6570
func (p *parser) parseAll() ([]ServerBlock, error) {
6671
var blocks []ServerBlock
@@ -268,7 +273,7 @@ func (p *parser) doImport() error {
268273
p.snippetExpansions++
269274
importedTokens = p.definedSnippets[importPattern]
270275
} else {
271-
if p.fileExpansions >= maxSnippetExpansions {
276+
if p.fileExpansions >= maxFileExpansions {
272277
return p.Errf("maximum file import depth (%d) exceeded", maxSnippetExpansions)
273278
}
274279
p.fileExpansions++

caddyfile/parse_test.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,20 @@
1515
package caddyfile
1616

1717
import (
18+
"fmt"
1819
"io/ioutil"
1920
"os"
2021
"path/filepath"
2122
"strings"
2223
"testing"
2324
)
2425

26+
func init() {
27+
// set a lower limit for testing only
28+
maxSnippetExpansions = 10
29+
maxFileExpansions = 10
30+
}
31+
2532
func TestAllTokens(t *testing.T) {
2633
tests := []struct {
2734
name string
@@ -801,3 +808,27 @@ func TestFileImportCycleError(t *testing.T) {
801808
t.Fatalf("expected error for file import cycle, got nil")
802809
}
803810
}
811+
812+
func TestFileImportDir(t *testing.T) {
813+
dir, err := ioutil.TempDir("", t.Name())
814+
if err != nil {
815+
t.Fatal(err)
816+
}
817+
defer os.RemoveAll(dir)
818+
819+
// create 10x the maxFileExpansions files
820+
// a single import with a glob should not error
821+
for i := 0; i < maxFileExpansions*10; i++ {
822+
fp := filepath.Join(dir, filepath.Base(dir)+"_"+fmt.Sprintf("%d", i))
823+
if err := ioutil.WriteFile(fp, []byte(""), 0644); err != nil {
824+
t.Fatal(err)
825+
}
826+
}
827+
828+
input := "import " + filepath.Join(dir, "*")
829+
p := testParser(input)
830+
_, err = p.parseAll()
831+
if err != nil {
832+
t.Fatalf("unexpected error importing temp dir via glob: %v", err)
833+
}
834+
}

0 commit comments

Comments
 (0)