[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