Skip to content

Commit

Permalink
Fixes jruby#7649. Infinite loop in StringScanner regex
Browse files Browse the repository at this point in the history
Crux of problem was strscan#concat was calling JRuby String append
function in Java and that was a pre-m17n version of append which
was not encoding aware OR coderange aware.  As a result, the string
thought it was 7bit ASCII (narrator: it was not) and this made
joni go off the rails.

The fix I used was to move append19 impl into append and deprecate
append19.  This version does all the right things.  In looking
at callers of append there were not many consumers.  ARGF#read
was also broken in the same way since we would be appending what-
ever file in its encoding onto the existing string.
  • Loading branch information
enebo committed Sep 6, 2023
1 parent 8ccff43 commit 703292e
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 27 deletions.
2 changes: 1 addition & 1 deletion core/src/main/java/org/jruby/RubyArray.java
Original file line number Diff line number Diff line change
Expand Up @@ -1968,7 +1968,7 @@ protected RubyString joinStrings(RubyString sep, int max, RubyString result) {
try {
for (int i = 0; i < max; i++) {
if (i > 0 && sep != null) result.cat19(sep);
result.append19(eltInternal(i));
result.append(eltInternal(i));
}
} catch (ArrayIndexOutOfBoundsException e) {
throw concurrentModification(getRuntime(), e);
Expand Down
38 changes: 12 additions & 26 deletions core/src/main/java/org/jruby/RubyString.java
Original file line number Diff line number Diff line change
Expand Up @@ -2640,32 +2640,7 @@ public boolean isEmpty() {
*
*/
public RubyString append(IRubyObject other) {
modifyCheck();

if (other instanceof RubyFixnum) {
cat(ConvertBytes.longToByteList(((RubyFixnum) other).value));
return this;
}
if (other instanceof RubyFloat) {
return cat((RubyString) ((RubyFloat) other).to_s());
}
if (other instanceof RubySymbol) {
cat(((RubySymbol) other).getBytes());
return this;
}
RubyString otherStr = other.convertToString();
infectBy(otherStr);
return cat(otherStr.value);
}

public RubyString append(RubyString other) {
modifyCheck();
infectBy(other);
return cat(other.value);
}

public RubyString append19(IRubyObject other) {
// fast path for fixnum straight into ascii-compatible bytelist
// fast path for fixnum straight into ascii-compatible bytelist (modify check performed in here)
if (other instanceof RubyFixnum && value.getEncoding().isAsciiCompatible()) {
ConvertBytes.longIntoString(this, ((RubyFixnum) other).value);
return this;
Expand All @@ -2683,6 +2658,17 @@ public RubyString append19(IRubyObject other) {
return cat19(other.convertToString());
}

public RubyString append(RubyString other) {
modifyCheck();
infectBy(other);
return cat19(other);
}

@Deprecated
public RubyString append19(IRubyObject other) {
return append(other);
}

public RubyString appendAsDynamicString(IRubyObject other) {
// fast path for fixnum straight into ascii-compatible bytelist
if (other instanceof RubyFixnum && value.getEncoding().isAsciiCompatible()) {
Expand Down

0 comments on commit 703292e

Please sign in to comment.