-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Description
While working on a patch for Consul hashicorp/consul#3948 I found a bug in this library because when compression is activated, msg.Len() is not the same as len(msg.Pack())
Since Consul was using a very old version of the library, I thought it had been fixed, so Consul upgraded its version to 1.0.4 after this issue hashicorp/consul#3977
But still, the issue still exists with version 1.0.4.
I created a test case that shows it into action: (to paste into dns_test.go
):
func TestMsgCompressLengthLargeRecords(t *testing.T) {
msg := new(Msg)
msg.Compress = true
msg.SetQuestion(Fqdn("my.service.acme."), TypeSRV)
numEntries := 0
for j := 0; j < 10; j++ {
for i := 0; i < 255; i++ {
numEntries++
target := fmt.Sprintf("host-redis-%d-%d.test.acme.com.node.dc1.consul.", j, i)
msg.Answer = append(msg.Answer, &SRV{Hdr: RR_Header{Name: "redis.service.consul.", Rrtype: 0x21, Class: 0x1, Ttl: 0x3c}, Port: 0x4c57, Target: target})
msg.Extra = append(msg.Extra, &CNAME{Hdr: RR_Header{Name: target, Rrtype: 0x1, Class: 0x1, Ttl: 0x3c}, Target: fmt.Sprintf("fx.168.%d.%d.", j, i)})
predicted := msg.Len()
buf, err := msg.Pack()
if err != nil {
t.Error(err)
}
if predicted != len(buf) {
t.Errorf("predicted compressed length is wrong: predicted %s (len=%d) %d, actual %d with %d entries",
msg.Question[0].Name, len(msg.Answer), predicted, len(buf), numEntries)
}
}
}
}
This test fails this way:
go test github.com/miekg/dns -run ^TestMsgCompressLengthLargeRecords$
--- FAIL: TestMsgCompressLengthLargeRecords (9.82s)
dns_test.go:309: predicted compressed length is wrong: predicted my.service.acme. (len=250) 22833, actual 22850 with 250 entries
dns_test.go:309: predicted compressed length is wrong: predicted my.service.acme. (len=251) 22925, actual 22959 with 251 entries
dns_test.go:309: predicted compressed length is wrong: predicted my.service.acme. (len=252) 23017, actual 23068 with 252 entries
dns_test.go:309: predicted compressed length is wrong: predicted my.service.acme. (len=253) 23109, actual 23177 with 253 entries
dns_test.go:309: predicted compressed length is wrong: predicted my.service.acme. (len=254) 23201, actual 23286 with 254 entries
dns_test.go:309: predicted compressed length is wrong: predicted my.service.acme. (len=255) 23293, actual 23395 with 255 entries
Which is exactly what I did see while patching Consul.
In the patch I am working on, since Consul might create very large SRV records (several thousands), in order to have a good response, we are trying to fill DNS at its maximum, so we compute the size compressed, see if it is more than 64K, if not send the response, otherwise, remove records and retry.
So, basically, the size uncompressed is supposed to be far bigger than 64k while I am trying to improve the patch to send 64k MAX compressed.
Note that this test passes without any issue with compression disabled.