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/