Fix parsing when RR ends in a brace

* Testcase added
This commit is contained in:
Miek Gieben 2011-12-17 11:28:54 +01:00
parent 376d58f513
commit 487e600562
2 changed files with 69 additions and 20 deletions

View File

@ -110,10 +110,11 @@ func TestParse(t *testing.T) {
"dnsex.nl. 86400 IN RRSIG SOA 8 2 86400 20110403154150 20110304154150 23334 dnsex.nl. QN6hwJQLEBqRVKmO2LgkuRSx9bkKIZxXlTVtHg5SaiN+8RCTckGtUXkQ vmZiBt3RdIWAjaabQYpEZHgvyjfy4Wwu/9RPDYnLt/qoyr4QKAdujchc m+fMDSbbcC7AN08i5D/dUWfNOHXjRJLY7t7AYB9DBt32LazIb0EU9QiW 5Cg=": "dnsex.nl.\t86400\tIN\tRRSIG\tSOA 8 2 86400 20110403154150 20110304154150 23334 dnsex.nl. QN6hwJQLEBqRVKmO2LgkuRSx9bkKIZxXlTVtHg5SaiN+8RCTckGtUXkQvmZiBt3RdIWAjaabQYpEZHgvyjfy4Wwu/9RPDYnLt/qoyr4QKAdujchcm+fMDSbbcC7AN08i5D/dUWfNOHXjRJLY7t7AYB9DBt32LazIb0EU9QiW5Cg=", "dnsex.nl. 86400 IN RRSIG SOA 8 2 86400 20110403154150 20110304154150 23334 dnsex.nl. QN6hwJQLEBqRVKmO2LgkuRSx9bkKIZxXlTVtHg5SaiN+8RCTckGtUXkQ vmZiBt3RdIWAjaabQYpEZHgvyjfy4Wwu/9RPDYnLt/qoyr4QKAdujchc m+fMDSbbcC7AN08i5D/dUWfNOHXjRJLY7t7AYB9DBt32LazIb0EU9QiW 5Cg=": "dnsex.nl.\t86400\tIN\tRRSIG\tSOA 8 2 86400 20110403154150 20110304154150 23334 dnsex.nl. QN6hwJQLEBqRVKmO2LgkuRSx9bkKIZxXlTVtHg5SaiN+8RCTckGtUXkQvmZiBt3RdIWAjaabQYpEZHgvyjfy4Wwu/9RPDYnLt/qoyr4QKAdujchcm+fMDSbbcC7AN08i5D/dUWfNOHXjRJLY7t7AYB9DBt32LazIb0EU9QiW5Cg=",
} }
for i, o := range tests { for i, o := range tests {
rr, _ := NewRR(i) rr, e:= NewRR(i)
if rr == nil { if e != nil {
t.Log("Failed to parse RR") t.Log("Failed to parse RR")
t.Fail() t.Fail()
continue
} }
if rr.String() != o { if rr.String() != o {
t.Logf("`%s' should be equal to\n`%s', but is `%s'\n", i, o, rr.String()) t.Logf("`%s' should be equal to\n`%s', but is `%s'\n", i, o, rr.String())
@ -124,13 +125,17 @@ func TestParse(t *testing.T) {
} }
} }
func TestParseBraces(t *testing.T) { func TestParseBrace(t *testing.T) {
tests := map[string]string{ tests := map[string]string{
"(miek.nl.) 3600 IN A 127.0.0.1": "miek.nl.\t3600\tIN\tA\t127.0.0.1", "(miek.nl.) 3600 IN A 127.0.0.1": "miek.nl.\t3600\tIN\tA\t127.0.0.1",
"miek.nl. (3600) IN MX (10) elektron.atoom.net.": "miek.nl.\t3600\tIN\tMX\t10 elektron.atoom.net.", "miek.nl. (3600) IN MX (10) elektron.atoom.net.": "miek.nl.\t3600\tIN\tMX\t10 elektron.atoom.net.",
`miek.nl. IN ( `miek.nl. IN (
3600 A 127.0.0.1)`: "miek.nl.\t3600\tIN\tA\t127.0.0.1", 3600 A 127.0.0.1)`: "miek.nl.\t3600\tIN\tA\t127.0.0.1",
"(miek.nl.) (A) (127.0.0.1)": "miek.nl.\t3600\tIN\tA\t127.0.0.1", "(miek.nl.) (A) (127.0.0.1)": "miek.nl.\t3600\tIN\tA\t127.0.0.1",
`(miek.nl.) (
(IN)
(AAAA)
(::1) )`: "miek.nl.\t3600\tIN\tAAAA\t::1",
`(miek.nl.) ( `(miek.nl.) (
(IN) (IN)
(AAAA) (AAAA)
@ -145,10 +150,11 @@ func TestParseBraces(t *testing.T) {
)`: "miek.nl.\t86400\tIN\tSOA\telektron.atoom.net. miekg.atoom.net. 2009032802 21600 7200 604800 3600", )`: "miek.nl.\t86400\tIN\tSOA\telektron.atoom.net. miekg.atoom.net. 2009032802 21600 7200 604800 3600",
} }
for i, o := range tests { for i, o := range tests {
rr, _ := NewRR(i) rr, e := NewRR(i)
if rr == nil { if e != nil {
t.Log("Failed to parse RR") t.Log("Failed to parse RR: " + e.Error())
t.Fail() t.Fail()
continue
} }
if rr.String() != o { if rr.String() != o {
t.Logf("`%s' should be equal to\n`%s', but is `%s'\n", i, o, rr.String()) t.Logf("`%s' should be equal to\n`%s', but is `%s'\n", i, o, rr.String())
@ -159,6 +165,34 @@ func TestParseBraces(t *testing.T) {
} }
} }
/*
func TestLexerBrace(t *testing.T) {
aaaa := `(miek.nl.) (
(IN)
(AAAA)
::1)`
// aaaa = `miek.nl. (
// IN
// AAAA
// ::1 ))`
//
var s scanner.Scanner
c := make(chan lex)
s.Init(strings.NewReader(aaaa))
s.Mode = 0
s.Whitespace = 0
go zlexer(s, c)
for l := range c {
if l.err != "" {
t.Logf("E: %s\n", l.err)
continue
}
t.Logf("%s ", l)
}
}
*/
func TestParseFailure(t *testing.T) { func TestParseFailure(t *testing.T) {
tests := []string{"miek.nl. IN A 327.0.0.1", tests := []string{"miek.nl. IN A 327.0.0.1",
"miek.nl. IN AAAA ::x", "miek.nl. IN AAAA ::x",

View File

@ -59,10 +59,11 @@ func (e *ParseError) Error() string {
} }
type lex struct { type lex struct {
token string // text of the token token string // Text of the token
value int // value: _STRING, _BLANK, etc. err string // Error text when the lexer detects it. Not used by the grammar
line int // line in the file value int // Value: _STRING, _BLANK, etc.
column int // column in the fil line int // Line in the file
column int // Column in the fil
} }
type Token struct { type Token struct {
@ -117,6 +118,12 @@ func ParseZone(r io.Reader, t chan Token) {
if _DEBUG { if _DEBUG {
fmt.Printf("[%v]\n", l) fmt.Printf("[%v]\n", l)
} }
// Lexer spotted an error already
if l.err != "" {
t <- Token{Error: &ParseError{l.err, l}}
return
}
switch st { switch st {
case _EXPECT_OWNER: case _EXPECT_OWNER:
// Set the defaults here // Set the defaults here
@ -154,7 +161,7 @@ func ParseZone(r io.Reader, t chan Token) {
case _STRING: // TTL is this case case _STRING: // TTL is this case
ttl, ok := strconv.Atoi(l.token) ttl, ok := strconv.Atoi(l.token)
if ok != nil { if ok != nil {
t <- Token{Error: &ParseError{"Not a TTL", l}} t <- Token{Error: &ParseError{"Ownername seen, not a TTL", l}}
return return
} else { } else {
h.Ttl = uint32(ttl) h.Ttl = uint32(ttl)
@ -194,7 +201,7 @@ func ParseZone(r io.Reader, t chan Token) {
case _STRING: // TTL case _STRING: // TTL
ttl, ok := strconv.Atoi(l.token) ttl, ok := strconv.Atoi(l.token)
if ok != nil { if ok != nil {
t <- Token{Error: &ParseError{"Not a TTL", l}} t <- Token{Error: &ParseError{"Class seen, not a TTL", l}}
return return
} else { } else {
h.Ttl = uint32(ttl) h.Ttl = uint32(ttl)
@ -241,17 +248,17 @@ func ParseZone(r io.Reader, t chan Token) {
func (l lex) String() string { func (l lex) String() string {
switch l.value { switch l.value {
case _STRING: case _STRING:
return l.token return "S:" + l.token + "$"
case _BLANK: case _BLANK:
return " " //"_" // seems to work, make then invisible for now return "_"
case _NEWLINE: case _NEWLINE:
return "|\n" return "|\n"
case _RRTYPE: case _RRTYPE:
return "R:" + l.token return "R:" + l.token + "$"
case _OWNER: case _OWNER:
return "O:" + l.token return "O:" + l.token + "$"
case _CLASS: case _CLASS:
return "C:" + l.token return "C:" + l.token + "$"
} }
return "" return ""
} }
@ -291,7 +298,7 @@ func zlexer(s scanner.Scanner, c chan lex) {
if !rrtype { if !rrtype {
if _, ok := Str_rr[strings.ToUpper(l.token)]; ok { if _, ok := Str_rr[strings.ToUpper(l.token)]; ok {
l.value = _RRTYPE l.value = _RRTYPE
rrtype = true // We've seen one rrtype = true
} }
if _, ok := Str_class[strings.ToUpper(l.token)]; ok { if _, ok := Str_class[strings.ToUpper(l.token)]; ok {
l.value = _CLASS l.value = _CLASS
@ -305,8 +312,8 @@ func zlexer(s scanner.Scanner, c chan lex) {
l.token = " " l.token = " "
c <- l c <- l
} }
space = true
owner = false owner = false
space = true
case ";": case ";":
if quote { if quote {
// Inside quoted text we allow ; // Inside quoted text we allow ;
@ -325,6 +332,12 @@ func zlexer(s scanner.Scanner, c chan lex) {
if str != "" { if str != "" {
l.value = _STRING l.value = _STRING
l.token = str l.token = str
if !rrtype {
if _, ok := Str_rr[strings.ToUpper(l.token)]; ok {
l.value = _RRTYPE
rrtype = true
}
}
c <- l c <- l
} }
if brace > 0 { if brace > 0 {
@ -363,7 +376,9 @@ func zlexer(s scanner.Scanner, c chan lex) {
} }
brace-- brace--
if brace < 0 { if brace < 0 {
fmt.Printf("%s\n", &ParseError{"Extra closing brace", l}) l.err = "Extra closing brace"
c <- l
return
} }
default: default:
if commt { if commt {