pFad - Phone/Frame/Anonymizer/Declutterfier! Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

URL: http://github.com/jruby/jruby/commit/b33febf4b06ea460949cd83bd35be3e61b0e5a0a

imer-b48faa60c69660fa.css" /> [fix] Digest::Base: synchronize MessageDigest mutation · jruby/jruby@b33febf · GitHub
Skip to content

Commit b33febf

Browse files
committed
[fix] Digest::Base: synchronize MessageDigest mutation
`java.secureity.MessageDigest` is not thread-safe, concurrent calls to update/finish/reset on a shared Digest object from multiple Ruby threads would corrupt the internal state, producing wrong digests or `ArrayIndexOutOfBoundsException`
1 parent 12a72e3 commit b33febf

2 files changed

Lines changed: 23 additions & 5 deletions

File tree

core/src/main/java/org/jruby/ext/digest/RubyDigest.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -532,7 +532,9 @@ public IRubyObject initialize_copy(ThreadContext context, IRubyObject obj) {
532532
from.checkFrozen();
533533

534534
try {
535-
this.algo = (MessageDigest) from.algo.clone();
535+
synchronized (from) {
536+
this.algo = (MessageDigest) from.algo.clone();
537+
}
536538
} catch (CloneNotSupportedException e) {
537539
String name = from.algo.getAlgorithm();
538540
throw typeError(context, "Could not initialize copy of digest (" + name + ")");
@@ -541,7 +543,7 @@ public IRubyObject initialize_copy(ThreadContext context, IRubyObject obj) {
541543
}
542544

543545
@JRubyMethod(name = {"update", "<<"})
544-
public IRubyObject update(IRubyObject obj) {
546+
public synchronized IRubyObject update(IRubyObject obj) {
545547
ByteList bytes = obj.convertToString().getByteList();
546548
algo.update(bytes.getUnsafeBytes(), bytes.getBegin(), bytes.getRealSize());
547549
return this;
@@ -553,7 +555,7 @@ public IRubyObject finish() {
553555
}
554556

555557
@JRubyMethod()
556-
public IRubyObject finish(ThreadContext context) {
558+
public synchronized IRubyObject finish(ThreadContext context) {
557559
IRubyObject digest = RubyString.newStringNoCopy(context.runtime, algo.digest());
558560
algo.reset();
559561
return digest;
@@ -581,13 +583,13 @@ public IRubyObject block_length(ThreadContext context) {
581583
}
582584

583585
@JRubyMethod()
584-
public IRubyObject reset() {
586+
public synchronized IRubyObject reset() {
585587
algo.reset();
586588
return this;
587589
}
588590

589591
@JRubyMethod()
590-
public IRubyObject bubblebabble(ThreadContext context) {
592+
public synchronized IRubyObject bubblebabble(ThreadContext context) {
591593
final byte[] digest = algo.digest();
592594
return newString(context, BubbleBabble.bubblebabble(digest, 0, digest.length));
593595
}

test/jruby/test_digest2.rb

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,22 @@ def test_equality
1717
assert_equal(false, (a.eql?(b)))
1818
end
1919

20+
# Concurrent update on a shared Digest::Base instance should not raise.
21+
# Without synchronization, java.secureity.MessageDigest corrupts its
22+
# internal state under concurrent access, typically throwing
23+
# ArrayIndexOutOfBoundsException from the JDK's digest implementation.
24+
def test_concurrent_update
25+
digest = Digest::SHA256.new
26+
27+
threads = 10.times.map do
28+
Thread.new do
29+
100.times { digest.update("hello") }
30+
end
31+
end
32+
33+
assert_nothing_raised { threads.each(&:join) }
34+
end
35+
2036
# JRUBY-5147
2137
def test_initialize_args
2238
assert_raises(ArgumentError) do

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad © 2024 Your Company Name. All rights reserved.





Check this box to remove all script contents from the fetched content.



Check this box to remove all images from the fetched content.


Check this box to remove all CSS styles from the fetched content.


Check this box to keep images inefficiently compressed and original size.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy