[前][次][番号順一覧][スレッド一覧]

ruby-changes:7050

From: shugo <ko1@a...>
Date: Wed, 13 Aug 2008 16:26:06 +0900 (JST)
Subject: [ruby-changes:7050] Ruby:r18568 (trunk): * object.c (rb_obj_untrusted): new method Object#untrusted?.

shugo	2008-08-13 16:25:05 +0900 (Wed, 13 Aug 2008)

  New Revision: 18568

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=18568

  Log:
    * 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?.

  Modified files:
    trunk/ChangeLog
    trunk/array.c
    trunk/class.c
    trunk/debug.c
    trunk/dir.c
    trunk/hash.c
    trunk/include/ruby/ruby.h
    trunk/io.c
    trunk/marshal.c
    trunk/object.c
    trunk/re.c
    trunk/ruby.c
    trunk/string.c
    trunk/struct.c
    trunk/test/ruby/test_array.rb
    trunk/test/ruby/test_hash.rb
    trunk/test/ruby/test_marshal.rb
    trunk/test/ruby/test_module.rb
    trunk/test/ruby/test_object.rb
    trunk/test/ruby/test_string.rb
    trunk/time.c
    trunk/variable.c
    trunk/vm_method.c

Index: array.c
===================================================================
--- array.c	(revision 18567)
+++ array.c	(revision 18568)
@@ -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");
 }
 
@@ -1263,10 +1263,12 @@
 {
     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_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 @@
 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 @@
     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 @@
     if (level == 0) return ary;
 
     result = flatten(ary, level, &mod);
-    if (OBJ_TAINTED(ary)) OBJ_TAINT(result);
+    OBJ_INFECT(result, ary);
 
     return result;
 }
Index: debug.c
===================================================================
--- debug.c	(revision 18567)
+++ debug.c	(revision 18568)
@@ -35,6 +35,7 @@
         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 @@
         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 @@
     } 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)
Index: time.c
===================================================================
--- time.c	(revision 18567)
+++ time.c	(revision 18568)
@@ -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 18567)
+++ include/ruby/ruby.h	(revision 18568)
@@ -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 18567)
+++ re.c	(revision 18568)
@@ -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: ChangeLog
===================================================================
--- ChangeLog	(revision 18567)
+++ ChangeLog	(revision 18568)
@@ -1,3 +1,18 @@
+Wed Aug 13 16:02:14 2008  Shugo Maeda  <shugo@r...>
+
+	* 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@r...>
 
 	* test/ruby/test_m17n.rb: follow EncodingCompatibilityError.
Index: variable.c
===================================================================
--- variable.c	(revision 18567)
+++ variable.c	(revision 18568)
@@ -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: string.c
===================================================================
--- string.c	(revision 18567)
+++ string.c	(revision 18568)
@@ -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: object.c
===================================================================
--- object.c	(revision 18567)
+++ object.c	(revision 18568)
@@ -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)) {
@@ -234,7 +234,7 @@
     }
     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 @@
     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 @@
     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 @@
 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: io.c
===================================================================
--- io.c	(revision 18567)
+++ io.c	(revision 18568)
@@ -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 18567)
+++ dir.c	(revision 18568)
@@ -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 18567)
+++ vm_method.c	(revision 18568)
@@ -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 18567)
+++ struct.c	(revision 18568)
@@ -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 18567)
+++ class.c	(revision 18568)
@@ -383,7 +383,7 @@
     int changed = 0;
 
     rb_frozen_class_p(klass);
-    if (!OBJ_TAINTED(klass)) {
+    if (!OBJ_UNTRUSTED(klass)) {
 	rb_secure(4);
     }
     
@@ -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 18567)
+++ hash.c	(revision 18568)
@@ -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");
 }
 
@@ -1166,7 +1166,7 @@
 
     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;
 }
Index: ruby.c
===================================================================
--- ruby.c	(revision 18567)
+++ ruby.c	(revision 18568)
@@ -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: marshal.c
===================================================================
--- marshal.c	(revision 18567)
+++ marshal.c	(revision 18568)
@@ -137,6 +137,7 @@
     st_table *symbols;
     st_table *data;
     int taint;
+    int untrust;
     st_table *compat_tbl;
     VALUE wrapper;
     st_table *encodings;
@@ -192,6 +193,7 @@
     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 @@
     }
     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 @@
     if (arg->taint) {
 	OBJ_TAINT(arg->str);
     }
+    if (arg->untrust) {
+	OBJ_UNTRUST(arg->str);
+    }
     return 0;
 }
 
@@ -878,6 +884,7 @@
     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 @@
     VALUE data;
     VALUE proc;
     int taint;
+    int untrust;
     st_table *compat_tbl;
     VALUE compat_tbl_wrapper;
 };
@@ -1014,6 +1022,7 @@
 	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 @@
         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;
 }
 
Index: test/ruby/test_module.rb
===================================================================
--- test/ruby/test_module.rb	(revision 18567)
+++ test/ruby/test_module.rb	(revision 18568)
@@ -699,4 +699,22 @@
     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
Index: test/ruby/test_array.rb
===================================================================
--- test/ruby/test_array.rb	(revision 18567)
+++ test/ruby/test_array.rb	(revision 18568)
@@ -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
@@ -708,6 +712,13 @@
                  @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 @@
     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 @@
   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
Index: test/ruby/test_object.rb
===================================================================
--- test/ruby/test_object.rb	(revision 18567)
+++ test/ruby/test_object.rb	(revision 18568)
@@ -320,4 +320,82 @@
       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
Index: test/ruby/test_string.rb
===================================================================
--- test/ruby/test_string.rb	(revision 18567)
+++ test/ruby/test_string.rb	(revision 18568)
@@ -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_marshal.rb
===================================================================
--- test/ruby/test_marshal.rb	(revision 18567)
+++ test/ruby/test_marshal.rb	(revision 18568)
@@ -179,4 +179,16 @@
       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
Index: test/ruby/test_hash.rb
===================================================================
--- test/ruby/test_hash.rb	(revision 18567)
+++ test/ruby/test_hash.rb	(revision 18568)
@@ -206,16 +206,20 @@
 
   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 @@
 
   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 @@
     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

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]