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.
| Package | Affected versions | Patched versions |
|---|---|---|
org.jruby:jruby-parentMaven | < 1.7.1 | 1.7.1 |
Affected products
1Patches
15e4aab28b26fUse Perl's Hash for String#hash
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- github.com/advisories/GHSA-fmmq-j7pq-f85cghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2012-5370ghsaADVISORY
- jruby.org/2012/12/03/jruby-1-7-1ghsaWEB
- rhn.redhat.com/errata/RHSA-2013-0533.htmlnvdWEB
- bugzilla.redhat.com/show_bug.cginvdWEB
- github.com/jruby/jruby/commit/5e4aab28b26fd127112b76fabfac9a33b64caf77ghsaWEB
- 2012.appsec-forum.ch/conferences/nvd
- asfws12.files.wordpress.com/2012/11/asfws2012-jean_philippe_aumasson-martin_bosslet-hash_flooding_dos_reloaded.pdfnvd
- www.ocert.org/advisories/ocert-2012-001.htmlnvd
- www.131002.net/data/talks/appsec12_slides.pdfnvd
News mentions
0No linked articles in our index yet.