[nsec] compute NSEC.len() the same way that we would do in packDataNsec (#967)
The byte sequence, when Unpack()-ed and subsequential Pack()-ed created a panic: runtime error: slice bounds out of range github.com/miekg/dns.(*Msg).packBufferWithCompressionMap(0xc0000d4000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x100, 0x14, 0x14e80b, 0xbf2d4654d501a3c8, ...) /Users/chantra/go/src/github.com/miekg/dns/msg.go:868 +0x13a8 Confirmed that Unpacking/Repacking payload described in TestCrashNSEC did not raise a slice bound out of range panic, added unittests which failed prior to this change. ``` go test -run TestCrashNSEC --- FAIL: TestCrashNSEC (0.00s) types_test.go:135: expected length of 19, got 12 FAIL exit status 1 FAIL github.com/miekg/dns 0.067s ```
This commit is contained in:
parent
2f1ea90356
commit
37f455fa04
34
fuzz_test.go
34
fuzz_test.go
|
@ -71,3 +71,37 @@ func TestPackDataOpt(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestCrashNSEC tests generated using fuzz.go and with a message pack
|
||||
// containing the following bytes:
|
||||
// "0000\x00\x00000000\x00\x00/00000" +
|
||||
// "0\x00\v\x00#\b00000\x00\x00\x00\x00\x00\x1a000" +
|
||||
// "000\x00\x00\x00\x00\x1a000000\x00\x00\x00\x00\x1a0" +
|
||||
// "00000\x00\v00\a0000000\x00"
|
||||
// That byte sequence, when Unpack() and subsequential Pack() created a
|
||||
// panic: runtime error: slice bounds out of range
|
||||
// which was attributed to the fact that NSEC RR length computation was different (and smaller)
|
||||
// then when within packDataNsec.
|
||||
func TestCrashNSEC(t *testing.T) {
|
||||
compression := make(map[string]struct{})
|
||||
nsec := &NSEC{
|
||||
Hdr: RR_Header{
|
||||
Name:".",
|
||||
Rrtype:0x2f,
|
||||
Class:0x3030,
|
||||
Ttl:0x30303030,
|
||||
Rdlength:0xb,
|
||||
},
|
||||
NextDomain:".",
|
||||
TypeBitMap:[]uint16{
|
||||
0x2302, 0x2303, 0x230a, 0x230b,
|
||||
0x2312, 0x2313, 0x231a, 0x231b,
|
||||
0x2322, 0x2323,
|
||||
},
|
||||
}
|
||||
expectedLength := 19
|
||||
l := nsec.len(0, compression)
|
||||
if l != expectedLength {
|
||||
t.Fatalf("expected length of %d, got %d", expectedLength, l)
|
||||
}
|
||||
}
|
||||
|
|
16
types.go
16
types.go
|
@ -854,14 +854,22 @@ func (rr *NSEC) String() string {
|
|||
func (rr *NSEC) len(off int, compression map[string]struct{}) int {
|
||||
l := rr.Hdr.len(off, compression)
|
||||
l += domainNameLen(rr.NextDomain, off+l, compression, false)
|
||||
lastwindow := uint32(2 ^ 32 + 1)
|
||||
var lastwindow, lastlength uint16
|
||||
for _, t := range rr.TypeBitMap {
|
||||
window := t / 256
|
||||
if uint32(window) != lastwindow {
|
||||
l += 1 + 32
|
||||
length := (t-window*256)/8 + 1
|
||||
if window > lastwindow && lastlength != 0 { // New window, jump to the new offset
|
||||
l += int(lastlength) + 2
|
||||
lastlength = 0
|
||||
}
|
||||
lastwindow = uint32(window)
|
||||
if window < lastwindow || length < lastlength {
|
||||
// packDataNsec would return Error{err: "nsec bits out of order"} here, but
|
||||
// when computing the length, we want do be liberal.
|
||||
continue
|
||||
}
|
||||
lastwindow, lastlength = window, length
|
||||
}
|
||||
l += int(lastlength) + 2
|
||||
return l
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue