VYPR
Moderate severityNVD Advisory· Published Nov 28, 2012· Updated Apr 29, 2026

CVE-2012-5370

CVE-2012-5370

Description

JRuby computes hash values without properly restricting the ability to trigger hash collisions predictably, which allows context-dependent attackers to cause a denial of service (CPU consumption) via crafted input to an application that maintains a hash table, as demonstrated by a universal multicollision attack against the MurmurHash2 algorithm, a different vulnerability than CVE-2011-4838.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
org.jruby:jruby-parentMaven
< 1.7.11.7.1

Affected products

1

Patches

1
5e4aab28b26f

Use Perl's Hash for String#hash

https://github.com/jruby/jrubyHiroshi NakamuraNov 17, 2012via ghsa
5 files changed · +46 5
  • src/org/jruby/RubyInstanceConfig.java+9 0 modified
    @@ -662,6 +662,14 @@ public void setObjectSpaceEnabled(boolean newObjectSpaceEnabled) {
         public boolean isObjectSpaceEnabled() {
             return objectSpaceEnabled;
         }
    +    
    +    public void setSiphashEnabled(boolean newSiphashEnabled) {
    +        siphashEnabled = newSiphashEnabled;
    +    }
    +    
    +    public boolean isSiphashEnabled() {
    +        return siphashEnabled;
    +    }
     
         public void setEnvironment(Map newEnvironment) {
             if (newEnvironment == null) newEnvironment = new HashMap();
    @@ -1196,6 +1204,7 @@ public int getProfileMaxMethods() {
         private PrintStream error          = System.err;
         private Profile profile            = Profile.DEFAULT;
         private boolean objectSpaceEnabled = Options.OBJECTSPACE_ENABLED.load();
    +    private boolean siphashEnabled     = Options.SIPHASH_ENABLED.load();
     
         private CompileMode compileMode = CompileMode.JIT;
         private boolean runRubyInProcess   = true;
    
  • src/org/jruby/Ruby.java+7 0 modified
    @@ -205,6 +205,7 @@ private Ruby(RubyInstanceConfig config) {
             this.out                = config.getOutput();
             this.err                = config.getError();
             this.objectSpaceEnabled = config.isObjectSpaceEnabled();
    +        this.siphashEnabled     = config.isSiphashEnabled();
             this.profile            = config.getProfile();
             this.currentDirectory   = config.getCurrentDirectory();
             this.kcode              = config.getKCode();
    @@ -3938,6 +3939,11 @@ public boolean isObjectSpaceEnabled() {
         public void setObjectSpaceEnabled(boolean objectSpaceEnabled) {
             this.objectSpaceEnabled = objectSpaceEnabled;
         }
    +    
    +    // You cannot set siphashEnabled property except via RubyInstanceConfig to avoid mixing hash functions.
    +    public boolean isSiphashEnabled() {
    +        return siphashEnabled;
    +    }
     
         public long getStartTime() {
             return startTime;
    @@ -4289,6 +4295,7 @@ public void secure(int level) {
         private boolean globalAbortOnExceptionEnabled = false;
         private boolean doNotReverseLookupEnabled = false;
         private volatile boolean objectSpaceEnabled;
    +    private boolean siphashEnabled;
         
         private final Set<Script> jittedMethods = Collections.synchronizedSet(new WeakHashSet<Script>());
         
    
  • src/org/jruby/RubyString.java+9 5 modified
    @@ -97,6 +97,7 @@
     import org.jruby.util.MurmurHash;
     import org.jruby.util.Numeric;
     import org.jruby.util.Pack;
    +import org.jruby.util.PerlHash;
     import org.jruby.util.RegexpOptions;
     import org.jruby.util.SipHashInline;
     import org.jruby.util.Sprintf;
    @@ -1213,13 +1214,15 @@ public int hashCode() {
         }
     
         /**
    -     * Generate a murmurhash for the String, using its associated Ruby instance's hash seed.
    +     * Generate a hash for the String, using its associated Ruby instance's hash seed.
          *
          * @param runtime
          * @return
          */
         public int strHashCode(Ruby runtime) {
    -        long hash = SipHashInline.hash24(runtime.getHashSeedK0(), runtime.getHashSeedK1(),
    +        long hash = runtime.isSiphashEnabled() ? SipHashInline.hash24(runtime.getHashSeedK0(),
    +                runtime.getHashSeedK1(), value.getUnsafeBytes(), value.getBegin(),
    +                value.getRealSize()) : PerlHash.hash(runtime.getHashSeedK0(),
                     value.getUnsafeBytes(), value.getBegin(), value.getRealSize());
             if (runtime.is1_9()) {
                 hash ^= (value.getEncoding().isAsciiCompatible() && scanForCodeRange() == CR_7BIT ? 0
    @@ -1229,14 +1232,15 @@ public int strHashCode(Ruby runtime) {
         }
     
         /**
    -     * Generate a murmurhash for the String, without a seed.
    +     * Generate a hash for the String, without a seed.
          *
          * @param runtime
          * @return
          */
         public int unseededStrHashCode(Ruby runtime) {
    -        long hash = SipHashInline.hash24(0, 0, value.getUnsafeBytes(), value.getBegin(),
    -                value.getRealSize());
    +        long hash = runtime.isSiphashEnabled() ? SipHashInline.hash24(0, 0, value.getUnsafeBytes(),
    +                value.getBegin(), value.getRealSize()) : PerlHash.hash(0, value.getUnsafeBytes(),
    +                value.getBegin(), value.getRealSize());
             if (runtime.is1_9()) {
                 hash ^= (value.getEncoding().isAsciiCompatible() && scanForCodeRange() == CR_7BIT ? 0
                         : value.getEncoding().getIndex());
    
  • src/org/jruby/util/cli/Options.java+1 0 modified
    @@ -161,6 +161,7 @@ public static String dump() {
         
         public static final Option<String> COMPAT_VERSION = string(MISCELLANEOUS, "compat.version", new String[]{"1.8","1.9","2.0"}, Constants.DEFAULT_RUBY_VERSION, "Specify the major Ruby version to be compatible with.");
         public static final Option<Boolean> OBJECTSPACE_ENABLED = bool(MISCELLANEOUS, "objectspace.enabled", false, "Enable or disable ObjectSpace.each_object.");
    +    public static final Option<Boolean> SIPHASH_ENABLED = bool(MISCELLANEOUS, "siphash.enabled", false, "Enable or disable SipHash for String hash function.");
         public static final Option<Boolean> LAUNCH_INPROC = bool(MISCELLANEOUS, "launch.inproc", false, "Set in-process launching of e.g. system('ruby ...').");
         public static final Option<String> BYTECODE_VERSION = string(MISCELLANEOUS, "bytecode.version", new String[]{"1.5","1.6","1.7"}, SafePropertyAccessor.getProperty("java.specification.version", "1.5"), "Specify the major Java bytecode version.");
         public static final Option<Boolean> MANAGEMENT_ENABLED = bool(MISCELLANEOUS, "management.enabled", false, "Set whether JMX management is enabled.");
    
  • src/org/jruby/util/PerlHash.java+20 0 added
    @@ -0,0 +1,20 @@
    +package org.jruby.util;
    +
    +/**
    + * Perl's Hash implementation.
    + *
    + * @author nahi@ruby-lang.org
    + */
    +public class PerlHash {
    +    public static long hash(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);
    +	}
    +	key += (key << 3);
    +	key ^= (key >>> 11);
    +	key += (key << 15);
    +	return key;
    +    }
    +}
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

10

News mentions

0

No linked articles in our index yet.