ruby-changes:40754
From: nobu <ko1@a...>
Date: Tue, 1 Dec 2015 17:13:54 +0900 (JST)
Subject: [ruby-changes:40754] nobu:r52833 (trunk): string.c: no frozen error at cstr
nobu 2015-12-01 17:13:43 +0900 (Tue, 01 Dec 2015) New Revision: 52833 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=52833 Log: string.c: no frozen error at cstr * string.c (rb_string_value_cstr): should not raise on frozen string. Modified files: trunk/ChangeLog trunk/string.c trunk/test/-ext-/string/test_cstr.rb Index: ChangeLog =================================================================== --- ChangeLog (revision 52832) +++ ChangeLog (revision 52833) @@ -1,3 +1,8 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Tue Dec 1 17:13:41 2015 Nobuyoshi Nakada <nobu@r...> + + * string.c (rb_string_value_cstr): should not raise on frozen + string. + Tue Dec 1 09:35:29 2015 KOSAKI Motohiro <kosaki.motohiro@g...> * missing/explicit_bzero.c: add a few comment. Index: string.c =================================================================== --- string.c (revision 52832) +++ string.c (revision 52833) @@ -161,7 +161,15 @@ static VALUE str_replace_shared_without_ https://github.com/ruby/ruby/blob/trunk/string.c#L161 static VALUE str_new_shared(VALUE klass, VALUE str); static VALUE str_new_frozen(VALUE klass, VALUE orig); static VALUE str_new_static(VALUE klass, const char *ptr, long len, int encindex); -static void str_make_independent_expand(VALUE str, long expand); +static void str_make_independent_expand(VALUE str, long len, long expand, int termlen); + +static inline void +str_make_independent(VALUE str) +{ + long len = RSTRING_LEN(str); + int termlen = TERM_LEN(str); + str_make_independent_expand((str), len, 0L, termlen); +} static rb_encoding * get_actual_encoding(const int encidx, VALUE str) @@ -258,7 +266,7 @@ fstr_update_callback(st_data_t *key, st_ https://github.com/ruby/ruby/blob/trunk/string.c#L266 str = str_new_frozen(rb_cString, str); if (STR_SHARED_P(str)) { /* str should not be shared */ /* shared substring */ - str_make_independent_expand(str, 0L); + str_make_independent(str); assert(OBJ_FROZEN(str)); } if (!BARE_STRING_P(str)) { @@ -1700,33 +1708,43 @@ rb_str_format_m(VALUE str, VALUE arg) https://github.com/ruby/ruby/blob/trunk/string.c#L1708 } static inline void -str_modifiable(VALUE str) +rb_check_lockedtmp(VALUE str) { if (FL_TEST(str, STR_TMPLOCK)) { rb_raise(rb_eRuntimeError, "can't modify string; temporarily locked"); } +} + +static inline void +str_modifiable(VALUE str) +{ + rb_check_lockedtmp(str); rb_check_frozen(str); } static inline int -str_independent(VALUE str) +str_dependent_p(VALUE str) { - str_modifiable(str); if (STR_EMBED_P(str) || !FL_TEST(str, STR_SHARED|STR_NOFREE)) { - return 1; + return 0; } else { - return 0; + return 1; } } +static inline int +str_independent(VALUE str) +{ + str_modifiable(str); + return !str_dependent_p(str); +} + static void -str_make_independent_expand(VALUE str, long expand) +str_make_independent_expand(VALUE str, long len, long expand, const int termlen) { char *ptr; const char *oldptr; - long len = RSTRING_LEN(str); - const int termlen = TERM_LEN(str); long capa = len + expand; if (len > capa) len = capa; @@ -1753,8 +1771,6 @@ str_make_independent_expand(VALUE str, l https://github.com/ruby/ruby/blob/trunk/string.c#L1771 RSTRING(str)->as.heap.aux.capa = capa; } -#define str_make_independent(str) str_make_independent_expand((str), 0L) - void rb_str_modify(VALUE str) { @@ -1766,22 +1782,24 @@ rb_str_modify(VALUE str) https://github.com/ruby/ruby/blob/trunk/string.c#L1782 void rb_str_modify_expand(VALUE str, long expand) { + int termlen; if (expand < 0) { rb_raise(rb_eArgError, "negative expanding string size"); } + termlen = TERM_LEN(str); if (!str_independent(str)) { - str_make_independent_expand(str, expand); + long len = RSTRING_LEN(str); + str_make_independent_expand(str, len, expand, termlen); } else if (expand > 0) { long len = RSTRING_LEN(str); long capa = len + expand; - int termlen = TERM_LEN(str); if (!STR_EMBED_P(str)) { REALLOC_N(RSTRING(str)->as.heap.ptr, char, capa + termlen); RSTRING(str)->as.heap.aux.capa = capa; } else if (capa + termlen > RSTRING_EMBED_LEN_MAX + 1) { - str_make_independent_expand(str, expand); + str_make_independent_expand(str, len, expand, termlen); } } ENC_CODERANGE_CLEAR(str); @@ -1857,19 +1875,21 @@ str_null_char(const char *s, long len, c https://github.com/ruby/ruby/blob/trunk/string.c#L1875 } static char * -str_fill_term(VALUE str, char *s, long len, int oldtermlen, int termlen) +str_fill_term(VALUE str, char *s, long len, int termlen) { long capa = rb_str_capacity(str) + 1; if (capa < len + termlen) { - rb_str_modify_expand(str, termlen); + rb_check_lockedtmp(str); + str_make_independent_expand(str, len, 0L, termlen); } - else if (!str_independent(str)) { - if (zero_filled(s + len, termlen)) return s; - str_make_independent(str); + else if (str_dependent_p(str)) { + if (!zero_filled(s + len, termlen)) + str_make_independent_expand(str, len, 0L, termlen); + } + else { + TERM_FILL(s + len, termlen); } - s = RSTRING_PTR(str); - TERM_FILL(s + len, termlen); return s; } @@ -1886,15 +1906,13 @@ rb_string_value_cstr(volatile VALUE *ptr https://github.com/ruby/ruby/blob/trunk/string.c#L1906 if (str_null_char(s, len, minlen, enc)) { rb_raise(rb_eArgError, "string contains null char"); } - return str_fill_term(str, s, len, minlen, minlen); + return str_fill_term(str, s, len, minlen); } if (!s || memchr(s, 0, len)) { rb_raise(rb_eArgError, "string contains null byte"); } if (s[len]) { - rb_str_modify(str); - s = RSTRING_PTR(str); - s[RSTRING_LEN(str)] = 0; + s = str_fill_term(str, s, len, minlen); } return s; } @@ -1904,8 +1922,7 @@ rb_str_fill_terminator(VALUE str, const https://github.com/ruby/ruby/blob/trunk/string.c#L1922 { char *s = RSTRING_PTR(str); long len = RSTRING_LEN(str); - rb_encoding *enc = rb_enc_get(str); - str_fill_term(str, s, len, rb_enc_mbminlen(enc), newminlen); + str_fill_term(str, s, len, newminlen); } VALUE @@ -2279,7 +2296,7 @@ rb_str_resize(VALUE str, long len) https://github.com/ruby/ruby/blob/trunk/string.c#L2296 TERM_FILL(RSTRING(str)->as.ary + len, termlen); return str; } - str_make_independent_expand(str, len - slen); + str_make_independent_expand(str, slen, len - slen, termlen); } else if (len + termlen <= RSTRING_EMBED_LEN_MAX + 1) { char *ptr = STR_HEAP_PTR(str); @@ -2293,7 +2310,7 @@ rb_str_resize(VALUE str, long len) https://github.com/ruby/ruby/blob/trunk/string.c#L2310 } else if (!independent) { if (len == slen) return str; - str_make_independent_expand(str, len - slen); + str_make_independent_expand(str, slen, len - slen, termlen); } else if ((capa = RSTRING(str)->as.heap.aux.capa) < len || (capa - len) > (len < 1024 ? len : 1024)) { Index: test/-ext-/string/test_cstr.rb =================================================================== --- test/-ext-/string/test_cstr.rb (revision 52832) +++ test/-ext-/string/test_cstr.rb (revision 52833) @@ -17,6 +17,24 @@ class Test_StringCStr < Test::Unit::Test https://github.com/ruby/ruby/blob/trunk/test/-ext-/string/test_cstr.rb#L17 assert_equal(0, s.cstr_term, Bug4319) end + def test_frozen + s0 = Bug::String.new("abcdefgh"*8) + + [4, 4*3-1, 8*3-1, 64].each do |n| + s = s0[0, n] + s.cstr_unterm('x') + s.freeze + assert_equal(0, s.cstr_term) + WCHARS.each do |enc| + s = s0.encode(enc) + s.set_len(n - n % s[0].bytesize) + s.cstr_unterm('x') + s.freeze + assert_equal(0, s.cstr_term) + end + end + end + WCHARS = [Encoding::UTF_16BE, Encoding::UTF_16LE, Encoding::UTF_32BE, Encoding::UTF_32LE] def test_wchar_embed -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/