diff --git a/src/dns.cpp b/src/dns.cpp index abd8046..7d18e44 100644 --- a/src/dns.cpp +++ b/src/dns.cpp @@ -86,14 +86,18 @@ void DNS::skip_to_dname_end(InputMemoryStream& stream) const { break; } else { - if ((value & 0xc0)) { - // This is an offset label, skip the second byte and we're done + const uint8_t offset_discriminator = value & 0xc0; + if (offset_discriminator == 0xc0) { + // This is an offset pointer, skip the second byte and we're done stream.skip(1); break; } - else { + else if (offset_discriminator == 0) { // This is an actual label, skip its contents stream.skip(value); + } else { + // high order two bits of the first octet of a label must be either 11 or 00 + throw malformed_packet(); } } } diff --git a/tests/src/dns_test.cpp b/tests/src/dns_test.cpp index 08bda33..b2a7507 100644 --- a/tests/src/dns_test.cpp +++ b/tests/src/dns_test.cpp @@ -571,6 +571,7 @@ TEST_F(DNSTest, BadLabelSize) { // add bad length const size_t bad_label_len{0x80}; + const size_t label_offset = payload_sz; payload[payload_sz++] = bad_label_len; // fill label for incorrect length and terminate @@ -590,13 +591,18 @@ TEST_F(DNSTest, BadLabelSize) { payload + payload_sz); payload_sz += sizeof(type_class); - // SUCCEED moves from dns_decompression_pointer_out_of_bounds to malformed_packet after fix - const DNS packet(payload, payload_sz); - EXPECT_EQ(packet.questions_count(), 1); + // invalid high two bits of label first octest is detected early now try { - const auto queries{packet.queries()}; + const DNS packet(payload, payload_sz); FAIL(); - } catch (dns_decompression_pointer_out_of_bounds& oob) { + } catch (malformed_packet& mp) { + SUCCEED(); + } + + // check the other invalid value of high two bits in label size + payload[label_offset] = 0x10; + try { + const DNS packet(payload, payload_sz); FAIL(); } catch (malformed_packet& mp) { SUCCEED();