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

ruby-changes:49395

From: ko1 <ko1@a...>
Date: Fri, 29 Dec 2017 05:09:34 +0900 (JST)
Subject: [ruby-changes:49395] ko1:r61510 (trunk): `$SAFE` as a process global state. [Feature #14250]

ko1	2017-12-29 05:09:24 +0900 (Fri, 29 Dec 2017)

  New Revision: 61510

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=61510

  Log:
    `$SAFE` as a process global state. [Feature #14250]
    
    * vm_core.h (rb_vm_t): move `rb_execution_context_t::safe_level` to
      `rb_vm_t::safe_level_` because `$SAFE` is a process (VM) global state.
    
    * vm_core.h (rb_proc_t): remove `rb_proc_t::safe_level` because `Proc`
      objects don't need to keep `$SAFE` at the creation.
      Also make `is_from_method` and `is_lambda` as 1 bit fields.
    
    * cont.c (cont_restore_thread): no need to keep `$SAFE` for Continuation.
    
    * eval.c (ruby_cleanup): use `rb_set_safe_level_force()` instead of access
      `vm->safe_level_` directly.
    
    * eval_jump.c: End procs `END{}` doesn't keep `$SAFE`.
    
    * proc.c (proc_dup): removed and introduce `rb_proc_dup` in vm.c.
    
    * safe.c (rb_set_safe_level): don't check `$SAFE` 1 -> 0 changes.
    
    * safe.c (safe_setter): use `rb_set_safe_level()`.
    
    * thread.c (rb_thread_safe_level): `Thread#safe_level` returns `$SAFE`.
      It should be obsolete.
    
    * transcode.c (load_transcoder_entry): `rb_safe_level()` only returns
      0 or 1 so that this check is not needed.
    
    * vm.c (vm_proc_create_from_captured): don't need to keep `$SAFE` for Proc.
    
    * vm.c (rb_proc_create): renamed to `proc_create`.
    
    * vm.c (rb_proc_dup): moved from proc.c.
    
    * vm.c (vm_invoke_proc): do not need to set and restore `$SAFE`
      for `Proc#call`.
    
    * vm_eval.c (rb_eval_cmd): rename a local variable to represent clearer
      meaning.
    
    * lib/drb/drb.rb: restore `$SAFE`.
    
    * lib/erb.rb: restore `$SAFE`, too.
    
    * test/lib/leakchecker.rb: check `$SAFE == 0` at the end of tests.
    
    * test/rubygems/test_gem.rb: do not set `$SAFE = 1`.
    
    * bootstraptest/test_proc.rb: catch up this change.
    
    * spec/ruby/optional/capi/string_spec.rb: ditto.
    
    * test/bigdecimal/test_bigdecimal.rb: ditto.
    
    * test/fiddle/test_func.rb: ditto.
    
    * test/fiddle/test_handle.rb: ditto.
    
    * test/net/imap/test_imap_response_parser.rb: ditto.
    
    * test/pathname/test_pathname.rb: ditto.
    
    * test/readline/test_readline.rb: ditto.
    
    * test/ruby/test_file.rb: ditto.
    
    * test/ruby/test_optimization.rb: ditto.
    
    * test/ruby/test_proc.rb: ditto.
    
    * test/ruby/test_require.rb: ditto.
    
    * test/ruby/test_thread.rb: ditto.
    
    * test/rubygems/test_gem_specification.rb: ditto.
    
    * test/test_tempfile.rb: ditto.
    
    * test/test_tmpdir.rb: ditto.
    
    * test/win32ole/test_win32ole.rb: ditto.
    
    * test/win32ole/test_win32ole_event.rb: ditto.

  Modified files:
    trunk/NEWS
    trunk/bootstraptest/test_proc.rb
    trunk/cont.c
    trunk/eval.c
    trunk/eval_jump.c
    trunk/lib/drb/drb.rb
    trunk/lib/erb.rb
    trunk/proc.c
    trunk/safe.c
    trunk/spec/ruby/optional/capi/string_spec.rb
    trunk/test/bigdecimal/test_bigdecimal.rb
    trunk/test/fiddle/test_func.rb
    trunk/test/fiddle/test_handle.rb
    trunk/test/lib/leakchecker.rb
    trunk/test/net/imap/test_imap_response_parser.rb
    trunk/test/pathname/test_pathname.rb
    trunk/test/readline/test_readline.rb
    trunk/test/ruby/test_file.rb
    trunk/test/ruby/test_optimization.rb
    trunk/test/ruby/test_proc.rb
    trunk/test/ruby/test_require.rb
    trunk/test/ruby/test_thread.rb
    trunk/test/rubygems/test_gem.rb
    trunk/test/rubygems/test_gem_specification.rb
    trunk/test/test_tempfile.rb
    trunk/test/test_tmpdir.rb
    trunk/test/win32ole/test_win32ole.rb
    trunk/test/win32ole/test_win32ole_event.rb
    trunk/thread.c
    trunk/transcode.c
    trunk/vm.c
    trunk/vm_core.h
    trunk/vm_eval.c
Index: bootstraptest/test_proc.rb
===================================================================
--- bootstraptest/test_proc.rb	(revision 61509)
+++ bootstraptest/test_proc.rb	(revision 61510)
@@ -224,14 +224,14 @@ assert_equal %q{[[nil, []], [1, []], [1, https://github.com/ruby/ruby/blob/trunk/bootstraptest/test_proc.rb#L224
   Proc.new{|a, *b| [a, b]}.call(1, 2, 3),
   ]
 }
-assert_equal %q{0}, %q{
+assert_equal %q{1}, %q{
   pr = proc{
     $SAFE
   }
   $SAFE = 1
   pr.call
 }
-assert_equal %q{[1, 0]}, %q{
+assert_equal %q{[1, 1]}, %q{
   pr = proc{
     $SAFE += 1
   }
Index: vm_core.h
===================================================================
--- vm_core.h	(revision 61509)
+++ vm_core.h	(revision 61510)
@@ -515,6 +515,9 @@ typedef struct rb_vm_struct { https://github.com/ruby/ruby/blob/trunk/vm_core.h#L515
     unsigned int running: 1;
     unsigned int thread_abort_on_exception: 1;
     unsigned int thread_report_on_exception: 1;
+
+    unsigned int safe_level_: 1;
+
     int trace_running;
     volatile int sleeper;
 
@@ -736,7 +739,6 @@ typedef struct rb_execution_context_stru https://github.com/ruby/ruby/blob/trunk/vm_core.h#L739
 
     struct rb_vm_tag *tag;
     struct rb_vm_protect_tag *protect_tag;
-    int safe_level;
     int raised_flag;
 
     /* interrupt flags */
@@ -899,9 +901,8 @@ RUBY_SYMBOL_EXPORT_END https://github.com/ruby/ruby/blob/trunk/vm_core.h#L901
 
 typedef struct {
     const struct rb_block block;
-    int8_t safe_level;		/* 0..1 */
-    int8_t is_from_method;	/* bool */
-    int8_t is_lambda;		/* bool */
+    unsigned int is_from_method: 1;	/* bool */
+    unsigned int is_lambda: 1;		/* bool */
 } rb_proc_t;
 
 typedef struct {
@@ -1464,8 +1465,9 @@ VM_BH_FROM_PROC(VALUE procval) https://github.com/ruby/ruby/blob/trunk/vm_core.h#L1465
 
 /* VM related object allocate functions */
 VALUE rb_thread_alloc(VALUE klass);
-VALUE rb_proc_alloc(VALUE klass);
 VALUE rb_binding_alloc(VALUE klass);
+VALUE rb_proc_alloc(VALUE klass);
+VALUE rb_proc_dup(VALUE self);
 
 /* for debug */
 extern void rb_vmdebug_stack_dump_raw(const rb_execution_context_t *ec, const rb_control_frame_t *cfp);
Index: lib/drb/drb.rb
===================================================================
--- lib/drb/drb.rb	(revision 61509)
+++ lib/drb/drb.rb	(revision 61510)
@@ -1571,17 +1571,23 @@ module DRb https://github.com/ruby/ruby/blob/trunk/lib/drb/drb.rb#L1571
         if $SAFE < @safe_level
           info = Thread.current['DRb']
           if @block
-            @result = Thread.new {
+            @result = Thread.new do
               Thread.current['DRb'] = info
+              prev_safe_level = $SAFE
               $SAFE = @safe_level
               perform_with_block
-            }.value
+            ensure
+              $SAFE = prev_safe_level
+            end.value
           else
-            @result = Thread.new {
+            @result = Thread.new do
               Thread.current['DRb'] = info
+              prev_safe_level = $SAFE
               $SAFE = @safe_level
               perform_without_block
-            }.value
+            ensure
+              $SAFE = prev_safe_level
+            end.value
           end
         else
           if @block
Index: lib/erb.rb
===================================================================
--- lib/erb.rb	(revision 61509)
+++ lib/erb.rb	(revision 61510)
@@ -864,10 +864,13 @@ class ERB https://github.com/ruby/ruby/blob/trunk/lib/erb.rb#L864
   #
   def result(b=new_toplevel)
     if @safe_level
-      proc {
+      proc do
+        prev_safe_level = $SAFE
         $SAFE = @safe_level
         eval(@src, b, (@filename || '(erb)'), @lineno)
-      }.call
+      ensure
+        $SAFE = prev_safe_level
+      end.call
     else
       eval(@src, b, (@filename || '(erb)'), @lineno)
     end
Index: vm_eval.c
===================================================================
--- vm_eval.c	(revision 61509)
+++ vm_eval.c	(revision 61510)
@@ -1490,7 +1490,7 @@ rb_eval_cmd(VALUE cmd, VALUE arg, int le https://github.com/ruby/ruby/blob/trunk/vm_eval.c#L1490
 {
     enum ruby_tag_type state;
     volatile VALUE val = Qnil;		/* OK */
-    const int VAR_NOCLOBBERED(safe) = rb_safe_level();
+    const int VAR_NOCLOBBERED(current_safe_level) = rb_safe_level();
     rb_execution_context_t * volatile ec = GET_EC();
 
     if (OBJ_TAINTED(cmd)) {
@@ -1510,7 +1510,7 @@ rb_eval_cmd(VALUE cmd, VALUE arg, int le https://github.com/ruby/ruby/blob/trunk/vm_eval.c#L1510
     }
     EC_POP_TAG();
 
-    rb_set_safe_level_force(safe);
+    rb_set_safe_level_force(current_safe_level);
     if (state) EC_JUMP_TAG(ec, state);
     return val;
 }
Index: proc.c
===================================================================
--- proc.c	(revision 61509)
+++ proc.c	(revision 61510)
@@ -124,28 +124,11 @@ rb_obj_is_proc(VALUE proc) https://github.com/ruby/ruby/blob/trunk/proc.c#L124
     }
 }
 
-VALUE rb_proc_create(VALUE klass, const struct rb_block *block,
-		     int8_t safe_level, int8_t is_from_method, int8_t is_lambda);
-
-/* :nodoc: */
-static VALUE
-proc_dup(VALUE self)
-{
-    VALUE procval;
-    rb_proc_t *src;
-
-    GetProcPtr(self, src);
-    procval = rb_proc_create(rb_cProc, &src->block,
-			     src->safe_level, src->is_from_method, src->is_lambda);
-    RB_GC_GUARD(self); /* for: body = proc_dup(body) */
-    return procval;
-}
-
 /* :nodoc: */
 static VALUE
 proc_clone(VALUE self)
 {
-    VALUE procval = proc_dup(self);
+    VALUE procval = rb_proc_dup(self);
     CLONESETUP(procval, self);
     return procval;
 }
@@ -752,7 +735,7 @@ proc_new(VALUE klass, int8_t is_lambda) https://github.com/ruby/ruby/blob/trunk/proc.c#L735
 	    return procval;
 	}
 	else {
-	    VALUE newprocval = proc_dup(procval);
+	    VALUE newprocval = rb_proc_dup(procval);
 	    RBASIC_SET_CLASS(newprocval, klass);
 	    return newprocval;
 	}
@@ -1982,7 +1965,7 @@ rb_mod_define_method(int argc, VALUE *ar https://github.com/ruby/ruby/blob/trunk/proc.c#L1965
 	RB_GC_GUARD(body);
     }
     else {
-	VALUE procval = proc_dup(body);
+	VALUE procval = rb_proc_dup(body);
 	if (vm_proc_iseq(procval) != NULL) {
 	    rb_proc_t *proc;
 	    GetProcPtr(procval, proc);
@@ -3115,7 +3098,7 @@ Init_Proc(void) https://github.com/ruby/ruby/blob/trunk/proc.c#L3098
     rb_define_method(rb_cProc, "to_proc", proc_to_proc, 0);
     rb_define_method(rb_cProc, "arity", proc_arity, 0);
     rb_define_method(rb_cProc, "clone", proc_clone, 0);
-    rb_define_method(rb_cProc, "dup", proc_dup, 0);
+    rb_define_method(rb_cProc, "dup", rb_proc_dup, 0);
     rb_define_method(rb_cProc, "hash", proc_hash, 0);
     rb_define_method(rb_cProc, "to_s", proc_to_s, 0);
     rb_define_alias(rb_cProc, "inspect", "to_s");
Index: thread.c
===================================================================
--- thread.c	(revision 61509)
+++ thread.c	(revision 61510)
@@ -2952,18 +2952,16 @@ rb_thread_stop_p(VALUE thread) https://github.com/ruby/ruby/blob/trunk/thread.c#L2952
  *  call-seq:
  *     thr.safe_level   -> integer
  *
- *  Returns the safe level in effect for <i>thr</i>. Setting thread-local safe
- *  levels can help when implementing sandboxes which run insecure code.
+ *  Returns the safe level.
  *
- *     thr = Thread.new { $SAFE = 1; sleep }
- *     Thread.current.safe_level   #=> 0
- *     thr.safe_level              #=> 1
+ *  This method is obsolete because $SAFE is a process global state.
+ *  Simply check $SAFE.
  */
 
 static VALUE
 rb_thread_safe_level(VALUE thread)
 {
-    return INT2NUM(rb_thread_ptr(thread)->ec->safe_level);
+    return UINT2NUM(rb_safe_level());
 }
 
 /*
Index: spec/ruby/optional/capi/string_spec.rb
===================================================================
--- spec/ruby/optional/capi/string_spec.rb	(revision 61509)
+++ spec/ruby/optional/capi/string_spec.rb	(revision 61510)
@@ -485,6 +485,8 @@ describe "C-API String function" do https://github.com/ruby/ruby/blob/trunk/spec/ruby/optional/capi/string_spec.rb#L485
           @s.SafeStringValue("str".taint)
         }.should raise_error(SecurityError)
       }.join
+    ensure
+      $SAFE = 0
     end
 
     it_behaves_like :string_value_macro, :SafeStringValue
Index: eval_jump.c
===================================================================
--- eval_jump.c	(revision 61509)
+++ eval_jump.c	(revision 61510)
@@ -50,7 +50,6 @@ rb_f_at_exit(void) https://github.com/ruby/ruby/blob/trunk/eval_jump.c#L50
 struct end_proc_data {
     void (*func) ();
     VALUE data;
-    int safe;
     struct end_proc_data *next;
 };
 
@@ -72,7 +71,6 @@ rb_set_end_proc(void (*func)(VALUE), VAL https://github.com/ruby/ruby/blob/trunk/eval_jump.c#L71
     link->next = *list;
     link->func = func;
     link->data = data;
-    link->safe = rb_safe_level();
     *list = link;
 }
 
@@ -104,7 +102,6 @@ exec_end_procs_chain(struct end_proc_dat https://github.com/ruby/ruby/blob/trunk/eval_jump.c#L102
 	*procs = link->next;
 	endproc = *link;
 	xfree(link);
-	rb_set_safe_level_force(endproc.safe);
 	(*endproc.func) (endproc.data);
 	*errp = errinfo;
     }
@@ -114,7 +111,6 @@ void https://github.com/ruby/ruby/blob/trunk/eval_jump.c#L111
 rb_exec_end_proc(void)
 {
     enum ruby_tag_type state;
-    volatile int safe = rb_safe_level();
     rb_execution_context_t * volatile ec = GET_EC();
     volatile VALUE errinfo = ec->errinfo;
 
@@ -133,7 +129,6 @@ rb_exec_end_proc(void) https://github.com/ruby/ruby/blob/trunk/eval_jump.c#L129
     }
     EC_POP_TAG();
 
-    rb_set_safe_level_force(safe);
     ec->errinfo = errinfo;
 }
 
Index: eval.c
===================================================================
--- eval.c	(revision 61509)
+++ eval.c	(revision 61510)
@@ -175,7 +175,7 @@ ruby_cleanup(volatile int ex) https://github.com/ruby/ruby/blob/trunk/eval.c#L175
 
       step_0: step++;
 	errs[1] = th->ec->errinfo;
-	th->ec->safe_level = 0;
+	rb_set_safe_level_force(0);
 	ruby_init_stack(&errs[STACK_UPPER(errs, 0, 1)]);
 
 	SAVE_ROOT_JMPBUF(th, ruby_finalize_0());
Index: NEWS
===================================================================
--- NEWS	(revision 61509)
+++ NEWS	(revision 61510)
@@ -11,3 +11,27 @@ with all sufficient information, see the https://github.com/ruby/ruby/blob/trunk/NEWS#L11
 (e.g. <tt>https://bugs.ruby-lang.org/issues/$FEATURE_OR_BUG_NUMBER</tt>)
 
 == Changes since the 2.5.0 release
+
+=== Language changes
+
+* $SAFE is a process global state and we can set 0 again. [Feature #14250]
+
+=== Core classes updates (outstanding ones only)
+
+* Proc
+
+  * Proc#call doesn't change $SAFE any more. [Feature #14250]
+
+=== Stdlib updates (outstanding ones only)
+
+=== Compatibility issues (excluding feature bug fixes)
+
+=== Stdlib compatibility issues (excluding feature bug fixes)
+
+=== C API updates
+
+=== Supported platform changes
+
+=== Implementation improvements
+
+=== Miscellaneous changes
Index: cont.c
===================================================================
--- cont.c	(revision 61509)
+++ cont.c	(revision 61510)
@@ -696,7 +696,6 @@ cont_restore_thread(rb_context_t *cont) https://github.com/ruby/ruby/blob/trunk/cont.c#L696
 	/* other members of ec */
 
 	th->ec->cfp = sec->cfp;
-	th->ec->safe_level = sec->safe_level;
 	th->ec->raised_flag = sec->raised_flag;
 	th->ec->tag = sec->tag;
 	th->ec->protect_tag = sec->protect_tag;
Index: vm.c
===================================================================
--- vm.c	(revision 61509)
+++ vm.c	(revision 61510)
@@ -809,7 +809,7 @@ static VALUE https://github.com/ruby/ruby/blob/trunk/vm.c#L809
 vm_proc_create_from_captured(VALUE klass,
 			     const struct rb_captured_block *captured,
 			     enum rb_block_type block_type,
-			     int8_t safe_level, int8_t is_from_method, int8_t is_lambda)
+			     int8_t is_from_method, int8_t is_lambda)
 {
     VALUE procval = rb_proc_alloc(klass);
     rb_proc_t *proc = RTYPEDDATA_DATA(procval);
@@ -822,7 +822,6 @@ vm_proc_create_from_captured(VALUE klass https://github.com/ruby/ruby/blob/trunk/vm.c#L822
     rb_vm_block_ep_update(procval, &proc->block, captured->ep);
 
     vm_block_type_set(&proc->block, block_type);
-    proc->safe_level = safe_level;
     proc->is_from_method = is_from_method;
     proc->is_lambda = is_lambda;
 
@@ -849,9 +848,8 @@ rb_vm_block_copy(VALUE obj, const struct https://github.com/ruby/ruby/blob/trunk/vm.c#L848
     }
 }
 
-VALUE
-rb_proc_create(VALUE klass, const struct rb_block *block,
-	       int8_t safe_level, int8_t is_from_method, int8_t is_lambda)
+static VALUE
+proc_create(VALUE klass, const struct rb_block *block, int8_t is_from_method, int8_t is_lambda)
 {
     VALUE procval = rb_proc_alloc(klass);
     rb_proc_t *proc = RTYPEDDATA_DATA(procval);
@@ -859,7 +857,6 @@ rb_proc_create(VALUE klass, const struct https://github.com/ruby/ruby/blob/trunk/vm.c#L857
     VM_ASSERT(VM_EP_IN_HEAP_P(GET_EC(), vm_block_ep(block)));
     rb_vm_block_copy(procval, &proc->block, block);
     vm_block_type_set(&proc->block, block->type);
-    proc->safe_level = safe_level;
     proc->is_from_method = is_from_method;
     proc->is_lambda = is_lambda;
 
@@ -867,6 +864,19 @@ rb_proc_create(VALUE klass, const struct https://github.com/ruby/ruby/blob/trunk/vm.c#L864
 }
 
 VALUE
+rb_proc_dup(VALUE self)
+{
+    VALUE procval;
+    rb_proc_t *src;
+
+    GetProcPtr(self, src);
+    procval = proc_create(rb_cProc, &src->block, src->is_from_method, src->is_lambda);
+    RB_GC_GUARD(self); /* for: body = rb_proc_dup(body) */
+    return procval;
+}
+
+
+VALUE
 rb_vm_make_proc_lambda(const rb_execution_context_t *ec, const struct rb_captured_block *captured, VALUE klass, int8_t is_lambda)
 {
     VALUE procval;
@@ -880,8 +890,7 @@ rb_vm_make_proc_lambda(const rb_executio https://github.com/ruby/ruby/blob/trunk/vm.c#L890
 	      imemo_type_p(captured->code.val, imemo_ifunc));
 
     procval = vm_proc_create_from_captured(klass, captured,
-					   imemo_type(captured->code.val) == imemo_iseq ? block_type_iseq : block_type_ifunc,
-					   (int8_t)ec->safe_level, FALSE, is_lambda);
+					   imemo_type(captured->code.val) == imemo_iseq ? block_type_iseq : block_type_ifunc, FALSE, is_lambda);
     return procval;
 }
 
@@ -1139,23 +1148,7 @@ static VALUE https://github.com/ruby/ruby/blob/trunk/vm.c#L1148
 vm_invoke_proc(rb_execution_context_t *ec, rb_proc_t *proc, VALUE self,
 	       int argc, const VALUE *argv, VALUE passed_block_handler)
 {
-    VALUE val = Qundef;
-    enum ruby_tag_type state;
-    volatile int stored_safe = ec->safe_level;
-
-    EC_PUSH_TAG(ec);
-    if ((state = EC_EXEC_TAG()) == TAG_NONE) {
-	ec->safe_level = proc->safe_level;
-	val = invoke_block_from_c_proc(ec, proc, self, argc, argv, passed_block_handler, proc->is_lambda);
-    }
-    EC_POP_TAG();
-
-    ec->safe_level = stored_safe;
-
-    if (state) {
-	EC_JUMP_TAG(ec, state);
-    }
-    return val;
+    return invoke_block_from_c_proc(ec, proc, self, argc, argv, passed_block_handler, proc->is_lambda);
 }
 
 static VALUE
Index: safe.c
===================================================================
--- safe.c	(revision 61509)
+++ safe.c	(revision 61510)
@@ -34,28 +34,34 @@ ruby_safe_level_2_warning(void) https://github.com/ruby/ruby/blob/trunk/safe.c#L34
 int
 rb_safe_level(void)
 {
-    return GET_EC()->safe_level;
+    return GET_VM()->safe_level_;
 }
 
 void
 rb_set_safe_level_force(int safe)
 {
-    GET_EC()->safe_level = safe;
+    GET_VM()->safe_level_ = safe;
 }
 
 void
 rb_set_safe_level(int level)
 {
-    rb_execution_context_t *ec = GET_EC();
+    rb_vm_t *vm = GET_VM();
 
-    if (level > ec->safe_level) {
-	if (level > SAFE_LEVEL_MAX) {
-	    rb_raise(rb_eArgError, "$SAFE=2 to 4 are obsolete");
-	}
-	/* block parameters */
-	rb_vm_stack_to_heap(ec);
+    if (level > SAFE_LEVEL_MAX) {
+	rb_raise(rb_eArgError, "$SAFE=2 to 4 are obsolete");
+    }
+    else if (level < 0) {
+	rb_raise(rb_eArgError, "$SAFE should be >= 0");
+    }
+    else {
+	int line;
+	const char *path = rb_source_location_cstr(&line);
 
-	ec->safe_level = level;
+	if (0) fprintf(stderr, "%s:%d $SAFE %d -> %d\n",
+		       path ? path : "-", line, vm->safe_level_, level);
+
+	vm->safe_level_ = level;
     }
 }
 
@@ -68,26 +74,8 @@ safe_getter(void) https://github.com/ruby/ruby/blob/trunk/safe.c#L74
 static void
 safe_setter(VALUE val)
 {
-    rb_execution_context_t *ec = GET_EC();
-    int current_level = ec->safe_level;
     int level = NUM2INT(val);
-
-    if (level == current_level) {
-	return;
-    }
-    else if (level < current_level) {
-	rb_raise(rb_eSecurityError,
-		 "tried to downgrade safe level from %d to %d",
-		 current_level, level);
-    }
-    else if (level > SAFE_LEVEL_MAX) {
-	rb_raise(rb_eArgError, "$SAFE=2 to 4 are obsolete");
-    }
-
-    /* block parameters */
-    rb_vm_stack_to_heap(ec);
-
-    ec->safe_level = level;
+    rb_set_safe_level(level);
 }
 
 void
Index: test/test_tmpdir.rb
===================================================================
--- test/test_tmpdir.rb	(revision 61509)
+++ test/test_tmpdir.rb	(revision 61510)
@@ -20,6 +20,8 @@ class TestTmpdir < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/test_tmpdir.rb#L20
       tmpdir << "foo"
       assert_equal(tmpdir_org, Dir.tmpdir)
     }.join
+  ensure
+    $SAFE = 0
   end
 
   def test_world_writable
Index: test/win32ole/test_win32ole.rb
===================================================================
--- test/win32ole/test_win32ole.rb	(revision 61509)
+++ test/win32ole/test_win32ole.rb	(revision 61510)
@@ -188,6 +188,8 @@ if defined?(WIN32OLE) https://github.com/ruby/ruby/blob/trunk/test/win32ole/test_win32ole.rb#L188
         th.join
       }
       assert_match(/insecure object creation - `Scripting.Dictionary'/, exc.message)
+    ensure
+      $SAFE = 0
     end
 
     def test_s_new_exc_host_tainted
@@ -203,6 +205,8 @@ if defined?(WIN32OLE) https://github.com/ruby/ruby/blob/trunk/test/win32ole/test_win32ole.rb#L205
         th.join
       }
       assert_match(/insecure object creation - `localhost'/, exc.message)
+    ensure
+      $SAFE = 0
     end
 
     def test_s_new_DCOM
@@ -242,6 +246,8 @@ if defined?(WIN32OLE) https://github.com/ruby/ruby/blob/trunk/test/win32ole/test_win32ole.rb#L246
         th.join
       }
       assert_match(/insecure connection - `winmgmts:'/, exc.message)
+    ensure
+      $SAFE = 0
     end
 
     def test_invoke_accept_symbol_hash_key
Index: test/win32ole/test_win32ole_event.rb
===================================================================
--- test/win32ole/test_win32ole_event.rb	(revision 61509)
+++ test/win32ole/test_win32ole_event.rb	(revision 61510)
@@ -395,6 +395,8 @@ if defined?(WIN32OLE_EVENT) https://github.com/ruby/ruby/blob/trunk/test/win32ole/test_win32ole_event.rb#L395
           th.join
         }
         assert_match(/insecure event creation - `ConnectionEvents'/, exc.message)
+      ensure
+        $SAFE = 0
       end
     end
   end
Index: test/test_tempfile.rb
===================================================================
--- test/test_tempfile.rb	(revision 61509)
+++ test/test_tempfile.rb	(revision 61510)
@@ -38,6 +38,8 @@ class TestTempfile < Test::Unit::TestCas https://github.com/ruby/ruby/blob/trunk/test/test_tempfile.rb#L38
     assert_nothing_raised(SecurityError, bug3733) {
       proc {$SAFE = 1; File.expand_path(Dir.tmpdir)}.call
     }
+  ensure
+    $SAFE = 0
   end
 
   def test_saves_in_given_directory
Index: test/fiddle/test_func.rb
===================================================================
--- test/fiddle/test_func.rb	(revision 61509)
+++ test/fiddle/test_func.rb	(revision 61510)
@@ -19,6 +19,8 @@ module Fiddle https://github.com/ruby/ruby/blob/trunk/test/fiddle/test_func.rb#L19
           f.call("uname -rs".dup.taint)
         end
       }.join
+    ensure
+      $SAFE = 0
     end
 
     def test_sinf
Index: test/fiddle/test_handle.rb
===================================================================
--- test/fiddle/test_handle.rb	(revision 61509)
+ (... truncated)

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

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