diff --git a/generate.go b/generate.go index f7b940379..26edc4f40 100644 --- a/generate.go +++ b/generate.go @@ -49,14 +49,14 @@ func (zp *ZoneParser) generate(l lex) (RR, bool) { if err != nil { return zp.setParseError("bad stop in $GENERATE range", l) } - if end < 0 || start < 0 || end < start { + if end < 0 || start < 0 || end < start || (end-start)/step > 65535 { return zp.setParseError("bad range in $GENERATE range", l) } // _BLANK l, ok := zp.c.Next() if !ok || l.value != zBlank { - return zp.setParseError("garbage after $GENERATE range", l) + return zp.setParseError("garbage after $GENERATE range", l) } // Create a complete new string, which we then parse again. diff --git a/generate_test.go b/generate_test.go index e638c2664..3757a7e77 100644 --- a/generate_test.go +++ b/generate_test.go @@ -205,27 +205,31 @@ $GENERATE 32-158 dhcp-${-32,4,d} A 10.0.0.$ } } +func TestOutofRangeRange(t *testing.T) { + // outside limit + data := `$GENERATE 0-65536 dhcp A 10.0.0.1` + zp := NewZoneParser(strings.NewReader(data), ".", "test") + for _, ok := zp.Next(); ok; _, ok = zp.Next() { + } + if zp.Err() == nil || !strings.Contains(zp.Err().Error(), "dns: bad range in $GENERATE") { + t.Errorf("Expected %q error, got %s", "bad range", zp.Err()) + } + // within limit + data = `$GENERATE 0-65535 dhcp A 10.0.0.1` + zp = NewZoneParser(strings.NewReader(data), ".", "test") + for _, ok := zp.Next(); ok; _, ok = zp.Next() { + } + if zp.Err() != nil { + t.Errorf("Expected nil error, got %s", zp.Err()) + } -func TestCrasherString(t *testing.T) { - tests := []struct{ - in string - err string -}{ - {"$GENERATE 0-300103\"$$GENERATE 2-2", "dns: garbage after $GENERATE range: \"\\\"\" at line: 1:19"}, - {"$GENERATE 0-5414137360", "dns: garbage after $GENERATE range: \"\\n\" at line: 1:22"}, - {"$GENERATE 11522-3668518066406258", "dns: garbage after $GENERATE range: \"\\n\" at line: 1:38"}, - {"$GENERATE 0-200\"(;00000000000000\n$$GENERATE 0-0", "dns: garbage after $GENERATE range: \"\\\"\" at line: 1:16"}, - } - for _, tc := range tests { - t.Run(tc.in, func(t *testing.T) { - _, err := NewRR(tc.in) - if err == nil { - t.Errorf("Expecting error for crasher line %s", tc.in) - } - if tc.err != err.Error() { - t.Errorf("Expecting error %s, got %s", tc.err, err.Error()) - } - }) + // within limit, due to /2 + data = `$GENERATE 0-65536/2 dhcp A 10.0.0.1` + zp = NewZoneParser(strings.NewReader(data), ".", "test") + for _, ok := zp.Next(); ok; _, ok = zp.Next() { + } + if zp.Err() != nil { + t.Errorf("Expected nil error, got %s", zp.Err()) } } diff --git a/scan.go b/scan.go index 7da14c88f..713aaabe6 100644 --- a/scan.go +++ b/scan.go @@ -134,7 +134,7 @@ func ReadRR(r io.Reader, file string) (RR, error) { } // ParseZone reads a RFC 1035 style zonefile from r. It returns -// *Tokens on the returned channel, each consisting of either a +// Tokens on the returned channel, each consisting of either a // parsed RR and optional comment or a nil RR and an error. The // channel is closed by ParseZone when the end of r is reached. // @@ -143,7 +143,8 @@ func ReadRR(r io.Reader, file string) (RR, error) { // origin, as if the file would start with an $ORIGIN directive. // // The directives $INCLUDE, $ORIGIN, $TTL and $GENERATE are all -// supported. +// supported. Note that $GENERATE's range support up to a maximum of +// of 65535 steps. // // Basic usage pattern when reading from a string (z) containing the // zone data: @@ -203,6 +204,7 @@ func parseZone(r io.Reader, origin, file string, t chan *Token) { // // The directives $INCLUDE, $ORIGIN, $TTL and $GENERATE are all // supported. Although $INCLUDE is disabled by default. +// Note that $GENERATE's range support up to a maximum of 65535 steps. // // Basic usage pattern when reading from a string (z) containing the // zone data: