summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog5
-rw-r--r--eval.c9
-rw-r--r--test/ruby/test_proc.rb31
3 files changed, 42 insertions, 3 deletions
diff --git a/ChangeLog b/ChangeLog
index ca3232f83c..a200a39468 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,7 +1,10 @@
-Sat Jun 19 13:24:15 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+Sat Jun 19 13:27:01 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
* eval.c (method_call): allow changing $SAFE. [ruby-dev:23713]
+ * eval.c (proc_set_safe_level, proc_invoke, rb_mod_define_method): not
+ set $SAFE for methods defined from Proc. [ruby-dev:23697]
+
Sat Jun 19 01:10:12 2004 Kouhei Sutou <kou@cozmixng.org>
* sample/rss/tdiary_plugin/rss-recent.rb: added more information.
diff --git a/eval.c b/eval.c
index 14f651d824..b068b52c49 100644
--- a/eval.c
+++ b/eval.c
@@ -7877,9 +7877,12 @@ rb_f_binding(self)
#define PROC_TSHIFT (FL_USHIFT+1)
#define PROC_TMASK (FL_USER1|FL_USER2|FL_USER3)
#define PROC_TMAX (PROC_TMASK >> PROC_TSHIFT)
+#define PROC_NOSAFE FL_USER4
#define SAFE_LEVEL_MAX PROC_TMASK
+#define proc_safe_level_p(data) (!(RBASIC(data)->flags & PROC_NOSAFE))
+
static void
proc_save_safe_level(data)
VALUE data;
@@ -7900,6 +7903,7 @@ static void
proc_set_safe_level(data)
VALUE data;
{
+ if (!proc_safe_level_p(data)) return;
ruby_safe_level = proc_get_safe_level(data);
}
@@ -8081,7 +8085,7 @@ proc_invoke(proc, args, self, klass)
ruby_block = old_block;
ruby_wrapper = old_wrapper;
ruby_dyna_vars = old_dvars;
- ruby_safe_level = safe;
+ if (proc_safe_level_p(proc)) ruby_safe_level = safe;
switch (state) {
case 0:
@@ -8428,7 +8432,7 @@ block_pass(self, node)
POP_TAG();
POP_ITER();
ruby_block = old_block;
- ruby_safe_level = safe;
+ if (proc_safe_level_p(proc)) ruby_safe_level = safe;
switch (state) {/* escape from orphan block */
case 0:
@@ -9147,6 +9151,7 @@ rb_mod_define_method(argc, argv, mod)
struct BLOCK *block;
body = proc_clone(body);
+ RBASIC(body)->flags |= PROC_NOSAFE;
Data_Get_Struct(body, struct BLOCK, block);
block->frame.last_func = id;
block->frame.orig_func = id;
diff --git a/test/ruby/test_proc.rb b/test/ruby/test_proc.rb
index 7a5f6a155b..aaeb189e27 100644
--- a/test/ruby/test_proc.rb
+++ b/test/ruby/test_proc.rb
@@ -91,4 +91,35 @@ class TestProc < Test::Unit::TestCase
assert_equal(10, Proc.new{|&b| b.call(10)}.call {|x| x})
assert_equal(12, Proc.new{|a,&b| b.call(a)}.call(12) {|x| x})
end
+
+ def test_safe
+ safe = $SAFE
+ c = Class.new
+ x = c.new
+
+ p = proc {
+ $SAFE += 1
+ proc {$SAFE}
+ }.call
+ assert_equal(safe, $SAFE)
+ assert_equal(safe + 1, p.call)
+ assert_equal(safe, $SAFE)
+
+ c.class_eval {define_method(:safe, p)}
+ assert_equal(safe, x.safe)
+ assert_equal(safe, x.method(:safe).call)
+ assert_equal(safe, x.method(:safe).to_proc.call)
+
+ p = proc {$SAFE += 1}
+ assert_equal(safe + 1, p.call)
+ assert_equal(safe, $SAFE)
+
+ c.class_eval {define_method(:inc, p)}
+ assert_equal(safe + 1, proc {x.inc; $SAFE}.call)
+ assert_equal(safe, $SAFE)
+ assert_equal(safe + 1, proc {x.method(:inc).call; $SAFE}.call)
+ assert_equal(safe, $SAFE)
+ assert_equal(safe + 1, proc {x.method(:inc).to_proc.call; $SAFE}.call)
+ assert_equal(safe, $SAFE)
+ end
end