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

ruby-changes:47244

From: normal <ko1@a...>
Date: Tue, 18 Jul 2017 18:53:00 +0900 (JST)
Subject: [ruby-changes:47244] normal:r59359 (trunk): string: preserve taint flag with String#-@ (uminus)

normal	2017-07-18 18:52:55 +0900 (Tue, 18 Jul 2017)

  New Revision: 59359

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=59359

  Log:
    string: preserve taint flag with String#-@ (uminus)
    
    * string.c (tainted_fstr_update): move up
      (rb_fstring): support registering tainted strings
      (register_fstring_tainted): extract from rb_fstring_existing0
      (rb_tainted_fstring_existing): use register_fstring_tainted instead

  Modified files:
    trunk/string.c
    trunk/test/ruby/test_string.rb
Index: string.c
===================================================================
--- string.c	(revision 59358)
+++ string.c	(revision 59359)
@@ -301,27 +301,79 @@ fstr_update_callback(st_data_t *key, st_ https://github.com/ruby/ruby/blob/trunk/string.c#L301
     }
 }
 
+static int
+tainted_fstr_update(st_data_t *key, st_data_t *val, st_data_t arg, int existing)
+{
+    VALUE *fstr = (VALUE *)arg;
+    VALUE str = (VALUE)*key;
+
+    if (existing) {
+	/* because of lazy sweep, str may be unmarked already and swept
+	 * at next time */
+	if (rb_objspace_garbage_object_p(str)) {
+	    *fstr = Qundef;
+	    return ST_DELETE;
+	}
+
+	*fstr = str;
+	return ST_STOP;
+    }
+    else {
+	str = rb_str_resurrect(str);
+	RB_OBJ_TAINT_RAW(str);
+	RB_FL_SET_RAW(str, RSTRING_FSTR);
+	RB_OBJ_FREEZE_RAW(str);
+
+	*key = *val = *fstr = str;
+	return ST_CONTINUE;
+    }
+}
+
+static VALUE
+register_fstring_tainted(VALUE str, st_table *tfstrings)
+{
+    st_data_t fstr;
+
+    do {
+	fstr = (st_data_t)str;
+	st_update(tfstrings, fstr, tainted_fstr_update, (st_data_t)&fstr);
+    } while ((VALUE)fstr == Qundef);
+
+    str = (VALUE)fstr;
+    assert(OBJ_FROZEN_RAW(str));
+    assert(!FL_TEST_RAW(str, STR_FAKESTR));
+    assert(!FL_TEST_RAW(str, FL_EXIVAR));
+    assert(FL_TEST_RAW(str, RSTRING_FSTR));
+    assert(FL_TEST_RAW(str, FL_TAINT));
+    assert(RBASIC_CLASS(str) == rb_cString);
+
+    return str;
+}
+
 RUBY_FUNC_EXPORTED
 VALUE
 rb_fstring(VALUE str)
 {
     VALUE fstr;
-    int bare;
+    int bare_ish;
 
     Check_Type(str, T_STRING);
 
     if (FL_TEST(str, RSTRING_FSTR))
 	return str;
 
-    bare = BARE_STRING_P(str);
-    if (STR_EMBED_P(str) && !bare) {
+    bare_ish = !FL_TEST_RAW(str, FL_EXIVAR) && RBASIC_CLASS(str) == rb_cString;
+    if (STR_EMBED_P(str) && !bare_ish) {
 	OBJ_FREEZE_RAW(str);
 	return str;
     }
-
-    fstr = register_fstring(str);
-
-    if (!bare) {
+    if (!FL_TEST_RAW(str, FL_TAINT)) {
+	fstr = register_fstring(str);
+    }
+    else {
+	fstr = register_fstring_tainted(str, rb_vm_tfstring_table());
+    }
+    if (!bare_ish) {
 	str_replace_shared_without_enc(str, fstr);
 	OBJ_FREEZE_RAW(str);
 	return str;
@@ -349,34 +401,6 @@ register_fstring(VALUE str) https://github.com/ruby/ruby/blob/trunk/string.c#L401
     return ret;
 }
 
-static int
-tainted_fstr_update(st_data_t *key, st_data_t *val, st_data_t arg, int existing)
-{
-    VALUE *fstr = (VALUE *)arg;
-    VALUE str = (VALUE)*key;
-
-    if (existing) {
-	/* because of lazy sweep, str may be unmarked already and swept
-	 * at next time */
-	if (rb_objspace_garbage_object_p(str)) {
-	    *fstr = Qundef;
-	    return ST_DELETE;
-	}
-
-	*fstr = str;
-	return ST_STOP;
-    }
-    else {
-	str = rb_str_resurrect(str);
-	RB_OBJ_TAINT_RAW(str);
-	RB_FL_SET_RAW(str, RSTRING_FSTR);
-	RB_OBJ_FREEZE_RAW(str);
-
-	*key = *val = *fstr = str;
-	return ST_CONTINUE;
-    }
-}
-
 static VALUE
 rb_fstring_existing0(VALUE str)
 {
@@ -414,20 +438,8 @@ rb_tainted_fstring_existing(VALUE str) https://github.com/ruby/ruby/blob/trunk/string.c#L438
     if (!RB_FL_TEST_RAW(ret, RSTRING_FSTR)) {
 	return Qnil;
     }
-    do {
-	fstr = (st_data_t)ret;
-	st_update(tfstrings, fstr, tainted_fstr_update, (st_data_t)&fstr);
-    } while ((VALUE)fstr == Qundef);
 
-    ret = (VALUE)fstr;
-    assert(OBJ_FROZEN_RAW(ret));
-    assert(!FL_TEST_RAW(ret, STR_FAKESTR));
-    assert(!FL_TEST_RAW(ret, FL_EXIVAR));
-    assert(FL_TEST_RAW(ret, RSTRING_FSTR));
-    assert(FL_TEST_RAW(ret, FL_TAINT));
-    assert(RBASIC_CLASS(ret) == rb_cString);
-
-    return ret;
+    return register_fstring_tainted(str, tfstrings);
 }
 
 VALUE
Index: test/ruby/test_string.rb
===================================================================
--- test/ruby/test_string.rb	(revision 59358)
+++ test/ruby/test_string.rb	(revision 59359)
@@ -2749,10 +2749,15 @@ CODE https://github.com/ruby/ruby/blob/trunk/test/ruby/test_string.rb#L2749
 
     assert_not_equal(str.object_id, (+str).object_id)
     assert_equal(str.object_id, (-str).object_id)
+
+    return unless @cls == String
     bar = %w(b a r).join('')
     assert_not_predicate bar, :tainted?
     assert_not_predicate str, :tainted?
     assert_same(str, -bar, "uminus deduplicates [Feature #13077]")
+    bar = %w(b a r).taint.join('')
+    tstr = str.dup.taint
+    assert_same -tstr, -bar
   end
 
   def test_ord

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

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