[前][次][番号順一覧][スレッド一覧]

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/

[前][次][番号順一覧][スレッド一覧]