Commit 64c18a7c authored by Matt Holt's avatar Matt Holt Committed by GitHub

caddyfile: Fix errors caught by fuzzing (#2097)

* caddyfile: More robust parsing for 'import' (fixes #2096)

The fix for hanging involves limiting the number of wildcards in an
import pattern to just 1. Otherwise some patterns can expand to the
entire disk.

The other fix requires that the end string for an environment variable
expansion come after the start string.

* caddyfile: Fix more fuzzing errors
parent d2fc0452
...@@ -263,14 +263,19 @@ func (p *parser) doImport() error { ...@@ -263,14 +263,19 @@ func (p *parser) doImport() error {
} else { } else {
globPattern = importPattern globPattern = importPattern
} }
if strings.Count(globPattern, "*") > 1 || strings.Count(globPattern, "?") > 1 ||
(strings.Contains(globPattern, "[") && strings.Contains(globPattern, "]")) {
// See issue #2096 - a pattern with many glob expansions can hang for too long
return p.Errf("Glob pattern may only contain one wildcard (*), but has others: %s", globPattern)
}
matches, err = filepath.Glob(globPattern) matches, err = filepath.Glob(globPattern)
if err != nil { if err != nil {
return p.Errf("Failed to use import pattern %s: %v", importPattern, err) return p.Errf("Failed to use import pattern %s: %v", importPattern, err)
} }
if len(matches) == 0 { if len(matches) == 0 {
if strings.Contains(globPattern, "*") { if strings.ContainsAny(globPattern, "*?[]") {
log.Printf("[WARNING] No files matching import pattern: %s", importPattern) log.Printf("[WARNING] No files matching import glob pattern: %s", importPattern)
} else { } else {
return p.Errf("File to import not found: %s", importPattern) return p.Errf("File to import not found: %s", importPattern)
} }
...@@ -440,7 +445,7 @@ func replaceEnvReferences(s, refStart, refEnd string) string { ...@@ -440,7 +445,7 @@ func replaceEnvReferences(s, refStart, refEnd string) string {
index := strings.Index(s, refStart) index := strings.Index(s, refStart)
for index != -1 { for index != -1 {
endIndex := strings.Index(s, refEnd) endIndex := strings.Index(s, refEnd)
if endIndex != -1 { if endIndex > index+len(refStart) {
ref := s[index : endIndex+len(refEnd)] ref := s[index : endIndex+len(refEnd)]
s = strings.Replace(s, ref, os.Getenv(ref[len(refStart):len(ref)-len(refEnd)]), -1) s = strings.Replace(s, ref, os.Getenv(ref[len(refStart):len(ref)-len(refEnd)]), -1)
} else { } else {
......
...@@ -228,6 +228,17 @@ func TestParseOneAndImport(t *testing.T) { ...@@ -228,6 +228,17 @@ func TestParseOneAndImport(t *testing.T) {
{`""`, false, []string{}, map[string]int{}}, {`""`, false, []string{}, map[string]int{}},
{``, false, []string{}, map[string]int{}}, {``, false, []string{}, map[string]int{}},
// test cases found by fuzzing!
{`import }{$"`, true, []string{}, map[string]int{}},
{`import /*/*.txt`, true, []string{}, map[string]int{}},
{`import /???/?*?o`, true, []string{}, map[string]int{}},
{`import /??`, true, []string{}, map[string]int{}},
{`import /[a-z]`, true, []string{}, map[string]int{}},
{`import {$}`, true, []string{}, map[string]int{}},
{`import {%}`, true, []string{}, map[string]int{}},
{`import {$$}`, true, []string{}, map[string]int{}},
{`import {%%}`, true, []string{}, map[string]int{}},
} { } {
result, err := testParseOne(test.input) result, err := testParseOne(test.input)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment