ruby-changes:53588
From: shyouhei <ko1@a...>
Date: Mon, 19 Nov 2018 18:52:52 +0900 (JST)
Subject: [ruby-changes:53588] shyouhei:r65804 (trunk): string.c: setbyte silently ignores upper bits
shyouhei 2018-11-19 18:52:46 +0900 (Mon, 19 Nov 2018) New Revision: 65804 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=65804 Log: string.c: setbyte silently ignores upper bits The behaviour of String#setbyte has been depending on the width of int, which is not portable. Must check explicitly. Modified files: trunk/string.c trunk/test/ruby/test_m17n.rb Index: test/ruby/test_m17n.rb =================================================================== --- test/ruby/test_m17n.rb (revision 65803) +++ test/ruby/test_m17n.rb (revision 65804) @@ -1524,6 +1524,17 @@ class TestM17N < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_m17n.rb#L1524 } end + def test_setbyte_range + s = u("\xE3\x81\x82\xE3\x81\x84") + assert_raise(RangeError) { s.setbyte(0, -1) } + assert_nothing_raised { s.setbyte(0, 0x00) } + assert_nothing_raised { s.setbyte(0, 0x7F) } + assert_nothing_raised { s.setbyte(0, 0x80) } + assert_nothing_raised { s.setbyte(0, 0xff) } + assert_raise(RangeError) { s.setbyte(0, 0x100) } + assert_raise(RangeError) { s.setbyte(0, 0x4f7574206f6620636861722072616e6765) } + end + def test_compatible assert_nil Encoding.compatible?("",0) assert_equal(Encoding::UTF_8, Encoding.compatible?(u(""), ua("abc"))) Index: string.c =================================================================== --- string.c (revision 65803) +++ string.c (revision 65804) @@ -5413,7 +5413,8 @@ rb_str_setbyte(VALUE str, VALUE index, V https://github.com/ruby/ruby/blob/trunk/string.c#L5413 long pos = NUM2LONG(index); int byte = NUM2INT(value); long len = RSTRING_LEN(str); - char *head, *ptr, *left = 0; + char *head, *left = 0; + unsigned char *ptr; rb_encoding *enc; int cr = ENC_CODERANGE_UNKNOWN, width, nlen; @@ -5421,17 +5422,21 @@ rb_str_setbyte(VALUE str, VALUE index, V https://github.com/ruby/ruby/blob/trunk/string.c#L5422 rb_raise(rb_eIndexError, "index %ld out of string", pos); if (pos < 0) pos += len; + if (byte < 0) + rb_raise(rb_eRangeError, "integer %d too small to convert into `unsigned char'", byte); + if (UCHAR_MAX < byte) + rb_raise(rb_eRangeError, "integer %d too big to convert into `unsigned char'", byte); if (!str_independent(str)) str_make_independent(str); enc = STR_ENC_GET(str); head = RSTRING_PTR(str); - ptr = &head[pos]; + ptr = (unsigned char *)&head[pos]; if (!STR_EMBED_P(str)) { cr = ENC_CODERANGE(str); switch (cr) { case ENC_CODERANGE_7BIT: - left = ptr; + left = (char *)ptr; *ptr = byte; if (ISASCII(byte)) goto end; nlen = rb_enc_precise_mbclen(left, head+len, enc); -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/