Sophie

Sophie

distrib > Mandriva > 2007.1 > i586 > by-pkgid > eaf226f4357223790f617cae99d7ef65 > files > 3

perl-Net-DNS-0.59-1.2mdv2007.1.src.rpm

--- Net-DNS-0.59/DNS.xs	2006-09-18 21:22:12.000000000 +0200
+++ Net-DNS-0.59-fixed/DNS.xs	2007-05-25 10:15:21.000000000 +0200
@@ -57,7 +57,7 @@
 	STRLEN len;
 	u_char * buf;
 	u_char name[MAXDNAME];
-	unsigned int pos;
+	int pos;
 	
 	if (SvROK(sv_buf)) 
 		sv_buf = SvRV(sv_buf);
--- Net-DNS-0.59/lib/Net/DNS/Packet.pm	2006-09-18 21:22:12.000000000 +0200
+++ Net-DNS-0.59-fixed/lib/Net/DNS/Packet.pm	2007-05-25 10:59:41.000000000 +0200
@@ -752,7 +752,7 @@
 }
 
 sub dn_expand_PP {
-	my ($packet, $offset) = @_; # $seen from $_[2] for debugging
+	my ($packet, $pkt_offset) = @_; # $seen from $_[2] for debugging
 	my $name = "";
 	my $len;
 	my $packetlen = length $$packet;
@@ -760,37 +760,42 @@
 
 	# Debugging
 	# warn "USING PURE PERL dn_expand()\n";
-	#if ($seen->{$offset}) {
-	#	die "dn_expand: loop: offset=$offset (seen = ",
+	#if ($seen->{$pkt_offset}) {
+	#	die "dn_expand: loop: offset=$pkt_offset (seen = ",
 	#	     join(",", keys %$seen), ")\n";
 	#}
-	#$seen->{$offset} = 1;
+	#$seen->{$pkt_offset} = 1;
 
+	my $checked = 0;
+	my $hasPtr = 0;
+	my $offset = $pkt_offset;
 	while (1) {
 		return (undef, undef) if $packetlen < ($offset + 1);
+		return (undef, undef) if $checked > $packetlen; # endless Loop
 
 		$len = unpack("\@$offset C", $$packet);
 
 		if ($len == 0) {
 			$offset++;
+			$pkt_offset++ if !$hasPtr;
 			last;
 		}
 		elsif (($len & 0xc0) == 0xc0) {
+			# pointer into message for compressed strings
 			return (undef, undef)
 				if $packetlen < ($offset + $int16sz);
 
+			$pkt_offset+=$int16sz if !$hasPtr;
+			$checked += $int16sz;
 			my $ptr = unpack("\@$offset n", $$packet);
 			$ptr &= 0x3fff;
-			my($name2) = dn_expand_PP($packet, $ptr); # pass $seen for debugging
-
-			return (undef, undef) unless defined $name2;
-
-			$name .= $name2;
-			$offset += $int16sz;
-			last;
+			$offset = $ptr;
+			$hasPtr = 1;
+			next; # restart with offset from pointer
 		}
 		else {
 			$offset++;
+			$pkt_offset+=1 if !$hasPtr;
 
 			return (undef, undef)
 				if $packetlen < ($offset + $len);
@@ -800,13 +805,15 @@
 			$name .= Net::DNS::wire2presentation($elem).".";
 
 			$offset += $len;
+			$pkt_offset+= $len if !$hasPtr;
+			$checked += $len;
 		}
 	}
 
 	
 
 	$name =~ s/\.$//o;
-	return ($name, $offset);
+	return ($name, $pkt_offset);
 }
 
 =head2 sign_tsig
--- Net-DNS-0.59/MANIFEST	2006-09-18 21:22:12.000000000 +0200
+++ Net-DNS-0.59-fixed/MANIFEST	2007-05-25 11:02:11.000000000 +0200
@@ -94,5 +94,6 @@
 t/10-recurse.t
 t/11-escapedchars.t
 t/11-inet6.t
+t/12-compression.t
 t/custom.txt
 TODO
--- Net-DNS-0.59/t/12-compression.t	1970-01-01 01:00:00.000000000 +0100
+++ Net-DNS-0.59-fixed/t/12-compression.t	2007-05-25 11:16:43.000000000 +0200
@@ -0,0 +1,33 @@
+# build DNS packet which has an endless loop in compression
+# check it against XS and PP implementation of dn_expand
+# both should return (undef,undef) as a sign that the packet
+# is invalid
+
+use Test::More tests => 2;
+use strict;
+use Net::DNS;
+
+# simple query packet
+my $pkt = Net::DNS::Packet->new( 'www.example.com','a' )->data;
+
+# replace 'com' with pointer to 'example', thus causing
+# endless loop for compressed string:
+# www.example.example.example.example...
+my $pos = pack( 'C', index( $pkt,"\007example" ));
+$pkt =~s{\003com}{\xc0$pos\001x};
+
+# start at 'www'
+my $start_offset = index( $pkt,"\003www" );
+
+# fail in case the implementation is buggy and loops forever
+$SIG{ ALRM } = sub { BAIL_OUT( "endless loop?" ) };
+alarm(15);
+
+# XS implementation
+skip("No dn_expand_xs available",1) if ! $Net::DNS::HAVE_XS; 
+my ($name,$offset) = Net::DNS::Packet::dn_expand( \$pkt,$start_offset );
+ok( !defined($name) && !defined($offset), 'XS detected invalid packet' );
+
+$Net::DNS::HAVE_XS = 0;
+my ($name,$offset) = Net::DNS::Packet::dn_expand( \$pkt,$start_offset );
+ok( !defined($name) && !defined($offset), 'PP detected invalid packet' );