[ruby-dev:35833] Re: $SAFEの今後
From:
"Shugo Maeda" <shugo@...>
Date:
2008-08-12 16:14:21 UTC
List:
ruby-dev #35833
前田です。 2008/07/02 18:17 Shugo Maeda <shugo@ruby-lang.org>: >> taint(汚染)が二種類になるので名前を考えないといけません。ま >> た、それぞれのレベルの汚染を操作するメソッドについても考えな >> いといけません。まあ、いずれも技術的な問題ではありませんが。 > > untrusted?はどうでしょう。 > # untrust/trustがtaint/untaint相当。 とりあえず、上記の名前で実装してみました。 パッチを添付します。 -- Shugo Maeda
Attachments (1)
untrusted.diff
(20 KB, text/x-diff)
Index: array.c
===================================================================
--- array.c (revision 18544)
+++ array.c (working copy)
@@ -54,7 +54,7 @@
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");
}
Index: debug.c
===================================================================
--- debug.c (revision 18544)
+++ debug.c (working copy)
@@ -67,8 +67,6 @@
} various;
} dummy_gdb_enums;
-const VALUE RUBY_FL_USER20 = FL_USER20;
-
int
ruby_debug_print_indent(int level, int debug_level, int indent_level)
{
Index: time.c
===================================================================
--- time.c (revision 18544)
+++ time.c (working copy)
@@ -60,7 +60,7 @@
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");
}
Index: include/ruby/ruby.h
===================================================================
--- include/ruby/ruby.h (revision 18544)
+++ include/ruby/ruby.h (working copy)
@@ -432,7 +432,7 @@
#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 @@
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 @@
#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 @@
#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 @@
#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)
Index: re.c
===================================================================
--- re.c (revision 18544)
+++ re.c (working copy)
@@ -2299,7 +2299,7 @@
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))
Index: variable.c
===================================================================
--- variable.c (revision 18544)
+++ variable.c (working copy)
@@ -995,7 +995,7 @@
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 @@
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 @@
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 @@
{
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 @@
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");
Index: object.c
===================================================================
--- object.c (revision 18544)
+++ object.c (working copy)
@@ -161,7 +161,7 @@
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)) {
@@ -692,6 +692,62 @@
return obj;
}
+/*
+ * call-seq:
+ * obj.untrusted? => true or false
+ *
+ * Returns <code>true</code> if the object is untainted.
+ */
+
+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 @@
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 @@
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);
Index: string.c
===================================================================
--- string.c (revision 18544)
+++ string.c (working copy)
@@ -1027,7 +1027,7 @@
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 @@
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 @@
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_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 @@
RSTRING_PTR(str)[RSTRING_LEN(str)] = '\0';
ENC_CODERANGE_SET(str, cr);
if (tainted) OBJ_TAINT(str);
+ if (untrusted) OBJ_UNTRUST(str);
return str;
}
Index: io.c
===================================================================
--- io.c (revision 18544)
+++ io.c (working copy)
@@ -227,8 +227,8 @@
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 @@
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_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_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 @@
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);
Index: dir.c
===================================================================
--- dir.c (revision 18544)
+++ dir.c (working copy)
@@ -414,8 +414,8 @@
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 @@
{
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);
Index: vm_method.c
===================================================================
--- vm_method.c (revision 18544)
+++ vm_method.c (working copy)
@@ -108,7 +108,8 @@
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 @@
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 @@
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 @@
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");
}
Index: struct.c
===================================================================
--- struct.c (revision 18544)
+++ struct.c (working copy)
@@ -144,7 +144,7 @@
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");
}
Index: class.c
===================================================================
--- class.c (revision 18544)
+++ class.c (working copy)
@@ -833,6 +833,12 @@
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;
Index: hash.c
===================================================================
--- hash.c (revision 18544)
+++ hash.c (working copy)
@@ -247,7 +247,7 @@
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");
}
Index: ruby.c
===================================================================
--- ruby.c (revision 18544)
+++ ruby.c (working copy)
@@ -1069,12 +1069,12 @@
#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++) {
Index: test/ruby/test_array.rb
===================================================================
--- test/ruby/test_array.rb (revision 18544)
+++ test/ruby/test_array.rb (working copy)
@@ -451,16 +451,20 @@
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
Index: test/ruby/test_string.rb
===================================================================
--- test/ruby/test_string.rb (revision 18544)
+++ test/ruby/test_string.rb (working copy)
@@ -427,16 +427,20 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
r = S('X')
r.taint
+ r.untrust
a.sub!(/./, r)
assert(a.tainted?)
+ assert(a.untrusted?)
end
def test_succ
Index: test/ruby/test_object.rb
===================================================================
--- test/ruby/test_object.rb (revision 18544)
+++ test/ruby/test_object.rb (working copy)
@@ -320,4 +320,59 @@
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?)
+ end
end