Commit d8c50264 authored by Matthew Holt's avatar Matthew Holt

Fix parser when address is empty token

Bug detected by go-fuzz (more fuzzing is required; need larger corpus)
parent 8d81ae88
...@@ -36,6 +36,9 @@ func Load(filename string, input io.Reader) (Group, error) { ...@@ -36,6 +36,9 @@ func Load(filename string, input io.Reader) (Group, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
if len(serverBlocks) == 0 {
return Default()
}
// Each server block represents one or more servers/addresses. // Each server block represents one or more servers/addresses.
// Iterate each server block and make a config for each one, // Iterate each server block and make a config for each one,
......
...@@ -21,7 +21,9 @@ func (p *parser) parseAll() ([]ServerBlock, error) { ...@@ -21,7 +21,9 @@ func (p *parser) parseAll() ([]ServerBlock, error) {
if err != nil { if err != nil {
return blocks, err return blocks, err
} }
blocks = append(blocks, p.block) if len(p.block.Addresses) > 0 {
blocks = append(blocks, p.block)
}
} }
return blocks, nil return blocks, nil
...@@ -85,21 +87,23 @@ func (p *parser) addresses() error { ...@@ -85,21 +87,23 @@ func (p *parser) addresses() error {
break break
} }
// Trailing comma indicates another address will follow, which if tkn != "" {
// may possibly be on the next line // Trailing comma indicates another address will follow, which
if tkn[len(tkn)-1] == ',' { // may possibly be on the next line
tkn = tkn[:len(tkn)-1] if tkn[len(tkn)-1] == ',' {
expectingAnother = true tkn = tkn[:len(tkn)-1]
} else { expectingAnother = true
expectingAnother = false // but we may still see another one on this line } else {
} expectingAnother = false // but we may still see another one on this line
}
// Parse and save this address // Parse and save this address
host, port, err := standardAddress(tkn) host, port, err := standardAddress(tkn)
if err != nil { if err != nil {
return err return err
}
p.block.Addresses = append(p.block.Addresses, Address{host, port})
} }
p.block.Addresses = append(p.block.Addresses, Address{host, port})
// Advance token and possibly break out of loop or return error // Advance token and possibly break out of loop or return error
hasNext := p.Next() hasNext := p.Next()
......
...@@ -61,7 +61,7 @@ func TestParseOneAndImport(t *testing.T) { ...@@ -61,7 +61,7 @@ func TestParseOneAndImport(t *testing.T) {
testParseOne := func(input string) (ServerBlock, error) { testParseOne := func(input string) (ServerBlock, error) {
p := testParser(input) p := testParser(input)
p.Next() p.Next() // parseOne doesn't call Next() to start, so we must
err := p.parseOne() err := p.parseOne()
return p.block, err return p.block, err
} }
...@@ -234,6 +234,10 @@ func TestParseOneAndImport(t *testing.T) { ...@@ -234,6 +234,10 @@ func TestParseOneAndImport(t *testing.T) {
"dir1": 1, "dir1": 1,
"dir2": 2, "dir2": 2,
}}, }},
{``, false, []Address{}, map[string]int{}},
{`""`, false, []Address{}, map[string]int{}},
} { } {
result, err := testParseOne(test.input) result, err := testParseOne(test.input)
...@@ -275,6 +279,62 @@ func TestParseOneAndImport(t *testing.T) { ...@@ -275,6 +279,62 @@ func TestParseOneAndImport(t *testing.T) {
} }
} }
func TestParseAll(t *testing.T) {
setupParseTests()
testParseAll := func(input string) ([]ServerBlock, error) {
p := testParser(input)
return p.parseAll()
}
for i, test := range []struct {
input string
shouldErr bool
numBlocks int
}{
{`localhost`, false, 1},
{`localhost {
dir1
}`, false, 1},
{`http://localhost https://localhost
dir1 foo bar`, false, 1},
{`http://localhost, https://localhost {
dir1 foo bar
}`, false, 1},
{`http://host1.com,
http://host2.com,
https://host3.com`, false, 1},
{`host1 {
}
host2 {
}`, false, 2},
{`""`, false, 0},
{``, false, 0},
} {
results, err := testParseAll(test.input)
if test.shouldErr && err == nil {
t.Errorf("Test %d: Expected an error, but didn't get one", i)
}
if !test.shouldErr && err != nil {
t.Errorf("Test %d: Expected no error, but got: %v", i, err)
}
if len(results) != test.numBlocks {
t.Errorf("Test %d: Expected %d server blocks, got %d",
i, test.numBlocks, len(results))
continue
}
}
}
func setupParseTests() { func setupParseTests() {
// Set up some bogus directives for testing // Set up some bogus directives for testing
ValidDirectives = map[string]struct{}{ ValidDirectives = map[string]struct{}{
......
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