Skip to content
Open
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
18 changes: 10 additions & 8 deletions lib/resolv.rb
Original file line number Diff line number Diff line change
Expand Up @@ -626,26 +626,28 @@ def extract_resources(msg, name, typeclass) # :nodoc:
n0 = Name.create(name)
msg.each_resource {|n, ttl, data|
if n0 == n
case data
when typeclass
if resource_of_type?(data, typeclass)
yield data
yielded = true
when Resource::CNAME
elsif Resource::CNAME === data
n0 = data.name
end
end
}
return if yielded
msg.each_resource {|n, ttl, data|
if n0 == n
case data
when typeclass
yield data
end
if n0 == n && resource_of_type?(data, typeclass)
yield data
end
}
end

# Decoding makes a fresh class for each resource of an unregistered type,
# so a class from Generic.create never matches such a resource by identity.
private def resource_of_type?(data, typeclass) # :nodoc:
typeclass === data || Resource::Generic.type_class_equal?(data.class, typeclass)
end

def self.random(arg) # :nodoc:
begin
SecureRandom.random_number(arg)
Expand Down
18 changes: 18 additions & 0 deletions test/resolv/test_resource.rb
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,24 @@ def test_generic_question_equality
Resolv::DNS::Message.decode(generic_question(40001))
end

# Looking up a type that has no named class means passing a class from
# Generic.create, which is never the class a decoded answer carries.
def test_getresources_with_generic_type
generic = Resolv::DNS::Resource::Generic
message = Resolv::DNS::Message.new
message.add_answer("example.com.", 60, generic.create(40000, 60000).new("\x01\x02\x03"))
reply = Resolv::DNS::Message.decode(message.encode)
dns = Resolv::DNS.new
dns.define_singleton_method(:fetch_resource) do |_name, _typeclass, &block|
block.call(reply, Resolv::DNS::Name.create("example.com."))
end

resources = dns.getresources("example.com", generic.create(40000, 60000))
assert_equal ["\x01\x02\x03".b], resources.map(&:data)
assert_empty dns.getresources("example.com", generic.create(40001, 60000))
assert_empty dns.getresources("example.com", Resolv::DNS::Resource::IN::A)
end

private def header(qdcount, ancount)
"\x00\x00\x00\x00".b + [qdcount, ancount, 0, 0].pack('nnnn')
end
Expand Down