diff --git a/spec/tags/1.9/ruby/core/string/concat_tags.txt b/spec/tags/1.9/ruby/core/string/concat_tags.txt index a6dbfa04444..8baa2501382 100644 --- a/spec/tags/1.9/ruby/core/string/concat_tags.txt +++ b/spec/tags/1.9/ruby/core/string/concat_tags.txt @@ -1,3 +1 @@ -fails:String#concat with Integer returns a ASCII-8BIT string if self is US-ASCII and the argument is between 128-255 (inclusive) -fails:String#concat with Integer raises RangeError if the argument is an invalid codepoint for self's encoding fails:String#concat when self is ASCII-8BIT and argument is US-ASCII uses ASCII-8BIT encoding diff --git a/src/org/jruby/RubyString.java b/src/org/jruby/RubyString.java index fc1eda9bb6a..1e716a4a531 100644 --- a/src/org/jruby/RubyString.java +++ b/src/org/jruby/RubyString.java @@ -69,6 +69,7 @@ import org.jcodings.EncodingDB; import org.jcodings.ascii.AsciiTables; import org.jcodings.constants.CharacterType; +import org.jcodings.exception.EncodingException; import org.jcodings.specific.ASCIIEncoding; import org.jcodings.specific.USASCIIEncoding; import org.jcodings.specific.UTF8Encoding; @@ -2638,9 +2639,23 @@ public RubyString concat19(ThreadContext context, IRubyObject other) { private RubyString concatNumeric(Ruby runtime, int c) { Encoding enc = value.getEncoding(); - int cl = codeLength(runtime, enc, c); - modify19(value.getRealSize() + cl); - enc.codeToMbc(c, value.getUnsafeBytes(), value.getBegin() + value.getRealSize()); + int cl; + + try { + cl = codeLength(runtime, enc, c); + modify19(value.getRealSize() + cl); + + if (enc == USASCIIEncoding.INSTANCE) { + if (c > 0xff) runtime.newRangeError(c + " out of char range"); + if (c > 0x79) { + value.setEncoding(ASCIIEncoding.INSTANCE); + enc = value.getEncoding(); + } + } + enc.codeToMbc(c, value.getUnsafeBytes(), value.getBegin() + value.getRealSize()); + } catch (EncodingException e) { + throw runtime.newRangeError(c + " out of char range"); + } value.setRealSize(value.getRealSize() + cl); return this; }