[SCM] 100% pure-Java implementation of Ruby branch, master, updated. debian/1.5.6-4-3-g8d20c64

Martin Quinson martin.quinson at loria.fr
Tue Dec 11 20:11:06 UTC 2012


The following commit has been merged in the master branch:
commit 7768f59d2bb281b2fa65241b68d34407ff187ee7
Author: Martin Quinson <martin.quinson at loria.fr>
Date:   Tue Dec 11 20:54:05 2012 +0100

    adapt my patch by using PerlHash instead of SipHash, as it is done upstream

diff --git a/debian/changelog b/debian/changelog
index 3bf73b9..0255bd8 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,8 +1,9 @@
 jruby (1.5.6-5) UNRELEASED; urgency=low
 
   * Team upload.
-  * Add patch for CVE-2012-5370: Use SipHash instead of MurmurHash
+  * Add patch for CVE-2012-5370: Use PerlHash instead of MurmurHash
     (that is vulnerable to DoS attacks). (Closes: #694694)
+    [Patch adapted from 5e4aab28 upstream]
 
  -- Martin Quinson <mquinson at debian.org>  Tue, 11 Dec 2012 00:07:45 +0100
 
diff --git a/debian/patches/0009-CVE-2012-5370.patch b/debian/patches/0009-CVE-2012-5370.patch
index 677a058..6f725f8 100644
--- a/debian/patches/0009-CVE-2012-5370.patch
+++ b/debian/patches/0009-CVE-2012-5370.patch
@@ -5,11 +5,14 @@ changing hash table operations complexity from an expected/average
 O(n) to the worst case O(n^2). Reporters were able to find colliding
 strings efficiently using equivalent substrings.
 
-Use SipHash instead, as it was done in the C implementation of Ruby.
+Use PerlHash instead, as it was done upstream (see commit
+5e4aab28b26fd127112b76fabfac9a33b64caf77 of git://jruby.org/jruby.git)
+instead of the SipHash that is used in the C implementation of Ruby,
+for performance reasons.
 
-Index: jruby-1.5.6/src/org/jruby/util/MurmurHash.java
+Index: jruby/src/org/jruby/util/MurmurHash.java
 ===================================================================
---- jruby-1.5.6.orig/src/org/jruby/util/MurmurHash.java	2012-12-10 23:38:21.827577622 +0100
+--- jruby.orig/src/org/jruby/util/MurmurHash.java	2012-12-11 20:29:23.666433052 +0100
 +++ /dev/null	1970-01-01 00:00:00.000000000 +0000
 @@ -1,62 +0,0 @@
 -package org.jruby.util;
@@ -74,16 +77,16 @@ Index: jruby-1.5.6/src/org/jruby/util/MurmurHash.java
 -        return h;
 -    }
 -}
-Index: jruby-1.5.6/src/org/jruby/RubyString.java
+Index: jruby/src/org/jruby/RubyString.java
 ===================================================================
---- jruby-1.5.6.orig/src/org/jruby/RubyString.java	2012-12-10 23:38:21.827577622 +0100
-+++ jruby-1.5.6/src/org/jruby/RubyString.java	2012-12-10 23:43:27.737909143 +0100
+--- jruby.orig/src/org/jruby/RubyString.java	2012-12-11 20:29:23.650433034 +0100
++++ jruby/src/org/jruby/RubyString.java	2012-12-11 20:49:48.895686092 +0100
 @@ -91,7 +91,7 @@
  import org.jruby.runtime.marshal.UnmarshalStream;
  import org.jruby.util.ByteList;
  import org.jruby.util.ConvertBytes;
 -import org.jruby.util.MurmurHash;
-+import org.jruby.util.SipHash;
++import org.jruby.util.PerlHash;
  import org.jruby.util.Numeric;
  import org.jruby.util.Pack;
  import org.jruby.util.Sprintf;
@@ -92,234 +95,36 @@ Index: jruby-1.5.6/src/org/jruby/RubyString.java
  
      private int strHashCode(Ruby runtime) {
 -        int hash = MurmurHash.hash32(value.getUnsafeBytes(), value.getBegin(), value.getRealSize(), runtime.getHashSeed());
-+        int hash = SipHash.hash32(value.getUnsafeBytes(), value.getBegin(), value.getRealSize(), runtime.getHashSeed());
++        int hash = PerlHash.hash32(runtime.getHashSeed(), value.getUnsafeBytes(), value.getBegin(), value.getRealSize());
          if (runtime.is1_9()) {
              hash ^= (value.getEncoding().isAsciiCompatible() && scanForCodeRange() == CR_7BIT ? 0 : value.getEncoding().getIndex());
          }
-Index: jruby-1.5.6/src/org/jruby/util/SipHash.java
+Index: jruby/src/org/jruby/util/PerlHash.java
 ===================================================================
 --- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ jruby-1.5.6/src/org/jruby/util/SipHash.java	2012-12-10 23:51:14.867456445 +0100
-@@ -0,0 +1,190 @@
++++ jruby/src/org/jruby/util/PerlHash.java	2012-12-11 20:42:32.429215037 +0100
+@@ -0,0 +1,24 @@
 +package org.jruby.util;
 +
 +/**
-+ * Original author: <a href="mailto:Martin.Bosslet at googlemail.com">Martin Bosslet</a>
-+ * Original license: 
-+ *   Copyright (c) 2012 Martin Boßlet
-+ *   
-+ *   Permission is hereby granted, free of charge, to any person obtaining
-+ *   a copy of this software and associated documentation files (the
-+ *   "Software"), to deal in the Software without restriction, including
-+ *   without limitation the rights to use, copy, modify, merge, publish,
-+ *   distribute, sublicense, and/or sell copies of the Software, and to
-+ *   permit persons to whom the Software is furnished to do so, subject to
-+ *   the following conditions:
-+ *   
-+ *   The above copyright notice and this permission notice shall be
-+ *   included in all copies or substantial portions of the Software.
-+ *   
-+ *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-+ *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-+ *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-+ *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-+ *   LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-+ *   OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-+ *   WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-+ *   
-+ * Adapted by Martin Quinson (mquinson at debian.org) to accept the hash32 prototype that is used in jruby.
-+ *   (same license applies)
-+ * 
++ * Perl's Hash implementation.
++ *
++ * @author nahi at ruby-lang.org
 + */
-+public class SipHash {
-+    public static int hash32(byte[] src, int offset, int length, byte[] seed) {
-+        long m;
-+        State s = new State(new SipKey(seed));
-+        int iter = length / 8;
-+        
-+        for(int i=0; i < iter; i++) {
-+            m = UnsignedInt64.binToIntOffset(src, (i * 8) + offset);
-+            s.processBlock(m);
++public class PerlHash {
++    public static long hash64(long key, byte[] src, int offset, int length) {
++        for (int idx = 0; idx < length; ++idx) {
++            key += (src[offset + idx] & 0xFF);
++            key += (key << 10);
++            key ^= (key >>> 6);
 +        }
-+        
-+        m = lastBlock(src, offset, length, iter);
-+        s.processBlock(m);
-+        s.finish();
-+        return s.digest32();
-+        
++        key += (key << 3);
++        key ^= (key >>> 11);
++        key += (key << 15);
++        return key;
 +    }
-+    
-+    private static long lastBlock(byte[] data, int offset, int length, int iter) {
-+        long last = ((long) length) << 56;
-+        int off = iter * 8+offset;
-+
-+        switch (length % 8) {
-+            case 7: 
-+                last |= ((long) data[off + 6]) << 48;
-+            case 6:
-+                last |= ((long) data[off + 5]) << 40;
-+            case 5:
-+                last |= ((long) data[off + 4]) << 32;
-+            case 4:
-+                last |= ((long) data[off + 3]) << 24;
-+            case 3:
-+                last |= ((long) data[off + 2]) << 16;
-+            case 2:
-+                last |= ((long) data[off + 1]) << 8;
-+            case 1:
-+                last |= (long) data[off];
-+                break;
-+            case 0:
-+                break;
-+        }
-+        return last;
++    public static int hash32(long key, byte[] src, int offset, int length) {
++        long res = hash64(key,src,offset,length);
++        return ((int) (res & 0xFFFFFFFF)) ^ ((int) (res >>> 32));
 +    }
-+    
-+    private static class State {
-+        private long v0;
-+        private long v1;
-+        private long v2;
-+        private long v3;
-+        
-+        public State(SipKey key) {
-+            v0 = 0x736f6d6570736575L;
-+            v1 = 0x646f72616e646f6dL;
-+            v2 = 0x6c7967656e657261L;
-+            v3 = 0x7465646279746573L;
-+            
-+            long k0 = key.getLeftHalf();
-+            long k1 = key.getRightHalf();
-+            
-+            v0 ^= k0;
-+            v1 ^= k1;
-+            v2 ^= k0;
-+            v3 ^= k1;
-+        }
-+
-+        private void compress() {
-+            v0 += v1;
-+            v2 += v3;
-+            v1 = UnsignedInt64.rotateLeft(v1, 13);
-+            v3 = UnsignedInt64.rotateLeft(v3, 16);
-+            v1 ^= v0;
-+            v3 ^= v2;
-+            v0 = UnsignedInt64.rotateLeft(v0, 32);
-+            v2 += v1;
-+            v0 += v3;
-+            v1 = UnsignedInt64.rotateLeft(v1, 17);
-+            v3 = UnsignedInt64.rotateLeft(v3, 21);
-+            v1 ^= v2;
-+            v3 ^= v0;
-+            v2 = UnsignedInt64.rotateLeft(v2, 32);
-+        }
-+        
-+        private void compressTimes(int times) {
-+            for (int i=0; i < times; i++) {
-+                compress();
-+            }
-+        }
-+        
-+        public void processBlock(long m) {
-+            v3 ^= m;
-+            compressTimes(2);
-+            v0 ^= m;
-+        }
-+        
-+        public void finish() {
-+            v2 ^= 0xff;
-+            compressTimes(4);
-+        }
-+        
-+        public long digest() {
-+            return v0 ^ v1 ^ v2 ^ v3;
-+        }
-+        public int digest32() {
-+            long res = digest();
-+            return ((int) (res & 0xFFFFFFFF)) ^ ((int) (res >>> 32));
-+        }
-+    }   
 +}
-+
-+class SipKey {
-+    private final byte[] key;
-+    
-+    public SipKey(byte[] key) {
-+        if (key == null || key.length != 16)
-+            throw new RuntimeException("SipHash key must be 16 bytes");
-+        this.key = key;
-+    }
-+    
-+    long getLeftHalf() {
-+       return UnsignedInt64.binToIntOffset(key, 0); 
-+    }
-+    
-+    long getRightHalf() {
-+        return UnsignedInt64.binToIntOffset(key, 8); 
-+    }
-+}
-+
-+class UnsignedInt64 {
-+    private UnsignedInt64() {}
-+    
-+    public static long binToInt(byte[] b) {
-+        return  binToIntOffset(b, 0);
-+    }
-+    
-+    public static long binToIntOffset(byte[] b, int off) {
-+        return ((long) b[off    ])       |
-+               ((long) b[off + 1]) << 8  |
-+               ((long) b[off + 2]) << 16 |
-+               ((long) b[off + 3]) << 24 |
-+               ((long) b[off + 4]) << 32 |
-+               ((long) b[off + 5]) << 40 |
-+               ((long) b[off + 6]) << 48 |
-+               ((long) b[off + 7]) << 56;
-+    }
-+    
-+    public static void intToBin(long l, byte[] b) {
-+        b[0] = (byte) ( l         & 0xff);
-+        b[1] = (byte) ((l >>> 8 ) & 0xff);
-+        b[2] = (byte) ((l >>> 16) & 0xff);
-+        b[3] = (byte) ((l >>> 24) & 0xff);
-+        b[4] = (byte) ((l >>> 32) & 0xff);
-+        b[5] = (byte) ((l >>> 40) & 0xff);
-+        b[6] = (byte) ((l >>> 48) & 0xff);
-+        b[7] = (byte) ((l >>> 56) & 0xff);
-+    }
-+    
-+    public static long rotateLeft(long l, int shift) {
-+        return (l << shift) | l >>> (64 - shift);
-+    }
-+}
-Index: jruby-1.5.6/src/org/jruby/Ruby.java
-===================================================================
---- jruby-1.5.6.orig/src/org/jruby/Ruby.java	2012-12-10 23:38:21.827577622 +0100
-+++ jruby-1.5.6/src/org/jruby/Ruby.java	2012-12-10 23:43:28.377922386 +0100
-@@ -270,7 +270,8 @@
-         this.jitCompiler        = new JITCompiler(this);
-         this.parserStats        = new ParserStats(this);
- 
--	this.hashSeed = this.random.nextInt();
-+	this.hashSeed = new byte[16];
-+	this.random.nextBytes(hashSeed);
-         
-         this.beanManager.register(new Config(this));
-         this.beanManager.register(parserStats);
-@@ -3707,7 +3708,7 @@
-         return jittedMethods;
-     }
- 
--    public int getHashSeed() {
-+    public byte[] getHashSeed() {
-         return hashSeed;
-     }
-     
-@@ -3815,7 +3816,7 @@
-     private long randomSeedSequence = 0;
-     private Random random = new Random();
-     /** The runtime-local seed for hash randomization */
--    private int hashSeed = 0;
-+    private byte[] hashSeed;
- 
-     private final List<EventHook> eventHooks = new Vector<EventHook>();
-     private boolean hasEventHooks;  

-- 
100% pure-Java implementation of Ruby



More information about the pkg-java-commits mailing list