Skip to content

Commit

Permalink
* object.c (rb_obj_untrusted): new method Object#untrusted?.
Browse files Browse the repository at this point in the history
  (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
  • Loading branch information
shugo committed Aug 13, 2008
1 parent 55c141c commit f433d71
Show file tree
Hide file tree
Showing 23 changed files with 369 additions and 93 deletions.
15 changes: 15 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
Wed Aug 13 16:02:14 2008 Shugo Maeda <[email protected]>

* 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 <[email protected]>

* test/ruby/test_m17n.rb: follow EncodingCompatibilityError.
Expand Down
11 changes: 9 additions & 2 deletions array.c
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}

Expand Down Expand Up @@ -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]);
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;

Expand All @@ -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;
}

Expand Down Expand Up @@ -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;
}
Expand Down
8 changes: 7 additions & 1 deletion class.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down Expand Up @@ -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;

Expand Down
4 changes: 2 additions & 2 deletions debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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,
Expand All @@ -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)
Expand Down
6 changes: 3 additions & 3 deletions dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down Expand Up @@ -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);
Expand Down
4 changes: 2 additions & 2 deletions hash.c
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}

Expand Down Expand Up @@ -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;
}
Expand Down
16 changes: 9 additions & 7 deletions include/ruby/ruby.h
Original file line number Diff line number Diff line change
Expand Up @@ -432,15 +432,15 @@ 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);\
rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone);\
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)

Expand Down Expand Up @@ -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))
Expand All @@ -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))

Expand All @@ -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)
Expand Down
13 changes: 7 additions & 6 deletions io.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
14 changes: 14 additions & 0 deletions marshal.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
Expand All @@ -900,6 +907,7 @@ struct load_arg {
VALUE data;
VALUE proc;
int taint;
int untrust;
st_table *compat_tbl;
VALUE compat_tbl_wrapper;
};
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
}

Expand Down
Loading

0 comments on commit f433d71

Please sign in to comment.