Skip to content

Commit

Permalink
Fix length handling in select!/reject! ensure
Browse files Browse the repository at this point in the history
The logic here had diverged somewhat from CRuby's logic, and did
not reacquire the array's begin or length as in CRuby. This led to
bad length calculation when there were additional mutations during
the select!/reject! loop.

Fixes jruby#7976
  • Loading branch information
headius committed Oct 25, 2023
1 parent eeef795 commit 1361c18
Showing 1 changed file with 11 additions and 7 deletions.
18 changes: 11 additions & 7 deletions core/src/main/java/org/jruby/RubyArray.java
Original file line number Diff line number Diff line change
Expand Up @@ -2924,7 +2924,7 @@ public IRubyObject select_bang(ThreadContext context, Block block) {
}
finally {
if (modified) checkFrozen();
selectBangEnsure(runtime, len, beg, len0, len1);
selectBangEnsure(runtime, len0, len1);
}
}

Expand Down Expand Up @@ -3082,17 +3082,20 @@ public IRubyObject rejectBang(ThreadContext context, Block block) {
}
finally {
if (modified) checkFrozen();
selectBangEnsure(runtime, realLength, beg, len0, len1);
selectBangEnsure(runtime, len0, len1);
}
}

// MRI: select_bang_ensure
private void selectBangEnsure(final Ruby runtime, final int len, final int beg,
int i1, int i2) {
if (i2 < i1) {
realLength = len - i1 + i2;
private void selectBangEnsure(final Ruby runtime, int i1, int i2) {
int len = realLength;

if (i2 < len && i2 < i1) {
int tail = 0;
int beg = begin;
if (i1 < len) {
safeArrayCopy(runtime, values, beg + i1, values, beg + i2, len - i1);
tail = len - i1;
safeArrayCopy(runtime, values, beg + i1, values, beg + i2, tail);
}
else if (realLength > 0) {
// nil out left-overs to avoid leaks (MRI doesn't)
Expand All @@ -3102,6 +3105,7 @@ else if (realLength > 0) {
throw concurrentModification(runtime, ex);
}
}
realLength = i2 + tail;
}
}

Expand Down

0 comments on commit 1361c18

Please sign in to comment.