Fix Rdlength related parsing bug in RFC3597 records (#1214)
* Set Rdlength in fromRFC3597 This was a bug found by oss-fuzz. My bad (#1211). * Limit maximum length of Rdata in (*RFC3597).parse RDATA must be a 16-bit unsigned integer. * Validate Rdlength and off in UnpackRRWithHeader * Revert "Validate Rdlength and off in UnpackRRWithHeader" This reverts commit 2f6a8811b944b100af7605e53a6fb164944a6d65. * Use hex.DecodedLen in (*RFC3597).fromRFC3597 While this isn't done elsewhere, it is clearer and more obvious.
This commit is contained in:
parent
ba2d042a57
commit
e6df8867af
9
dns.go
9
dns.go
@ -134,9 +134,14 @@ func (rr *RFC3597) ToRFC3597(r RR) error {
|
||||
|
||||
// fromRFC3597 converts an unknown RR representation from RFC 3597 to the known RR type.
|
||||
func (rr *RFC3597) fromRFC3597(r RR) error {
|
||||
*r.Header() = rr.Hdr
|
||||
hdr := r.Header()
|
||||
*hdr = rr.Hdr
|
||||
|
||||
if len(rr.Rdata) == 0 {
|
||||
// Can't overflow uint16 as the length of Rdata is validated in (*RFC3597).parse.
|
||||
// We can only get here when rr was constructed with that method.
|
||||
hdr.Rdlength = uint16(hex.DecodedLen(len(rr.Rdata)))
|
||||
|
||||
if noRdata(*hdr) {
|
||||
// Dynamic update.
|
||||
return nil
|
||||
}
|
||||
|
@ -1387,7 +1387,7 @@ func (rr *RFC3597) parse(c *zlexer, o string) *ParseError {
|
||||
|
||||
c.Next() // zBlank
|
||||
l, _ = c.Next()
|
||||
rdlength, e := strconv.Atoi(l.token)
|
||||
rdlength, e := strconv.ParseUint(l.token, 10, 16)
|
||||
if e != nil || l.err {
|
||||
return &ParseError{"", "bad RFC3597 Rdata ", l}
|
||||
}
|
||||
@ -1396,7 +1396,7 @@ func (rr *RFC3597) parse(c *zlexer, o string) *ParseError {
|
||||
if e1 != nil {
|
||||
return e1
|
||||
}
|
||||
if rdlength*2 != len(s) {
|
||||
if int(rdlength)*2 != len(s) {
|
||||
return &ParseError{"", "bad RFC3597 Rdata", l}
|
||||
}
|
||||
rr.Rdata = s
|
||||
|
19
scan_test.go
19
scan_test.go
@ -229,8 +229,23 @@ example.com. 60 PX (
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseRFC3597InvalidLength(t *testing.T) {
|
||||
// We need to space separate the 00s otherwise it will exceed the maximum token size
|
||||
// of the zone lexer.
|
||||
_, err := NewRR("example. 3600 CLASS1 TYPE1 \\# 65536 " + strings.Repeat("00 ", 65536))
|
||||
if err == nil {
|
||||
t.Error("should not have parsed excessively long RFC3579 record")
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseKnownRRAsRFC3597(t *testing.T) {
|
||||
t.Run("with RDATA", func(t *testing.T) {
|
||||
// This was found by oss-fuzz.
|
||||
_, err := NewRR("example. 3600 tYpe44 \\# 03 75 0100")
|
||||
if err != nil {
|
||||
t.Errorf("failed to parse RFC3579 format: %v", err)
|
||||
}
|
||||
|
||||
rr, err := NewRR("example. 3600 CLASS1 TYPE1 \\# 4 7f000001")
|
||||
if err != nil {
|
||||
t.Fatalf("failed to parse RFC3579 format: %v", err)
|
||||
@ -247,7 +262,7 @@ func TestParseKnownRRAsRFC3597(t *testing.T) {
|
||||
|
||||
localhost := net.IPv4(127, 0, 0, 1)
|
||||
if !a.A.Equal(localhost) {
|
||||
t.Fatalf("expected A with IP %v, but got %v", localhost, a.A)
|
||||
t.Errorf("expected A with IP %v, but got %v", localhost, a.A)
|
||||
}
|
||||
})
|
||||
t.Run("without RDATA", func(t *testing.T) {
|
||||
@ -266,7 +281,7 @@ func TestParseKnownRRAsRFC3597(t *testing.T) {
|
||||
}
|
||||
|
||||
if len(a.A) != 0 {
|
||||
t.Fatalf("expected A with empty IP, but got %v", a.A)
|
||||
t.Errorf("expected A with empty IP, but got %v", a.A)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user