summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2011-08-24 23:27:35 +0000
committerko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2011-08-24 23:27:35 +0000
commit382ed4285ae504c34a002536b922c0ca7cbd0a33 (patch)
tree9a1bc1144916ef28276df925b307f7515d874cbd
parent7a3f54edb1656a7ad068c54e4084123beef2aafa (diff)
* vm.c (vm_make_env_each): work around to solve Bug #2729.
fixes: Bug #2729 a patch from Kazuki Tsujimoto <kazuki@callcc.net> This problem is caused by changing dfp (dynamic env pointer) from saved dfp. Saved dfp is pointed env in VM stack. However, the dfp can be moved because VM copies env from VM stack to the heap. At this copying, dfp was also changed. To solve this problem, I'll try to change throw mechanism (not save target dfp, but save target cfp). * bootstraptest/test_flow.rb: add a test for above. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_9_3@33063 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog14
-rw-r--r--bootstraptest/test_flow.rb13
-rw-r--r--vm.c17
3 files changed, 44 insertions, 0 deletions
diff --git a/ChangeLog b/ChangeLog
index e92a548246..d76051929e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+Thu Aug 25 08:19:43 2011 Koichi Sasada <ko1@atdot.net>
+
+ * vm.c (vm_make_env_each): work around to solve Bug #2729.
+ fixes: Bug #2729
+ a patch from Kazuki Tsujimoto <kazuki@callcc.net>
+ This problem is caused by changing dfp (dynamic env pointer)
+ from saved dfp. Saved dfp is pointed env in VM stack. However,
+ the dfp can be moved because VM copies env from VM stack to
+ the heap. At this copying, dfp was also changed. To solve this
+ problem, I'll try to change throw mechanism (not save target dfp,
+ but save target cfp).
+
+ * bootstraptest/test_flow.rb: add a test for above.
+
Thu Aug 25 08:04:08 2011 Marc-Andre Lafortune <ruby-core@marc-andre.ca>
* numeric.c (int_round): Fix Integer#round [ruby-core:39096]
diff --git a/bootstraptest/test_flow.rb b/bootstraptest/test_flow.rb
index 02062755aa..100ad0a2f1 100644
--- a/bootstraptest/test_flow.rb
+++ b/bootstraptest/test_flow.rb
@@ -517,6 +517,19 @@ assert_equal %Q{ENSURE\n}, %q{
end
end
e = Bug2728.new
+}],
+ ['[ruby-core:28132]', %q{
+ class Bug2729
+ include Enumerable
+ def each
+ begin
+ yield :foo
+ ensure
+ proc {}.call
+ end
+ end
+ end
+ e = Bug2729.new
}]].each do |bug, src|
assert_equal "foo", src + %q{e.detect {true}}, bug
assert_equal "true", src + %q{e.any? {true}}, bug
diff --git a/vm.c b/vm.c
index 3147ae4c73..4805e286e7 100644
--- a/vm.c
+++ b/vm.c
@@ -415,6 +415,23 @@ vm_make_env_each(rb_thread_t * const th, rb_control_frame_t * const cfp,
if (!RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) {
/* TODO */
env->block.iseq = 0;
+ } else {
+ /* rewrite dfp in errinfo to point to heap */
+ if (cfp->iseq->type == ISEQ_TYPE_RESCUE ||
+ cfp->iseq->type == ISEQ_TYPE_ENSURE) {
+ VALUE errinfo = env->env[0]; /* #$! */
+ if (RB_TYPE_P(errinfo, T_NODE)) {
+ VALUE *escape_dfp = GET_THROWOBJ_CATCH_POINT(errinfo);
+ if (! ENV_IN_HEAP_P(th, escape_dfp)) {
+ VALUE dfpval = *escape_dfp;
+ if (CLASS_OF(dfpval) == rb_cEnv) {
+ rb_env_t *dfpenv;
+ GetEnvPtr(dfpval, dfpenv);
+ SET_THROWOBJ_CATCH_POINT(errinfo, (VALUE)(dfpenv->env + dfpenv->local_size));
+ }
+ }
+ }
+ }
}
return envval;
}