1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

* object.c (rb_obj_untrusted): new method Object#untrusted?.

(rb_obj_untrust): new method Object#untrust.
  (rb_obj_trust): new method Object#trust.
* array.c, debug.c, time.c, include/ruby/ruby.h, re.c, variable.c,
  string.c, io.c, dir.c, vm_method.c, struct.c, class.c, hash.c,
  ruby.c, marshal.c: fixes for Object#untrusted?.
* test/ruby/test_module.rb, test/ruby/test_array.rb,
  test/ruby/test_object.rb, test/ruby/test_string.rb,
  test/ruby/test_marshal.rb, test/ruby/test_hash.rb: added tests for
  Object#untrusted?.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@18568 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
shugo 2008-08-13 07:25:05 +00:00
parent 55c141c624
commit f433d710d0
23 changed files with 364 additions and 88 deletions

View file

@ -1,3 +1,18 @@
Wed Aug 13 16:02:14 2008 Shugo Maeda <shugo@ruby-lang.org>
* object.c (rb_obj_untrusted): new method Object#untrusted?.
(rb_obj_untrust): new method Object#untrust.
(rb_obj_trust): new method Object#trust.
* array.c, debug.c, time.c, include/ruby/ruby.h, re.c, variable.c,
string.c, io.c, dir.c, vm_method.c, struct.c, class.c, hash.c,
ruby.c, marshal.c: fixes for Object#untrusted?.
* test/ruby/test_module.rb, test/ruby/test_array.rb,
test/ruby/test_object.rb, test/ruby/test_string.rb,
test/ruby/test_marshal.rb, test/ruby/test_hash.rb: added tests for
Object#untrusted?.
Wed Aug 13 16:13:58 2008 NARUSE, Yui <naruse@ruby-lang.org>
* test/ruby/test_m17n.rb: follow EncodingCompatibilityError.

11
array.c
View file

@ -54,7 +54,7 @@ static inline void
rb_ary_modify_check(VALUE ary)
{
if (OBJ_FROZEN(ary)) rb_error_frozen("array");
if (!OBJ_TAINTED(ary) && rb_safe_level() >= 4)
if (!OBJ_UNTRUSTED(ary) && rb_safe_level() >= 4)
rb_raise(rb_eSecurityError, "Insecure: can't modify array");
}
@ -1263,10 +1263,12 @@ rb_ary_join(VALUE ary, VALUE sep)
{
long len = 1, i;
int taint = Qfalse;
int untrust = Qfalse;
VALUE result, tmp;
if (RARRAY_LEN(ary) == 0) return rb_str_new(0, 0);
if (OBJ_TAINTED(ary) || OBJ_TAINTED(sep)) taint = Qtrue;
if (OBJ_UNTRUSTED(ary) || OBJ_UNTRUSTED(sep)) untrust = Qtrue;
for (i=0; i<RARRAY_LEN(ary); i++) {
tmp = rb_check_string_type(RARRAY_PTR(ary)[i]);
@ -1298,9 +1300,11 @@ rb_ary_join(VALUE ary, VALUE sep)
rb_str_buf_append(result, sep);
rb_str_buf_append(result, tmp);
if (OBJ_TAINTED(tmp)) taint = Qtrue;
if (OBJ_UNTRUSTED(tmp)) untrust = Qtrue;
}
if (taint) OBJ_TAINT(result);
if (untrust) OBJ_UNTRUST(result);
return result;
}
@ -1330,6 +1334,7 @@ static VALUE
inspect_ary(VALUE ary, VALUE dummy, int recur)
{
int tainted = OBJ_TAINTED(ary);
int untrust = OBJ_UNTRUSTED(ary);
long i;
VALUE s, str;
@ -1338,11 +1343,13 @@ inspect_ary(VALUE ary, VALUE dummy, int recur)
for (i=0; i<RARRAY_LEN(ary); i++) {
s = rb_inspect(RARRAY_PTR(ary)[i]);
if (OBJ_TAINTED(s)) tainted = Qtrue;
if (OBJ_UNTRUSTED(s)) untrust = Qtrue;
if (i > 0) rb_str_buf_cat2(str, ", ");
rb_str_buf_append(str, s);
}
rb_str_buf_cat2(str, "]");
if (tainted) OBJ_TAINT(str);
if (untrust) OBJ_UNTRUST(str);
return str;
}
@ -2952,7 +2959,7 @@ rb_ary_flatten(int argc, VALUE *argv, VALUE ary)
if (level == 0) return ary;
result = flatten(ary, level, &mod);
if (OBJ_TAINTED(ary)) OBJ_TAINT(result);
OBJ_INFECT(result, ary);
return result;
}

View file

@ -383,7 +383,7 @@ rb_include_module(VALUE klass, VALUE module)
int changed = 0;
rb_frozen_class_p(klass);
if (!OBJ_TAINTED(klass)) {
if (!OBJ_UNTRUSTED(klass)) {
rb_secure(4);
}
@ -833,6 +833,12 @@ rb_singleton_class(VALUE obj)
else {
FL_UNSET(klass, FL_TAINT);
}
if (OBJ_UNTRUSTED(obj)) {
OBJ_UNTRUST(klass);
}
else {
FL_UNSET(klass, FL_UNTRUSTED);
}
if (OBJ_FROZEN(obj)) OBJ_FREEZE(klass);
ALLOW_INTS;

View file

@ -35,6 +35,7 @@ static const union {
RUBY_FL_RESERVED = FL_RESERVED,
RUBY_FL_FINALIZE = FL_FINALIZE,
RUBY_FL_TAINT = FL_TAINT,
RUBY_FL_UNTRUSTED = FL_UNTRUSTED,
RUBY_FL_EXIVAR = FL_EXIVAR,
RUBY_FL_FREEZE = FL_FREEZE,
RUBY_FL_SINGLETON = FL_SINGLETON,
@ -57,7 +58,6 @@ static const union {
RUBY_FL_USER16 = FL_USER16,
RUBY_FL_USER17 = FL_USER17,
RUBY_FL_USER18 = FL_USER18,
RUBY_FL_USER19 = FL_USER19,
RUBY_FL_USHIFT = FL_USHIFT,
RUBY_NODE_TYPESHIFT = NODE_TYPESHIFT,
RUBY_NODE_TYPEMASK = NODE_TYPEMASK,
@ -67,7 +67,7 @@ static const union {
} various;
} dummy_gdb_enums;
const VALUE RUBY_FL_USER20 = FL_USER20;
const VALUE RUBY_FL_USER19 = FL_USER19;
int
ruby_debug_print_indent(int level, int debug_level, int indent_level)

6
dir.c
View file

@ -414,8 +414,8 @@ dir_closed(void)
static void
dir_check(VALUE dir)
{
if (!OBJ_TAINTED(dir) && rb_safe_level() >= 4)
rb_raise(rb_eSecurityError, "Insecure: operation on untainted Dir");
if (!OBJ_UNTRUSTED(dir) && rb_safe_level() >= 4)
rb_raise(rb_eSecurityError, "Insecure: operation on trusted Dir");
rb_check_frozen(dir);
}
@ -630,7 +630,7 @@ dir_rewind(VALUE dir)
{
struct dir_data *dirp;
if (rb_safe_level() >= 4 && !OBJ_TAINTED(dir)) {
if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(dir)) {
rb_raise(rb_eSecurityError, "Insecure: can't close");
}
GetDIR(dir, dirp);

4
hash.c
View file

@ -247,7 +247,7 @@ static void
rb_hash_modify_check(VALUE hash)
{
if (OBJ_FROZEN(hash)) rb_error_frozen("hash");
if (!OBJ_TAINTED(hash) && rb_safe_level() >= 4)
if (!OBJ_UNTRUSTED(hash) && rb_safe_level() >= 4)
rb_raise(rb_eSecurityError, "Insecure: can't modify hash");
}
@ -1166,7 +1166,7 @@ rb_hash_to_a(VALUE hash)
ary = rb_ary_new();
rb_hash_foreach(hash, to_a_i, ary);
if (OBJ_TAINTED(hash)) OBJ_TAINT(ary);
OBJ_INFECT(ary, hash);
return ary;
}

View file

@ -432,7 +432,7 @@ VALUE rb_newobj(void);
#define OBJSETUP(obj,c,t) do {\
RBASIC(obj)->flags = (t);\
RBASIC(obj)->klass = (c);\
if (rb_safe_level() >= 3) FL_SET(obj, FL_TAINT);\
if (rb_safe_level() >= 3) FL_SET(obj, FL_TAINT | FL_UNTRUSTED);\
} while (0)
#define CLONESETUP(clone,obj) do {\
OBJSETUP(clone,rb_singleton_class_clone((VALUE)obj),RBASIC(obj)->flags);\
@ -440,7 +440,7 @@ VALUE rb_newobj(void);
if (FL_TEST(obj, FL_EXIVAR)) rb_copy_generic_ivar((VALUE)clone,(VALUE)obj);\
} while (0)
#define DUPSETUP(dup,obj) do {\
OBJSETUP(dup,rb_obj_class(obj),(RBASIC(obj)->flags)&(T_MASK|FL_EXIVAR|FL_TAINT));\
OBJSETUP(dup,rb_obj_class(obj),(RBASIC(obj)->flags)&(T_MASK|FL_EXIVAR|FL_TAINT|FL_UNTRUSTED));\
if (FL_TEST(obj, FL_EXIVAR)) rb_copy_generic_ivar((VALUE)dup,(VALUE)obj);\
} while (0)
@ -693,10 +693,11 @@ struct RBignum {
#define FL_RESERVED (((VALUE)1)<<6) /* will be used in the future GC */
#define FL_FINALIZE (((VALUE)1)<<7)
#define FL_TAINT (((VALUE)1)<<8)
#define FL_EXIVAR (((VALUE)1)<<9)
#define FL_FREEZE (((VALUE)1)<<10)
#define FL_UNTRUSTED (((VALUE)1)<<9)
#define FL_EXIVAR (((VALUE)1)<<10)
#define FL_FREEZE (((VALUE)1)<<11)
#define FL_USHIFT 11
#define FL_USHIFT 12
#define FL_USER0 (((VALUE)1)<<(FL_USHIFT+0))
#define FL_USER1 (((VALUE)1)<<(FL_USHIFT+1))
@ -718,7 +719,6 @@ struct RBignum {
#define FL_USER17 (((VALUE)1)<<(FL_USHIFT+17))
#define FL_USER18 (((VALUE)1)<<(FL_USHIFT+18))
#define FL_USER19 (((VALUE)1)<<(FL_USHIFT+19))
#define FL_USER20 (((VALUE)1)<<(FL_USHIFT+20))
#define SPECIAL_CONST_P(x) (IMMEDIATE_P(x) || !RTEST(x))
@ -732,7 +732,9 @@ struct RBignum {
#define OBJ_TAINTED(x) FL_TEST((x), FL_TAINT)
#define OBJ_TAINT(x) FL_SET((x), FL_TAINT)
#define OBJ_INFECT(x,s) do {if (FL_ABLE(x) && FL_ABLE(s)) RBASIC(x)->flags |= RBASIC(s)->flags & FL_TAINT;} while (0)
#define OBJ_UNTRUSTED(x) FL_TEST((x), FL_UNTRUSTED)
#define OBJ_UNTRUST(x) FL_SET((x), FL_UNTRUSTED)
#define OBJ_INFECT(x,s) do {if (FL_ABLE(x) && FL_ABLE(s)) RBASIC(x)->flags |= RBASIC(s)->flags & (FL_TAINT | FL_UNTRUSTED);} while (0)
#define OBJ_FROZEN(x) FL_TEST((x), FL_FREEZE)
#define OBJ_FREEZE(x) FL_SET((x), FL_FREEZE)

13
io.c
View file

@ -227,8 +227,8 @@ rb_eof_error(void)
VALUE
rb_io_taint_check(VALUE io)
{
if (!OBJ_TAINTED(io) && rb_safe_level() >= 4)
rb_raise(rb_eSecurityError, "Insecure: operation on untainted IO");
if (!OBJ_UNTRUSTED(io) && rb_safe_level() >= 4)
rb_raise(rb_eSecurityError, "Insecure: operation on trusted IO");
rb_check_frozen(io);
return io;
}
@ -2819,7 +2819,7 @@ rb_io_close(VALUE io)
static VALUE
rb_io_close_m(VALUE io)
{
if (rb_safe_level() >= 4 && !OBJ_TAINTED(io)) {
if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(io)) {
rb_raise(rb_eSecurityError, "Insecure: can't close");
}
rb_io_check_closed(RFILE(io)->fptr);
@ -2902,7 +2902,7 @@ rb_io_close_read(VALUE io)
rb_io_t *fptr;
VALUE write_io;
if (rb_safe_level() >= 4 && !OBJ_TAINTED(io)) {
if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(io)) {
rb_raise(rb_eSecurityError, "Insecure: can't close");
}
GetOpenFile(io, fptr);
@ -2962,7 +2962,7 @@ rb_io_close_write(VALUE io)
rb_io_t *fptr;
VALUE write_io;
if (rb_safe_level() >= 4 && !OBJ_TAINTED(io)) {
if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(io)) {
rb_raise(rb_eSecurityError, "Insecure: can't close");
}
write_io = GetWriteIO(io);
@ -4430,7 +4430,8 @@ io_reopen(VALUE io, VALUE nfile)
off_t pos = 0;
nfile = rb_io_get_io(nfile);
if (rb_safe_level() >= 4 && (!OBJ_TAINTED(io) || !OBJ_TAINTED(nfile))) {
if (rb_safe_level() >= 4 &&
(!OBJ_UNTRUSTED(io) || !OBJ_UNTRUSTED(nfile))) {
rb_raise(rb_eSecurityError, "Insecure: can't reopen");
}
GetOpenFile(io, fptr);

View file

@ -137,6 +137,7 @@ struct dump_arg {
st_table *symbols;
st_table *data;
int taint;
int untrust;
st_table *compat_tbl;
VALUE wrapper;
st_table *encodings;
@ -192,6 +193,7 @@ w_nbyte(const char *s, int n, struct dump_arg *arg)
rb_str_buf_cat(buf, s, n);
if (arg->dest && RSTRING_LEN(buf) >= BUFSIZ) {
if (arg->taint) OBJ_TAINT(buf);
if (arg->untrust) OBJ_UNTRUST(buf);
rb_io_write(arg->dest, buf);
rb_str_resize(buf, 0);
}
@ -581,6 +583,7 @@ w_object(VALUE obj, struct dump_arg *arg, int limit)
}
else {
if (OBJ_TAINTED(obj)) arg->taint = Qtrue;
if (OBJ_UNTRUSTED(obj)) arg->untrust = Qtrue;
if (rb_respond_to(obj, s_mdump)) {
volatile VALUE v;
@ -809,6 +812,9 @@ dump_ensure(struct dump_arg *arg)
if (arg->taint) {
OBJ_TAINT(arg->str);
}
if (arg->untrust) {
OBJ_UNTRUST(arg->str);
}
return 0;
}
@ -878,6 +884,7 @@ marshal_dump(int argc, VALUE *argv)
arg.symbols = st_init_numtable();
arg.data = st_init_numtable();
arg.taint = Qfalse;
arg.untrust = Qfalse;
arg.compat_tbl = st_init_numtable();
arg.wrapper = Data_Wrap_Struct(rb_cData, mark_dump_arg, 0, &arg);
arg.encodings = 0;
@ -900,6 +907,7 @@ struct load_arg {
VALUE data;
VALUE proc;
int taint;
int untrust;
st_table *compat_tbl;
VALUE compat_tbl_wrapper;
};
@ -1014,6 +1022,7 @@ r_bytes0(long len, struct load_arg *arg)
StringValue(str);
if (RSTRING_LEN(str) != len) goto too_short;
if (OBJ_TAINTED(str)) arg->taint = Qtrue;
if (OBJ_UNTRUSTED(str)) arg->untrust = Qtrue;
}
return str;
}
@ -1084,6 +1093,11 @@ r_entry(VALUE v, struct load_arg *arg)
if ((VALUE)real_obj != Qundef)
OBJ_TAINT((VALUE)real_obj);
}
if (arg->untrust) {
OBJ_UNTRUST(v);
if ((VALUE)real_obj != Qundef)
OBJ_UNTRUST((VALUE)real_obj);
}
return v;
}

View file

@ -161,7 +161,7 @@ init_copy(VALUE dest, VALUE obj)
rb_raise(rb_eTypeError, "[bug] frozen object (%s) allocated", rb_obj_classname(dest));
}
RBASIC(dest)->flags &= ~(T_MASK|FL_EXIVAR);
RBASIC(dest)->flags |= RBASIC(obj)->flags & (T_MASK|FL_EXIVAR|FL_TAINT);
RBASIC(dest)->flags |= RBASIC(obj)->flags & (T_MASK|FL_EXIVAR|FL_TAINT|FL_UNTRUSTED);
rb_copy_generic_ivar(dest, obj);
rb_gc_copy_finalizer(dest, obj);
switch (TYPE(obj)) {
@ -234,7 +234,7 @@ rb_obj_clone(VALUE obj)
}
clone = rb_obj_alloc(rb_obj_class(obj));
RBASIC(clone)->klass = rb_singleton_class_clone(obj);
RBASIC(clone)->flags = (RBASIC(obj)->flags | FL_TEST(clone, FL_TAINT)) & ~(FL_FREEZE|FL_FINALIZE);
RBASIC(clone)->flags = (RBASIC(obj)->flags | FL_TEST(clone, FL_TAINT) | FL_TEST(clone, FL_UNTRUSTED)) & ~(FL_FREEZE|FL_FINALIZE);
init_copy(clone, obj);
RBASIC(clone)->flags |= RBASIC(obj)->flags & FL_FREEZE;
@ -302,7 +302,7 @@ rb_any_to_s(VALUE obj)
VALUE str;
str = rb_sprintf("#<%s:%p>", cname, (void*)obj);
if (OBJ_TAINTED(obj)) OBJ_TAINT(str);
OBJ_INFECT(str, obj);
return str;
}
@ -692,6 +692,62 @@ rb_obj_untaint(VALUE obj)
return obj;
}
/*
* call-seq:
* obj.untrusted? => true or false
*
* Returns <code>true</code> if the object is untrusted.
*/
VALUE
rb_obj_untrusted(VALUE obj)
{
if (OBJ_UNTRUSTED(obj))
return Qtrue;
return Qfalse;
}
/*
* call-seq:
* obj.untrust -> obj
*
* Marks <i>obj</i> as untrusted.
*/
VALUE
rb_obj_untrust(VALUE obj)
{
rb_secure(4);
if (!OBJ_UNTRUSTED(obj)) {
if (OBJ_FROZEN(obj)) {
rb_error_frozen("object");
}
OBJ_UNTRUST(obj);
}
return obj;
}
/*
* call-seq:
* obj.trust => obj
*
* Removes the untrusted mark from <i>obj</i>.
*/
VALUE
rb_obj_trust(VALUE obj)
{
rb_secure(3);
if (OBJ_UNTRUSTED(obj)) {
if (OBJ_FROZEN(obj)) {
rb_error_frozen("object");
}
FL_UNSET(obj, FL_UNTRUSTED);
}
return obj;
}
void
rb_obj_infect(VALUE obj1, VALUE obj2)
{
@ -723,7 +779,7 @@ VALUE
rb_obj_freeze(VALUE obj)
{
if (!OBJ_FROZEN(obj)) {
if (rb_safe_level() >= 4 && !OBJ_TAINTED(obj)) {
if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(obj)) {
rb_raise(rb_eSecurityError, "Insecure: can't freeze object");
}
OBJ_FREEZE(obj);
@ -2419,6 +2475,9 @@ Init_Object(void)
rb_define_method(rb_mKernel, "taint", rb_obj_taint, 0);
rb_define_method(rb_mKernel, "tainted?", rb_obj_tainted, 0);
rb_define_method(rb_mKernel, "untaint", rb_obj_untaint, 0);
rb_define_method(rb_mKernel, "untrust", rb_obj_untrust, 0);
rb_define_method(rb_mKernel, "untrusted?", rb_obj_untrusted, 0);
rb_define_method(rb_mKernel, "trust", rb_obj_trust, 0);
rb_define_method(rb_mKernel, "freeze", rb_obj_freeze, 0);
rb_define_method(rb_mKernel, "frozen?", rb_obj_frozen_p, 0);

2
re.c
View file

@ -2299,7 +2299,7 @@ rb_reg_initialize(VALUE obj, const char *s, int len, rb_encoding *enc,
rb_encoding *fixed_enc = 0;
rb_encoding *a_enc = rb_ascii8bit_encoding();
if (!OBJ_TAINTED(obj) && rb_safe_level() >= 4)
if (!OBJ_UNTRUSTED(obj) && rb_safe_level() >= 4)
rb_raise(rb_eSecurityError, "Insecure: can't modify regexp");
rb_check_frozen(obj);
if (FL_TEST(obj, REG_LITERAL))

4
ruby.c
View file

@ -1069,12 +1069,12 @@ process_options(VALUE arg)
#endif
opt->script_name = rb_str_new4(rb_progname);
opt->script = RSTRING_PTR(opt->script_name);
safe = rb_safe_level();
rb_set_safe_level_force(0);
ruby_set_argv(argc, argv);
process_sflag(opt);
ruby_init_loadpath();
safe = rb_safe_level();
rb_set_safe_level_force(0);
ruby_init_gems(!(opt->disable & DISABLE_BIT(gems)));
lenc = rb_locale_encoding();
for (i = 0; i < RARRAY_LEN(rb_argv); i++) {

View file

@ -1027,7 +1027,7 @@ str_modifiable(VALUE str)
rb_raise(rb_eRuntimeError, "can't modify string; temporarily locked");
}
if (OBJ_FROZEN(str)) rb_error_frozen("string");
if (!OBJ_TAINTED(str) && rb_safe_level() >= 4)
if (!OBJ_UNTRUSTED(str) && rb_safe_level() >= 4)
rb_raise(rb_eSecurityError, "Insecure: can't modify string");
}
@ -3170,6 +3170,7 @@ rb_str_sub_bang(int argc, VALUE *argv, VALUE str)
VALUE pat, repl, hash = Qnil;
int iter = 0;
int tainted = 0;
int untrusted = 0;
long plen;
if (argc == 1 && rb_block_given_p()) {
@ -3182,6 +3183,7 @@ rb_str_sub_bang(int argc, VALUE *argv, VALUE str)
StringValue(repl);
}
if (OBJ_TAINTED(repl)) tainted = 1;
if (OBJ_UNTRUSTED(repl)) untrusted = 1;
}
else {
rb_raise(rb_eArgError, "wrong number of arguments (%d for 2)", argc);
@ -3227,6 +3229,7 @@ rb_str_sub_bang(int argc, VALUE *argv, VALUE str)
rb_str_modify(str);
rb_enc_associate(str, enc);
if (OBJ_TAINTED(repl)) tainted = 1;
if (OBJ_UNTRUSTED(repl)) untrusted = 1;
if (ENC_CODERANGE_UNKNOWN < cr && cr < ENC_CODERANGE_BROKEN) {
int cr2 = ENC_CODERANGE(repl);
if (cr2 == ENC_CODERANGE_UNKNOWN || cr2 > cr) cr = cr2;
@ -3246,6 +3249,7 @@ rb_str_sub_bang(int argc, VALUE *argv, VALUE str)
RSTRING_PTR(str)[RSTRING_LEN(str)] = '\0';
ENC_CODERANGE_SET(str, cr);
if (tainted) OBJ_TAINT(str);
if (untrusted) OBJ_UNTRUST(str);
return str;
}

View file

@ -144,7 +144,7 @@ static void
rb_struct_modify(VALUE s)
{
if (OBJ_FROZEN(s)) rb_error_frozen("Struct");
if (!OBJ_TAINTED(s) && rb_safe_level() >= 4)
if (!OBJ_UNTRUSTED(s) && rb_safe_level() >= 4)
rb_raise(rb_eSecurityError, "Insecure: can't modify Struct");
}

View file

@ -451,16 +451,20 @@ class TestArray < Test::Unit::TestCase
def test_clone
for taint in [ false, true ]
for frozen in [ false, true ]
a = @cls[*(0..99).to_a]
a.taint if taint
a.freeze if frozen
b = a.clone
for untrust in [ false, true ]
for frozen in [ false, true ]
a = @cls[*(0..99).to_a]
a.taint if taint
a.untrust if untrust
a.freeze if frozen
b = a.clone
assert_equal(a, b)
assert(a.__id__ != b.__id__)
assert_equal(a.frozen?, b.frozen?)
assert_equal(a.tainted?, b.tainted?)
assert_equal(a, b)
assert(a.__id__ != b.__id__)
assert_equal(a.frozen?, b.frozen?)
assert_equal(a.untrusted?, b.untrusted?)
assert_equal(a.tainted?, b.tainted?)
end
end
end
end
@ -708,6 +712,13 @@ class TestArray < Test::Unit::TestCase
@cls[@cls[@cls[@cls[],@cls[]],@cls[@cls[]],@cls[]],@cls[@cls[@cls[]]]].flatten)
assert_raise(TypeError, "[ruby-dev:31197]") { [[]].flatten("") }
a6 = @cls[[1, 2], 3]
a6.taint
a6.untrust
a7 = a6.flatten
assert_equal(true, a7.tainted?)
assert_equal(true, a7.untrusted?)
end
def test_flatten!
@ -797,6 +808,12 @@ class TestArray < Test::Unit::TestCase
assert_equal("1,2,3", a.join(','))
$, = ""
a = @cls[1, 2, 3]
a.taint
a.untrust
s = a.join
assert_equal(true, s.tainted?)
assert_equal(true, s.untrusted?)
end
def test_last
@ -1574,4 +1591,13 @@ class TestArray < Test::Unit::TestCase
def test_array_subclass
assert_equal(Array2, Array2[1,2,3].uniq.class, "[ruby-dev:34581]")
end
def test_inspect
a = @cls[1, 2, 3]
a.taint
a.untrust
s = a.inspect
assert_equal(true, s.tainted?)
assert_equal(true, s.untrusted?)
end
end

View file

@ -206,16 +206,20 @@ class TestHash < Test::Unit::TestCase
def test_clone
for taint in [ false, true ]
for frozen in [ false, true ]
a = @h.clone
a.taint if taint
a.freeze if frozen
b = a.clone
for untrust in [ false, true ]
for frozen in [ false, true ]
a = @h.clone
a.taint if taint
a.untrust if untrust
a.freeze if frozen
b = a.clone
assert_equal(a, b)
assert(a.__id__ != b.__id__)
assert_equal(a.frozen?, b.frozen?)
assert_equal(a.tainted?, b.tainted?)
assert_equal(a, b)
assert(a.__id__ != b.__id__)
assert_equal(a.frozen?, b.frozen?)
assert_equal(a.untrusted?, b.untrusted?)
assert_equal(a.tainted?, b.tainted?)
end
end
end
end
@ -288,16 +292,19 @@ class TestHash < Test::Unit::TestCase
def test_dup
for taint in [ false, true ]
for frozen in [ false, true ]
a = @h.dup
a.taint if taint
a.freeze if frozen
b = a.dup
for untrust in [ false, true ]
for frozen in [ false, true ]
a = @h.dup
a.taint if taint
a.freeze if frozen
b = a.dup
assert_equal(a, b)
assert(a.__id__ != b.__id__)
assert_equal(false, b.frozen?)
assert_equal(a.tainted?, b.tainted?)
assert_equal(a, b)
assert(a.__id__ != b.__id__)
assert_equal(false, b.frozen?)
assert_equal(a.tainted?, b.tainted?)
assert_equal(a.untrusted?, b.untrusted?)
end
end
end
end
@ -599,6 +606,13 @@ class TestHash < Test::Unit::TestCase
assert_equal([3,4], a.delete([3,4]))
assert_equal([5,6], a.delete([5,6]))
assert_equal(0, a.length)
h = @cls[ 1=>2, 3=>4, 5=>6 ]
h.taint
h.untrust
a = h.to_a
assert_equal(true, a.tainted?)
assert_equal(true, a.untrusted?)
end
def test_to_hash

View file

@ -179,4 +179,16 @@ class TestMarshal < Test::Unit::TestCase
Marshal.dump((0..1000).map {|x| C4.new(x % 50 == 25) })
end
end
def test_taint_and_untrust
x = Object.new
x.taint
x.untrust
s = Marshal.dump(x)
assert_equal(true, s.tainted?)
assert_equal(true, s.untrusted?)
y = Marshal.load(s)
assert_equal(true, y.tainted?)
assert_equal(true, y.untrusted?)
end
end

View file

@ -699,4 +699,22 @@ class TestModule < Test::Unit::TestCase
assert_equal(true, c2.include?(m))
assert_equal(false, m.include?(m))
end
def test_include_under_safe4
m = Module.new
c1 = Class.new
assert_raise(SecurityError) do
lambda {
$SAFE = 4
c1.instance_eval { include(m) }
}.call
end
assert_nothing_raised do
lambda {
$SAFE = 4
c2 = Class.new
c2.instance_eval { include(m) }
}.call
end
end
end

View file

@ -320,4 +320,82 @@ class TestObject < Test::Unit::TestCase
1.extend
end
end
def test_untrusted
obj = lambda {
$SAFE = 4
x = Object.new
x.instance_eval { @foo = 1 }
x
}.call
assert_equal(true, obj.untrusted?)
assert_equal(true, obj.tainted?)
x = Object.new
assert_equal(false, x.untrusted?)
assert_raise(SecurityError) do
lambda {
$SAFE = 4
x.instance_eval { @foo = 1 }
}.call
end
x = Object.new
x.taint
assert_raise(SecurityError) do
lambda {
$SAFE = 4
x.instance_eval { @foo = 1 }
}.call
end
x.untrust
assert_equal(true, x.untrusted?)
assert_nothing_raised do
lambda {
$SAFE = 4
x.instance_eval { @foo = 1 }
}.call
end
x.trust
assert_equal(false, x.untrusted?)
assert_raise(SecurityError) do
lambda {
$SAFE = 4
x.instance_eval { @foo = 1 }
}.call
end
a = Object.new
a.untrust
assert_equal(true, a.untrusted?)
b = a.dup
assert_equal(true, b.untrusted?)
c = a.clone
assert_equal(true, c.untrusted?)
a = Object.new
b = lambda {
$SAFE = 4
a.dup
}.call
assert_equal(true, b.untrusted?)
a = Object.new
b = lambda {
$SAFE = 4
a.clone
}.call
assert_equal(true, b.untrusted?)
end
def test_to_s
x = Object.new
x.taint
x.untrust
s = x.to_s
assert_equal(true, s.untrusted?)
assert_equal(true, s.tainted?)
end
end

View file

@ -427,16 +427,20 @@ class TestString < Test::Unit::TestCase
def test_clone
for taint in [ false, true ]
for frozen in [ false, true ]
a = S("Cool")
a.taint if taint
a.freeze if frozen
b = a.clone
for untrust in [ false, true ]
for frozen in [ false, true ]
a = S("Cool")
a.taint if taint
a.untrust if untrust
a.freeze if frozen
b = a.clone
assert_equal(a, b)
assert(a.__id__ != b.__id__)
assert_equal(a.frozen?, b.frozen?)
assert_equal(a.tainted?, b.tainted?)
assert_equal(a, b)
assert(a.__id__ != b.__id__)
assert_equal(a.frozen?, b.frozen?)
assert_equal(a.untrusted?, b.untrusted?)
assert_equal(a.tainted?, b.tainted?)
end
end
end
@ -532,16 +536,20 @@ class TestString < Test::Unit::TestCase
def test_dup
for taint in [ false, true ]
for frozen in [ false, true ]
a = S("hello")
a.taint if taint
a.freeze if frozen
b = a.dup
for untrust in [ false, true ]
for frozen in [ false, true ]
a = S("hello")
a.taint if taint
a.untrust if untrust
a.freeze if frozen
b = a.dup
assert_equal(a, b)
assert(a.__id__ != b.__id__)
assert(!b.frozen?)
assert_equal(a.tainted?, b.tainted?)
assert_equal(a, b)
assert(a.__id__ != b.__id__)
assert(!b.frozen?)
assert_equal(a.tainted?, b.tainted?)
assert_equal(a.untrusted?, b.untrusted?)
end
end
end
end
@ -623,7 +631,9 @@ class TestString < Test::Unit::TestCase
a = S("hello")
a.taint
a.untrust
assert(a.gsub(/./, S('X')).tainted?)
assert(a.gsub(/./, S('X')).untrusted?)
assert_equal("z", "abc".gsub(/./, "a" => "z"), "moved from btest/knownbug")
@ -651,8 +661,10 @@ class TestString < Test::Unit::TestCase
r = S('X')
r.taint
r.untrust
a.gsub!(/./, r)
assert(a.tainted?)
assert(a.untrusted?)
a = S("hello")
assert_nil(a.sub!(S('X'), S('Y')))
@ -823,9 +835,11 @@ class TestString < Test::Unit::TestCase
a = S("foo")
a.taint
a.untrust
b = a.replace(S("xyz"))
assert_equal(S("xyz"), b)
assert(b.tainted?)
assert(b.untrusted?)
s = "foo" * 100
s2 = ("bar" * 100).dup
@ -1170,7 +1184,10 @@ class TestString < Test::Unit::TestCase
a = S("hello")
a.taint
assert(a.sub(/./, S('X')).tainted?)
a.untrust
x = a.sub(/./, S('X'))
assert(x.tainted?)
assert(x.untrusted?)
o = Object.new
def o.to_str; "bar"; end
@ -1211,8 +1228,10 @@ class TestString < Test::Unit::TestCase
r = S('X')
r.taint
r.untrust
a.sub!(/./, r)
assert(a.tainted?)
assert(a.untrusted?)
end
def test_succ

2
time.c
View file

@ -60,7 +60,7 @@ static void
time_modify(VALUE time)
{
rb_check_frozen(time);
if (!OBJ_TAINTED(time) && rb_safe_level() >= 4)
if (!OBJ_UNTRUSTED(time) && rb_safe_level() >= 4)
rb_raise(rb_eSecurityError, "Insecure: can't modify Time");
}

View file

@ -995,7 +995,7 @@ rb_ivar_set(VALUE obj, ID id, VALUE val)
long i, len;
int ivar_extended;
if (!OBJ_TAINTED(obj) && rb_safe_level() >= 4)
if (!OBJ_UNTRUSTED(obj) && rb_safe_level() >= 4)
rb_raise(rb_eSecurityError, "Insecure: can't modify instance variable");
if (OBJ_FROZEN(obj)) rb_error_frozen("object");
switch (TYPE(obj)) {
@ -1216,7 +1216,7 @@ rb_obj_remove_instance_variable(VALUE obj, VALUE name)
struct st_table *iv_index_tbl;
st_data_t index;
if (!OBJ_TAINTED(obj) && rb_safe_level() >= 4)
if (!OBJ_UNTRUSTED(obj) && rb_safe_level() >= 4)
rb_raise(rb_eSecurityError, "Insecure: can't modify instance variable");
if (OBJ_FROZEN(obj)) rb_error_frozen("object");
if (!rb_is_instance_id(id)) {
@ -1505,7 +1505,7 @@ rb_mod_remove_const(VALUE mod, VALUE name)
if (!rb_is_const_id(id)) {
rb_name_error(id, "`%s' is not allowed as a constant name", rb_id2name(id));
}
if (!OBJ_TAINTED(mod) && rb_safe_level() >= 4)
if (!OBJ_UNTRUSTED(mod) && rb_safe_level() >= 4)
rb_raise(rb_eSecurityError, "Insecure: can't remove constant");
if (OBJ_FROZEN(mod)) rb_error_frozen("class/module");
@ -1667,7 +1667,7 @@ mod_av_set(VALUE klass, ID id, VALUE val, int isconst)
{
const char *dest = isconst ? "constant" : "class variable";
if (!OBJ_TAINTED(klass) && rb_safe_level() >= 4)
if (!OBJ_UNTRUSTED(klass) && rb_safe_level() >= 4)
rb_raise(rb_eSecurityError, "Insecure: can't set %s", dest);
if (OBJ_FROZEN(klass)) {
if (BUILTIN_TYPE(klass) == T_MODULE) {
@ -1922,7 +1922,7 @@ rb_mod_remove_cvar(VALUE mod, VALUE name)
if (!rb_is_class_id(id)) {
rb_name_error(id, "wrong class variable name %s", rb_id2name(id));
}
if (!OBJ_TAINTED(mod) && rb_safe_level() >= 4)
if (!OBJ_UNTRUSTED(mod) && rb_safe_level() >= 4)
rb_raise(rb_eSecurityError, "Insecure: can't remove class variable");
if (OBJ_FROZEN(mod)) rb_error_frozen("class/module");

View file

@ -108,7 +108,8 @@ rb_add_method(VALUE klass, ID mid, NODE * node, int noex)
if (NIL_P(klass)) {
klass = rb_cObject;
}
if (rb_safe_level() >= 4 && (klass == rb_cObject || !OBJ_TAINTED(klass))) {
if (rb_safe_level() >= 4 &&
(klass == rb_cObject || !OBJ_UNTRUSTED(klass))) {
rb_raise(rb_eSecurityError, "Insecure: can't define method");
}
if (!FL_TEST(klass, FL_SINGLETON) &&
@ -307,7 +308,7 @@ remove_method(VALUE klass, ID mid)
if (klass == rb_cObject) {
rb_secure(4);
}
if (rb_safe_level() >= 4 && !OBJ_TAINTED(klass)) {
if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(klass)) {
rb_raise(rb_eSecurityError, "Insecure: can't remove method");
}
if (OBJ_FROZEN(klass))
@ -474,7 +475,7 @@ rb_undef(VALUE klass, ID id)
if (rb_vm_cbase() == rb_cObject && klass == rb_cObject) {
rb_secure(4);
}
if (rb_safe_level() >= 4 && !OBJ_TAINTED(klass)) {
if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(klass)) {
rb_raise(rb_eSecurityError, "Insecure: can't undef `%s'",
rb_id2name(id));
}
@ -810,7 +811,7 @@ rb_mod_alias_method(VALUE mod, VALUE newname, VALUE oldname)
static void
secure_visibility(VALUE self)
{
if (rb_safe_level() >= 4 && !OBJ_TAINTED(self)) {
if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(self)) {
rb_raise(rb_eSecurityError,
"Insecure: can't change method visibility");
}