Skip Menu |

This queue is for tickets about the Net-DNS CPAN distribution.

Report information
The Basics
Id: 83451
Status: rejected
Priority: 0/
Queue: Net-DNS

People
Owner: Nobody in particular
Requestors: Mark.Martinec [...] ijs.si
Cc:
AdminCc:

Bug Information
Severity: Normal
Broken in: 0.72
Fixed in: (no value)



Subject: A failure or a signal during Net::DNS::Packet::decode results in missing sections in DNS packet object
The 'decode' (or the 'new') method in Net::DNS::Packet uses an eval in an attempt to capture possible failures (thrown signals) while decoding a raw packet into a Net::DNS::Packet object. In case of an error, the 'decode' (or the 'new') is supposed to return undef and provide a failure reason in $@ . Unfortunately the code in decode() returns a partially filled packet object instead of undef when eval fails, so a caller is unaware that decoding failed. A fix is trivial - attached. Background story: A typical scenario (in SpamAssassin) is when an application calls Net::DNS::Resolver::bgread() and receives a reply packet object with a missing question section (or other missing sections) - resulting in a reported warning. This elusive bug occurs a couple times per day in case of mail filtering with SpamAssassin, and has been observed for years, resulting in the following (old) comment in code: # odd. this should not happen, but clearly some DNS servers # can return something that Net::DNS interprets as having no # question section. It took a couple of days of packet capturing, saving bytes as read by recv() in bgread() and comparing them with captured packets to prove that a packet with a missing question section does not come from a faulty DNS server but is fabricated locally. Instrumenting Net::DNS::Packet with debugging finally revealed that on a rare occasion an alarm signal occurs sometime during decoding of a packet and causes exit from eval (without invalidating the partially decoded packet object), so all later sections remain undecoded, i.e. resulting in an apparently valid packet object but with a missing answer section, or a missing question + answer (and later) sections. I would appreciate if the attached patch would be accepted.
Subject: Net-DNS-Packet.patch
--- Net/DNS/Packet.pm.ori 2012-12-28 14:22:41.000000000 +0100 +++ Net/DNS/Packet.pm 2013-02-15 17:11:02.000000000 +0100 @@ -151,6 +151,9 @@ ( $record, $offset ) = decode Net::DNS::RR( $data, $offset, $hash ); CORE::push( @{$self->{additional}}, $record ); } + 1; + } or do { + undef $self; }; if ( $debug && $self ) {
From: rwfranks [...] acm.org
On Tue Feb 19 15:13:12 2013, Mark.Martinec@ijs.si wrote: Show quoted text
> The 'decode' (or the 'new') method in Net::DNS::Packet uses an > eval in an attempt to capture possible failures (thrown signals) > while decoding a raw packet into a Net::DNS::Packet object.
The eval{} is there to capture any exception raised *inside* the decoders and handle them in a uniform way. What it does *not* do is to protect the code from signals, which can interrupt the code anywhere at all. SpamAssassin calls alarm(), in three separate packages, which will all generate the (singular) ALRM signal. *You* are responsible for managing the consequences of all this complexity. In particular, you need to be certain whose code you are killing with the die in the alarm handlers, and whose eval{} block will catch the resulting exception. Show quoted text
> Unfortunately the code in decode() returns a partially filled > packet object instead of undef when eval fails, so a caller > is unaware that decoding failed. A fix is trivial - attached.
This is not an unfortunate oversight, it is a design feature. Some applications need to know about damaged and incomplete packets, so Net::DNS needs to represent them. The messy code at the end of decode() makes that happen.