mirror of
https://github.com/miekg/dns.git
synced 2025-08-10 11:36:58 +02:00
Updated code to handle escapes in TXT RDATA
Added test demonstrating error in TXT parsing. Fixed lexing process and slightly updated conversion back to strings. See #126 for details.
This commit is contained in:
parent
b6da65c4b0
commit
ae7d973e40
@ -137,6 +137,39 @@ func TestDomainNameAndTXTEscapes(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestTXTEscapeParsing(t *testing.T) {
|
||||||
|
test := [][]string{
|
||||||
|
{`";"`, `";"`},
|
||||||
|
{`\;`, `";"`},
|
||||||
|
{`"\t"`, `"\t"`},
|
||||||
|
{`"\r"`, `"\r"`},
|
||||||
|
{`"\ "`, `" "`},
|
||||||
|
{`"\;"`, `";"`},
|
||||||
|
{`"\;\""`, `";\""`},
|
||||||
|
{`"\(a\)"`, `"(a)"`},
|
||||||
|
{`"\(a)"`, `"(a)"`},
|
||||||
|
{`"(a\)"`, `"(a)"`},
|
||||||
|
{`"(a)"`, `"(a)"`},
|
||||||
|
{`"\048"`, `"0"`},
|
||||||
|
{`"\` + "\n" + `"`, `"\n"`},
|
||||||
|
{`"\` + "\r" + `"`, `"\r"`},
|
||||||
|
{`"\` + "\x11" + `"`, `"\017"`},
|
||||||
|
{`"\'"`, `"'"`},
|
||||||
|
}
|
||||||
|
for _, s := range test {
|
||||||
|
rr, err := NewRR(fmt.Sprintf("example.com. IN TXT %v", s[0]))
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Could not parse %v TXT: %s", s[0], err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
txt := sprintTxt(rr.(*TXT).Txt)
|
||||||
|
if txt != s[1] {
|
||||||
|
t.Errorf("Mismatch after parsing `%v` TXT record: `%v` != `%v`", s[0], txt, s[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func GenerateDomain(r *rand.Rand, size int) []byte {
|
func GenerateDomain(r *rand.Rand, size int) []byte {
|
||||||
dnLen := size % 70 // artificially limit size so there's less to intrepret if a failure occurs
|
dnLen := size % 70 // artificially limit size so there's less to intrepret if a failure occurs
|
||||||
var dn []byte
|
var dn []byte
|
||||||
|
25
types.go
25
types.go
@ -482,24 +482,25 @@ func sprintTxt(txt []string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func appendDomainNameByte(s []byte, b byte) []byte {
|
func appendDomainNameByte(s []byte, b byte) []byte {
|
||||||
if b == '.' || b == '(' || b == ')' || b == ';' || b == ' ' || b == '\'' || b == '@' {
|
switch b {
|
||||||
|
case '.', ' ', '\'', '@', ';', '(', ')': // additional chars to escape
|
||||||
return append(s, '\\', b)
|
return append(s, '\\', b)
|
||||||
}
|
}
|
||||||
return appendTXTStringByte(s, b)
|
return appendTXTStringByte(s, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
func appendTXTStringByte(s []byte, b byte) []byte {
|
func appendTXTStringByte(s []byte, b byte) []byte {
|
||||||
if b == '"' {
|
switch b {
|
||||||
return append(s, `\"`...)
|
case '\t':
|
||||||
} else if b == '\\' {
|
return append(s, '\\', 't')
|
||||||
return append(s, `\\`...)
|
case '\r':
|
||||||
} else if b == '\t' {
|
return append(s, '\\', 'r')
|
||||||
return append(s, `\t`...)
|
case '\n':
|
||||||
} else if b == '\r' {
|
return append(s, '\\', 'n')
|
||||||
return append(s, `\r`...)
|
case '"', '\\':
|
||||||
} else if b == '\n' {
|
return append(s, '\\', b)
|
||||||
return append(s, `\n`...)
|
}
|
||||||
} else if b < ' ' || b > '~' {
|
if b < ' ' || b > '~' {
|
||||||
return append(s, fmt.Sprintf("\\%03d", b)...)
|
return append(s, fmt.Sprintf("\\%03d", b)...)
|
||||||
}
|
}
|
||||||
return append(s, b)
|
return append(s, b)
|
||||||
|
39
zscan.go
39
zscan.go
@ -525,7 +525,6 @@ func zlexer(s *scan, c chan lex) {
|
|||||||
stri++
|
stri++
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
escape = false
|
|
||||||
if commt {
|
if commt {
|
||||||
com[comi] = x
|
com[comi] = x
|
||||||
comi++
|
comi++
|
||||||
@ -607,14 +606,14 @@ func zlexer(s *scan, c chan lex) {
|
|||||||
owner = false
|
owner = false
|
||||||
space = true
|
space = true
|
||||||
case ';':
|
case ';':
|
||||||
if quote {
|
if escape {
|
||||||
// Inside quotes this is legal
|
escape = false
|
||||||
str[stri] = x
|
str[stri] = x
|
||||||
stri++
|
stri++
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if escape {
|
if quote {
|
||||||
escape = false
|
// Inside quotes this is legal
|
||||||
str[stri] = x
|
str[stri] = x
|
||||||
stri++
|
stri++
|
||||||
break
|
break
|
||||||
@ -631,9 +630,15 @@ func zlexer(s *scan, c chan lex) {
|
|||||||
com[comi] = ';'
|
com[comi] = ';'
|
||||||
comi++
|
comi++
|
||||||
case '\r':
|
case '\r':
|
||||||
// discard
|
escape = false
|
||||||
// this means it can also not be used as rdata
|
if quote {
|
||||||
|
str[stri] = x
|
||||||
|
stri++
|
||||||
|
break
|
||||||
|
}
|
||||||
|
// discard if outside of quotes
|
||||||
case '\n':
|
case '\n':
|
||||||
|
escape = false
|
||||||
// Escaped newline
|
// Escaped newline
|
||||||
if quote {
|
if quote {
|
||||||
str[stri] = x
|
str[stri] = x
|
||||||
@ -641,7 +646,6 @@ func zlexer(s *scan, c chan lex) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
// inside quotes this is legal
|
// inside quotes this is legal
|
||||||
escape = false
|
|
||||||
if commt {
|
if commt {
|
||||||
// Reset a comment
|
// Reset a comment
|
||||||
commt = false
|
commt = false
|
||||||
@ -696,18 +700,20 @@ func zlexer(s *scan, c chan lex) {
|
|||||||
comi = 0
|
comi = 0
|
||||||
}
|
}
|
||||||
case '\\':
|
case '\\':
|
||||||
// quote?
|
// comments do not get escaped chars, everything is copied
|
||||||
if commt {
|
if commt {
|
||||||
com[comi] = x
|
com[comi] = x
|
||||||
comi++
|
comi++
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
// something already escaped must be in string
|
||||||
if escape {
|
if escape {
|
||||||
str[stri] = x
|
str[stri] = x
|
||||||
stri++
|
stri++
|
||||||
escape = false
|
escape = false
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
// something escaped outside of string gets added to string
|
||||||
str[stri] = x
|
str[stri] = x
|
||||||
stri++
|
stri++
|
||||||
escape = true
|
escape = true
|
||||||
@ -729,21 +735,19 @@ func zlexer(s *scan, c chan lex) {
|
|||||||
l.value = _STRING
|
l.value = _STRING
|
||||||
l.token = string(str[:stri])
|
l.token = string(str[:stri])
|
||||||
l.length = stri
|
l.length = stri
|
||||||
|
|
||||||
debug.Printf("[%+v]", l.token)
|
debug.Printf("[%+v]", l.token)
|
||||||
c <- l
|
c <- l
|
||||||
stri = 0
|
stri = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// send quote itself as separate token
|
||||||
l.value = _QUOTE
|
l.value = _QUOTE
|
||||||
l.token = "\""
|
l.token = "\""
|
||||||
l.length = 1
|
l.length = 1
|
||||||
c <- l
|
c <- l
|
||||||
quote = !quote
|
quote = !quote
|
||||||
case '(', ')':
|
case '(', ')':
|
||||||
if quote {
|
|
||||||
str[stri] = x
|
|
||||||
stri++
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if commt {
|
if commt {
|
||||||
com[comi] = x
|
com[comi] = x
|
||||||
comi++
|
comi++
|
||||||
@ -755,6 +759,11 @@ func zlexer(s *scan, c chan lex) {
|
|||||||
escape = false
|
escape = false
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
if quote {
|
||||||
|
str[stri] = x
|
||||||
|
stri++
|
||||||
|
break
|
||||||
|
}
|
||||||
switch x {
|
switch x {
|
||||||
case ')':
|
case ')':
|
||||||
brace--
|
brace--
|
||||||
@ -769,12 +778,12 @@ func zlexer(s *scan, c chan lex) {
|
|||||||
brace++
|
brace++
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
escape = false
|
||||||
if commt {
|
if commt {
|
||||||
com[comi] = x
|
com[comi] = x
|
||||||
comi++
|
comi++
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
escape = false
|
|
||||||
str[stri] = x
|
str[stri] = x
|
||||||
stri++
|
stri++
|
||||||
space = false
|
space = false
|
||||||
|
Loading…
Reference in New Issue
Block a user