Skip to content

Commit

Permalink
Fix negative index handling for String#[]=.
Browse files Browse the repository at this point in the history
  • Loading branch information
headius committed Mar 24, 2015
1 parent f55efaf commit 6f1d6e7
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 4 deletions.
8 changes: 4 additions & 4 deletions core/src/main/java/org/jruby/RubyString.java
Expand Up @@ -906,7 +906,7 @@ public final void modify19() {
clearCodeRange();
}

private void modifyAndKeepCodeRange() {
public void modifyAndKeepCodeRange() {
modify();
keepCodeRange();
}
Expand Down Expand Up @@ -2884,7 +2884,7 @@ private IRubyObject replaceInternal(int beg, int len, RubyString repl) {
}

private void replaceInternal19(int beg, int len, RubyString repl) {
StringSupport.replaceInternal19(beg, len, this, repl);
StringSupport.replaceInternal19(getRuntime(), beg, len, this, repl);
infectBy(repl);
}

Expand Down Expand Up @@ -3055,7 +3055,7 @@ public IRubyObject op_aset19(ThreadContext context, IRubyObject arg0, IRubyObjec
}

private IRubyObject op_aset19(ThreadContext context, int idx, IRubyObject arg1) {
replaceInternal19(checkIndex(idx, strLength()), 1, arg1.convertToString());
StringSupport.replaceInternal19(context.runtime, idx, 1, this, arg1.convertToString());
return arg1;
}

Expand All @@ -3068,7 +3068,7 @@ public IRubyObject op_aset19(ThreadContext context, IRubyObject arg0, IRubyObjec
int len = RubyNumeric.num2int(arg1);
checkLength(len);
RubyString repl = arg2.convertToString();
replaceInternal19(checkIndex(beg, strLength()), len, repl);
StringSupport.replaceInternal19(context.runtime, beg, len, this, repl);
}
return arg2;
}
Expand Down
21 changes: 21 additions & 0 deletions core/src/main/java/org/jruby/util/StringSupport.java
Expand Up @@ -1338,6 +1338,7 @@ public static ByteList replaceInternal(int beg, int len, ByteListHolder source,
return source.getByteList();
}

// headius: TODO: This version does not raise errors in proper places
public static void replaceInternal19(int beg, int len, CodeRangeable source, CodeRangeable repl) {
Encoding enc = source.checkEncoding(repl);
int p = source.getByteList().getBegin();
Expand All @@ -1362,6 +1363,26 @@ public static void replaceInternal19(int beg, int len, CodeRangeable source, Cod
if (cr != CR_BROKEN) source.setCodeRange(cr);
}

public static void replaceInternal19(Ruby runtime, int beg, int len, RubyString source, RubyString repl) {
source.checkEncoding(repl);
int slen = strLengthFromRubyString(source);

if (slen < beg) {
throw runtime.newIndexError("index " + beg + " out of string");
}
if (beg < 0) {
if (-beg > slen) {
throw runtime.newIndexError("index " + beg + " out of string");
}
beg += slen;
}
if (slen < len || slen < beg + len) {
len = slen - beg;
}

replaceInternal19(beg, len, source, repl);
}

public static boolean isAsciiOnly(CodeRangeable string) {
return string.getByteList().getEncoding().isAsciiCompatible() && string.scanForCodeRange() == CR_7BIT;
}
Expand Down

0 comments on commit 6f1d6e7

Please sign in to comment.