summaryrefslogtreecommitdiff
path: root/string.c
diff options
context:
space:
mode:
authornormal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-07-18 09:52:55 +0000
committernormal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-07-18 09:52:55 +0000
commit86e266bb60e16c3a4868f6174aa8c4a5c50ff4a5 (patch)
tree6b1ac1e40d8300e852f0e9e632df08f0dfdfa1c0 /string.c
parent1f67a3900fbd45482ed36ad3b148b321307c1576 (diff)
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 git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@59359 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'string.c')
-rw-r--r--string.c108
1 files changed, 60 insertions, 48 deletions
diff --git a/string.c b/string.c
index 72fb65087c..932ed5e85f 100644
--- a/string.c
+++ b/string.c
@@ -301,27 +301,79 @@ fstr_update_callback(st_data_t *key, st_data_t *value, st_data_t arg, int existi
}
}
+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)
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)
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