Author: stevehay
Date: Mon Mar 18 02:07:50 2013
New Revision: 1457619

URL: http://svn.apache.org/r1457619
Log:
Perl 5.16.3's fix for a rehash-based DoS makes it more difficult to invoke the 
workaround for the old hash collision attack, which breaks mod_perl's 
t/perl/hash_attack.t. Patch from rt.cpan.org #83916 improves the fix previously 
applied as revision 1455340. [Zefram]
Tested by the committer on Windows 7 x64 using Perls 5.8.1, 5.8.2 (VC++ 6.0), 
5.10.1, 5.12.5 (VC++ 2008), 5.14.2, 5.16.3, 5.17.5, 5.17.6 and 5.17.9 (VC++ 
2010), all against Apache 2.2.22.

Modified:
    perl/modperl/trunk/Changes
    perl/modperl/trunk/t/response/TestPerl/hash_attack.pm

Modified: perl/modperl/trunk/Changes
URL: 
http://svn.apache.org/viewvc/perl/modperl/trunk/Changes?rev=1457619&r1=1457618&r2=1457619&view=diff
==============================================================================
--- perl/modperl/trunk/Changes (original)
+++ perl/modperl/trunk/Changes Mon Mar 18 02:07:50 2013
@@ -12,6 +12,11 @@ Also refer to the Apache::Test changes l
 
 =item 2.0.8-dev
 
+Perl 5.16.3's fix for a rehash-based DoS makes it more difficult to invoke
+the workaround for the old hash collision attack, which breaks mod_perl's
+t/perl/hash_attack.t. Patch from rt.cpan.org #83916 improves the fix
+previously applied as revision 1455340. [Zefram]
+
 On Perl 5.17.6 and above, hash seeding has changed, and HvREHASH has
 disappeared. Patch to update mod_perl accordingly from rt.cpan.org #83921.
 [Zefram]

Modified: perl/modperl/trunk/t/response/TestPerl/hash_attack.pm
URL: 
http://svn.apache.org/viewvc/perl/modperl/trunk/t/response/TestPerl/hash_attack.pm?rev=1457619&r1=1457618&r2=1457619&view=diff
==============================================================================
--- perl/modperl/trunk/t/response/TestPerl/hash_attack.pm (original)
+++ perl/modperl/trunk/t/response/TestPerl/hash_attack.pm Mon Mar 18 02:07:50 
2013
@@ -30,7 +30,7 @@ use Math::BigInt;
 
 use constant MASK_U32  => 2**32;
 use constant HASH_SEED => 0; # 5.8.2: always zero before the rehashing
-use constant THRESHOLD => 14; #define HV_MAX_LENGTH_BEFORE_REHASH
+use constant THRESHOLD => 14; #define HV_MAX_LENGTH_BEFORE_(SPLIT|REHASH)
 use constant START     => "a";
 
 # create conditions which will trigger a rehash on the current stash
@@ -58,6 +58,8 @@ sub handler {
     return Apache2::Const::OK;
 }
 
+sub buckets { scalar(%{$_[0]}) =~ m#/([0-9]+)\z# ? 0+$1 : 8 }
+
 sub attack {
     my $stash = shift;
 
@@ -99,13 +101,23 @@ sub attack {
         $s++;
     }
 
-    # Now add more keys until we reach a power of 2, to force the number
-    # of buckets to be doubled (at which point the longest chain is checked).
-    $keys = scalar keys %$stash;
-    $bits = log($keys)/log(2);
-    my $limit = 2 ** ceil($bits);
-    debug "pad keys from $keys to $limit";
-    $stash->{$s++}++ while keys(%$stash) <= $limit;
+    # If the rehash hasn't been triggered yet, it's being delayed until the
+    # next bucket split.  Add keys until a split occurs.
+    unless (Internals::HvREHASH(%$stash)) {
+        debug "Will add padding keys until hash split";
+        my $old_buckets = buckets($stash);
+        while (buckets($stash) == $old_buckets) {
+            next if exists $stash->{$s};
+            $h = hash($s);
+            $c++;
+            $stash->{$s}++;
+            debug sprintf "%2d: %5s, %08x %s", $c, $s, $h, scalar(%$stash);
+            push @keys, $s;
+            debug "The hash collision attack has been successful"
+                if Internals::HvREHASH(%$stash);
+            $s++;
+        }
+    }
 
     # this verifies that the attack was mounted successfully. If
     # HvREHASH is on it is. Otherwise the sequence wasn't successful.


Reply via email to