Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions lib/resolv.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1845,6 +1845,9 @@ def get_labels
# size counts the encoded form, so it starts at 1 for the root
# label's terminating zero octet. [RFC 1035 3.1]
size = 1
# A pointer chain decodes to few or no labels, so the 255-octet cap
# never bounds its work; cap the pointers followed per name too.
pointers = 0
while true
raise DecodeError.new("limit exceeded") if @limit <= @index
case @data.getbyte(@index)
Expand All @@ -1855,6 +1858,8 @@ def get_labels
end
return d
when 192..255
pointers += 1
raise DecodeError.new("too many compression pointers") if pointers > 128
idx = self.get_unpack('n')[0] & 0x3fff
if prev_index <= idx
raise DecodeError.new("non-backward name pointer")
Expand Down
16 changes: 16 additions & 0 deletions test/resolv/test_dns.rb
Original file line number Diff line number Diff line change
Expand Up @@ -670,6 +670,22 @@ def test_too_long_address
end
end

# A pointer chain hidden in a carrier RR's opaque RDATA, with a second RR's
# name pointing at its top, decodes to no labels but follows many pointers.
def test_too_many_compression_pointers
hops = 130
header = [0, 0, 0, 2, 0, 0].pack("n6")
carrier = "\x00" + [60000, 1, 0].pack("nnN")
chain = +"\x00"; prev = 23
hops.times { |j| chain << [0xC000 | prev].pack("n"); prev = 24 + 2 * j }
carrier << [chain.bytesize].pack("n") << chain
top = 24 + 2 * (hops - 1)
victim = [0xC000 | top].pack("n") + [60000, 1, 0, 0].pack("nnNn")
assert_raise_with_message(Resolv::DNS::DecodeError, /too many compression pointers/) do
Resolv::DNS::Message.decode(header + carrier + victim)
end
end

# A DNS label is limited to 63 octets. [RFC 1035 2.3.4] Writing a longer label
# through the label path must raise instead of overflowing the length octet.
def test_put_label_rejects_label_over_63_octets
Expand Down
Loading