diff --git a/src/lib/dns/rdata/generic/nsec3_50.cc b/src/lib/dns/rdata/generic/nsec3_50.cc index 47800de65e..39765ab0d8 100644 --- a/src/lib/dns/rdata/generic/nsec3_50.cc +++ b/src/lib/dns/rdata/generic/nsec3_50.cc @@ -163,8 +163,8 @@ NSEC3::NSEC3(InputBuffer& buffer, size_t rdata_len) { const uint8_t nextlen = buffer.readUint8(); --rdata_len; - if (rdata_len <= nextlen) { - isc_throw(DNSMessageFORMERR, "NSEC3 hash length is too large: " << + if (nextlen == 0 || rdata_len <= nextlen) { + isc_throw(DNSMessageFORMERR, "NSEC3 invalid hash length: " << static_cast(nextlen)); } diff --git a/src/lib/dns/tests/rdata_nsec3_unittest.cc b/src/lib/dns/tests/rdata_nsec3_unittest.cc index 0099e5d966..9a8b183c33 100644 --- a/src/lib/dns/tests/rdata_nsec3_unittest.cc +++ b/src/lib/dns/tests/rdata_nsec3_unittest.cc @@ -153,6 +153,11 @@ TEST_F(Rdata_NSEC3_Test, createFromWire) { "rdata_nsec3_fromWire12.wire"), DNSMessageFORMERR); + // empty hash. invalid. + EXPECT_THROW(rdataFactoryFromFile(RRType::NSEC3(), RRClass::IN(), + "rdata_nsec3_fromWire14.wire"), + DNSMessageFORMERR); + // // Short buffer cases. The data is valid NSEC3 RDATA, but the buffer // is trimmed at the end. All cases should result in an exception from diff --git a/src/lib/dns/tests/testdata/Makefile.am b/src/lib/dns/tests/testdata/Makefile.am index 9bcdf2b793..5be679602b 100644 --- a/src/lib/dns/tests/testdata/Makefile.am +++ b/src/lib/dns/tests/testdata/Makefile.am @@ -14,6 +14,7 @@ BUILT_SOURCES += rdata_nsec3_fromWire6.wire rdata_nsec3_fromWire7.wire BUILT_SOURCES += rdata_nsec3_fromWire8.wire rdata_nsec3_fromWire9.wire BUILT_SOURCES += rdata_nsec3_fromWire10.wire rdata_nsec3_fromWire11.wire BUILT_SOURCES += rdata_nsec3_fromWire12.wire rdata_nsec3_fromWire13.wire +BUILT_SOURCES += rdata_nsec3_fromWire14.wire BUILT_SOURCES += rdata_rrsig_fromWire2.wire BUILT_SOURCES += rdata_soa_toWireUncompressed.wire BUILT_SOURCES += rdata_txt_fromWire2.wire rdata_txt_fromWire3.wire @@ -62,6 +63,7 @@ EXTRA_DIST += rdata_nsec3_fromWire6.spec rdata_nsec3_fromWire7.spec EXTRA_DIST += rdata_nsec3_fromWire8.spec rdata_nsec3_fromWire9.spec EXTRA_DIST += rdata_nsec3_fromWire10.spec rdata_nsec3_fromWire11.spec EXTRA_DIST += rdata_nsec3_fromWire12.spec rdata_nsec3_fromWire13.spec +EXTRA_DIST += rdata_nsec3_fromWire14.spec EXTRA_DIST += rdata_opt_fromWire rdata_rrsig_fromWire1 EXTRA_DIST += rdata_rrsig_fromWire2.spec EXTRA_DIST += rdata_soa_fromWire rdata_soa_toWireUncompressed.spec diff --git a/src/lib/dns/tests/testdata/gen-wiredata.py.in b/src/lib/dns/tests/testdata/gen-wiredata.py.in index 4af2838f6a..379d748be3 100755 --- a/src/lib/dns/tests/testdata/gen-wiredata.py.in +++ b/src/lib/dns/tests/testdata/gen-wiredata.py.in @@ -361,7 +361,9 @@ class NSEC3(NSECBASE): ' ' if len(self.salt) > 0 else '', encode_string(self.salt))) f.write("# Hash Len=%d, Hash='%s'\n" % (self.hashlen, self.hash)) - f.write('%02x %s\n' % (self.hashlen, encode_string(self.hash))) + f.write('%02x%s%s\n' % (self.hashlen, + ' ' if len(self.hash) > 0 else '', + encode_string(self.hash))) class RRSIG: rdlen = -1 # auto-calculate diff --git a/src/lib/dns/tests/testdata/rdata_nsec3_fromWire14.spec b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire14.spec new file mode 100644 index 0000000000..a0550d5e6f --- /dev/null +++ b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire14.spec @@ -0,0 +1,9 @@ +# +# An invalid NSEC3 RDATA: empty hash +# + +[custom] +sections: nsec3 +[nsec3] +hashlen: 0 +hash: ''