From 61d807ccfae5500d1471f1074a6671ac9f191c88 Mon Sep 17 00:00:00 2001 From: nobu Date: Wed, 22 Jul 2015 14:44:20 +0000 Subject: string.c: fix coderange of reverse * string.c (rb_str_reverse): reversed string is not a substring, and should not set coderange of the original string. [ruby-dev:49189] [Bug #11387] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@51344 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 6 ++++++ string.c | 21 ++++++++------------- test/ruby/test_m17n.rb | 7 ++++++- 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/ChangeLog b/ChangeLog index fae7d715de..a288ec0ebd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +Wed Jul 22 23:44:17 2015 Nobuyoshi Nakada + + * string.c (rb_str_reverse): reversed string is not a substring, + and should not set coderange of the original string. + [ruby-dev:49189] [Bug #11387] + Wed Jul 22 20:17:51 2015 Koichi Sasada * vm_core.h: modify layout of rb_iseq_constant_body. diff --git a/string.c b/string.c index 56960574ec..110d11199e 100644 --- a/string.c +++ b/string.c @@ -4802,13 +4802,14 @@ rb_str_reverse(VALUE str) rb_encoding *enc; VALUE rev; char *s, *e, *p; - int single = 1; + int cr; if (RSTRING_LEN(str) <= 1) return rb_str_dup(str); enc = STR_ENC_GET(str); rev = rb_str_new_with_class(str, 0, RSTRING_LEN(str)); s = RSTRING_PTR(str); e = RSTRING_END(str); p = RSTRING_END(rev); + cr = ENC_CODERANGE(str); if (RSTRING_LEN(str) > 1) { if (single_byte_optimizable(str)) { @@ -4816,21 +4817,22 @@ rb_str_reverse(VALUE str) *--p = *s++; } } - else if (ENC_CODERANGE(str) == ENC_CODERANGE_VALID) { + else if (cr == ENC_CODERANGE_VALID) { while (s < e) { int clen = rb_enc_fast_mbclen(s, e, enc); - if (clen > 1 || (*s & 0x80)) single = 0; p -= clen; memcpy(p, s, clen); s += clen; } } else { + cr = rb_enc_asciicompat(enc) ? + ENC_CODERANGE_7BIT : ENC_CODERANGE_VALID; while (s < e) { int clen = rb_enc_mbclen(s, e, enc); - if (clen > 1 || (*s & 0x80)) single = 0; + if (clen > 1 || (*s & 0x80)) cr = ENC_CODERANGE_UNKNOWN; p -= clen; memcpy(p, s, clen); s += clen; @@ -4839,15 +4841,8 @@ rb_str_reverse(VALUE str) } STR_SET_LEN(rev, RSTRING_LEN(str)); OBJ_INFECT(rev, str); - if (ENC_CODERANGE(str) == ENC_CODERANGE_UNKNOWN) { - if (single) { - ENC_CODERANGE_SET(str, ENC_CODERANGE_7BIT); - } - else { - ENC_CODERANGE_SET(str, ENC_CODERANGE_VALID); - } - } - rb_enc_cr_str_copy_for_substr(rev, str); + str_enc_copy(rev, str); + ENC_CODERANGE_SET(rev, cr); return rev; } diff --git a/test/ruby/test_m17n.rb b/test/ruby/test_m17n.rb index 94a32591cb..d655dbf9e7 100644 --- a/test/ruby/test_m17n.rb +++ b/test/ruby/test_m17n.rb @@ -1142,7 +1142,12 @@ class TestM17N < Test::Unit::TestCase end def test_reverse - assert_equal(u("\xf0jihgfedcba"), u("abcdefghij\xf0").reverse) + bug11387 = '[ruby-dev:49189] [Bug #11387]' + s1 = u("abcdefghij\xf0") + s2 = s1.reverse + assert_not_predicate(s1, :valid_encoding?, bug11387) + assert_equal(u("\xf0jihgfedcba"), s2) + assert_not_predicate(s2, :valid_encoding?, bug11387) end def test_reverse_bang -- cgit v1.2.3