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
This commit is contained in:
parent
1f67a3900f
commit
86e266bb60
134
string.c
134
string.c
@ -301,54 +301,6 @@ fstr_update_callback(st_data_t *key, st_data_t *value, st_data_t arg, int existi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RUBY_FUNC_EXPORTED
|
|
||||||
VALUE
|
|
||||||
rb_fstring(VALUE str)
|
|
||||||
{
|
|
||||||
VALUE fstr;
|
|
||||||
int bare;
|
|
||||||
|
|
||||||
Check_Type(str, T_STRING);
|
|
||||||
|
|
||||||
if (FL_TEST(str, RSTRING_FSTR))
|
|
||||||
return str;
|
|
||||||
|
|
||||||
bare = BARE_STRING_P(str);
|
|
||||||
if (STR_EMBED_P(str) && !bare) {
|
|
||||||
OBJ_FREEZE_RAW(str);
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
fstr = register_fstring(str);
|
|
||||||
|
|
||||||
if (!bare) {
|
|
||||||
str_replace_shared_without_enc(str, fstr);
|
|
||||||
OBJ_FREEZE_RAW(str);
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
return fstr;
|
|
||||||
}
|
|
||||||
|
|
||||||
static VALUE
|
|
||||||
register_fstring(VALUE str)
|
|
||||||
{
|
|
||||||
VALUE ret;
|
|
||||||
st_table *frozen_strings = rb_vm_fstring_table();
|
|
||||||
|
|
||||||
do {
|
|
||||||
ret = str;
|
|
||||||
st_update(frozen_strings, (st_data_t)str,
|
|
||||||
fstr_update_callback, (st_data_t)&ret);
|
|
||||||
} while (ret == Qundef);
|
|
||||||
|
|
||||||
assert(OBJ_FROZEN(ret));
|
|
||||||
assert(!FL_TEST_RAW(ret, STR_FAKESTR));
|
|
||||||
assert(!FL_TEST_RAW(ret, FL_EXIVAR));
|
|
||||||
assert(!FL_TEST_RAW(ret, FL_TAINT));
|
|
||||||
assert(RBASIC_CLASS(ret) == rb_cString);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
tainted_fstr_update(st_data_t *key, st_data_t *val, st_data_t arg, int existing)
|
tainted_fstr_update(st_data_t *key, st_data_t *val, st_data_t arg, int existing)
|
||||||
{
|
{
|
||||||
@ -377,6 +329,78 @@ tainted_fstr_update(st_data_t *key, st_data_t *val, st_data_t arg, int existing)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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_ish;
|
||||||
|
|
||||||
|
Check_Type(str, T_STRING);
|
||||||
|
|
||||||
|
if (FL_TEST(str, RSTRING_FSTR))
|
||||||
|
return str;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
return fstr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
register_fstring(VALUE str)
|
||||||
|
{
|
||||||
|
VALUE ret;
|
||||||
|
st_table *frozen_strings = rb_vm_fstring_table();
|
||||||
|
|
||||||
|
do {
|
||||||
|
ret = str;
|
||||||
|
st_update(frozen_strings, (st_data_t)str,
|
||||||
|
fstr_update_callback, (st_data_t)&ret);
|
||||||
|
} while (ret == Qundef);
|
||||||
|
|
||||||
|
assert(OBJ_FROZEN(ret));
|
||||||
|
assert(!FL_TEST_RAW(ret, STR_FAKESTR));
|
||||||
|
assert(!FL_TEST_RAW(ret, FL_EXIVAR));
|
||||||
|
assert(!FL_TEST_RAW(ret, FL_TAINT));
|
||||||
|
assert(RBASIC_CLASS(ret) == rb_cString);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
rb_fstring_existing0(VALUE str)
|
rb_fstring_existing0(VALUE str)
|
||||||
{
|
{
|
||||||
@ -414,20 +438,8 @@ rb_tainted_fstring_existing(VALUE str)
|
|||||||
if (!RB_FL_TEST_RAW(ret, RSTRING_FSTR)) {
|
if (!RB_FL_TEST_RAW(ret, RSTRING_FSTR)) {
|
||||||
return Qnil;
|
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;
|
return register_fstring_tainted(str, tfstrings);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VALUE
|
VALUE
|
||||||
|
@ -2749,10 +2749,15 @@ CODE
|
|||||||
|
|
||||||
assert_not_equal(str.object_id, (+str).object_id)
|
assert_not_equal(str.object_id, (+str).object_id)
|
||||||
assert_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('')
|
bar = %w(b a r).join('')
|
||||||
assert_not_predicate bar, :tainted?
|
assert_not_predicate bar, :tainted?
|
||||||
assert_not_predicate str, :tainted?
|
assert_not_predicate str, :tainted?
|
||||||
assert_same(str, -bar, "uminus deduplicates [Feature #13077]")
|
assert_same(str, -bar, "uminus deduplicates [Feature #13077]")
|
||||||
|
bar = %w(b a r).taint.join('')
|
||||||
|
tstr = str.dup.taint
|
||||||
|
assert_same -tstr, -bar
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_ord
|
def test_ord
|
||||||
|
Loading…
x
Reference in New Issue
Block a user