Skip Menu |

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

Report information
The Basics
Id: 40249
Status: resolved
Priority: 0/
Queue: Net-DNS

People
Owner: Nobody in particular
Requestors: brett.watson [...] gmail.com
Cc:
AdminCc:

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



Subject: Possible use of freed data by Net::DNS::Packet->new(\$data)
Date: Wed, 22 Oct 2008 16:53:13 +1100
To: bug-Net-DNS [...] rt.cpan.org
From: "Brett Watson" <brett.watson [...] gmail.com>
This is an issue with Net::DNS 0.63 on Perl 5.8.8 as found in Xubuntu 8.04 (hardy). In tracking down a difficult-to-diagnose bug, I think I've pinned the blame on XS code accessed in Net::DNS::Packet->new(). I'm now working around this bug, so I have no patch to offer, but here are the details of what I found to aid the maintainers in finding it. The situation was that I have written two wrapper functions: one for DNS query via UDP, the other via TCP. The TCP one was failing for some reason, with the following results. Use of uninitialized value in subroutine entry at /usr/lib/perl5/Net/DNS/Packet.pm line 588. Exception: corrupt or incomplete data at /usr/lib/perl5/Net/DNS/RR.pm line 510. caught at -e line 1 This error was being triggered when I called the "print" method on a packet generated with the following code. # ...snipped code that reads $data... $packet = Net::DNS::Packet->new(\$data); undef($data); In an attempt to diagnose this, I added the "debug" parameter to the new() call (i.e. $packet = Net::DNS::Packet->new(\$data, 1)), and the problem immediately vanished, which was odd. I then determined that my working UDP code continued to work (and my TCP code continued to fail) when the data being passed to new() was *exactly the same*. This was completely baffling. My suspicion subsequently fell on the following undef() command, which was being used to free up the data buffer explicitly. I was not doing this in my UDP code, but allowing the buffer to be freed when it went out of scope. Removing this undef() cleared the problem. Hypothesis: there has been some kind of oversight in reference counting in XS code. My undef($data) is reducing the reference count to zero, but Net::DNS still has a pointer to the data somewhere. The complaint about "corrupt or incomplete data" is happening because the data is in partly-overwritten freed memory, which should not be referenced.
On Wed Oct 22 01:53:46 2008, brett.watson@gmail.com wrote: Show quoted text
> This is an issue with Net::DNS 0.63 on Perl 5.8.8 as found in Xubuntu 8.04 > (hardy). > > In tracking down a difficult-to-diagnose bug, I think I've pinned the blame > on XS code accessed in Net::DNS::Packet->new(). I'm now working around this > bug, so I have no patch to offer, but here are the details of what I found > to aid the maintainers in finding it. > > The situation was that I have written two wrapper functions: one for DNS > query via UDP, the other via TCP. The TCP one was failing for some reason, > with the following results. > > Use of uninitialized value in subroutine entry at > /usr/lib/perl5/Net/DNS/Packet.pm line 588. > Exception: corrupt or incomplete data at /usr/lib/perl5/Net/DNS/RR.pm line > 510. > caught at -e line 1 > > This error was being triggered when I called the "print" method on a packet > generated with the following code. > > # ...snipped code that reads $data... > $packet = Net::DNS::Packet->new(\$data); > undef($data); > > In an attempt to diagnose this, I added the "debug" parameter to the new() > call (i.e. $packet = Net::DNS::Packet->new(\$data, 1)), and the problem > immediately vanished, which was odd. I then determined that my working UDP > code continued to work (and my TCP code continued to fail) when the data > being passed to new() was *exactly the same*. This was completely baffling. > > My suspicion subsequently fell on the following undef() command, which was > being used to free up the data buffer explicitly. I was not doing this in my > UDP code, but allowing the buffer to be freed when it went out of scope. > Removing this undef() cleared the problem. > > Hypothesis: there has been some kind of oversight in reference counting in > XS code. My undef($data) is reducing the reference count to zero, but > Net::DNS still has a pointer to the data somewhere. The complaint about > "corrupt or incomplete data" is happening because the data is in > partly-overwritten freed memory, which should not be referenced.
Fortunatelly this is not as deep as it seems. What happens (since release 0.63) is that for efficiency reasons the packet is only parsed when the sections are needed. So a reference to the data is stored in a buffer inside the packet instance and only used when you want to actually access the answer, or other sections in the packet. A workaround is to call $packet->answer; $packet->additional; $packet->authority; shortly before the undef. I've made a note in the Changes file to document this: NOTE rt.cpan.org # 40249 Release 0.62 introduced a feature to parse data inside a packet only when needed. This can the following to happen: Eception: corrupt or incomplete data at /usr/lib/perl5/Net/DNS/RR.pm line 510. caught at -e line 1 This may happen when you have undefined your packet data before all the sections have been fully parsed. Such as in: $packet = Net::DNS::Packet->new(\$data); undef($data); The workaround is to force parcing by calling the methods that parse the data. e.g. $packet = Net::DNS::Packet->new(\$data); $packet->answer; $packet->additional; $packet->authority; undef ($data)