[#35027] [Ruby 1.9-Bug#4352][Open] [patch] Fix eval(s, b) backtrace; make eval(s, b) consistent with eval(s) — "James M. Lawrence" <redmine@...>

Bug #4352: [patch] Fix eval(s, b) backtrace; make eval(s, b) consistent with eval(s)

16 messages 2011/02/01

[#35114] [Ruby 1.9-Bug#4373][Open] http.rb:677: [BUG] Segmentation fault — Christian Fazzini <redmine@...>

Bug #4373: http.rb:677: [BUG] Segmentation fault

59 messages 2011/02/06

[#35171] [Ruby 1.9-Bug#4386][Open] encoding: directive does not affect regex expressions — mathew murphy <redmine@...>

Bug #4386: encoding: directive does not affect regex expressions

9 messages 2011/02/09

[#35237] [Ruby 1.9-Bug#4400][Open] nested at_exit hooks run in strange order — Suraj Kurapati <redmine@...>

Bug #4400: nested at_exit hooks run in strange order

12 messages 2011/02/15

[ruby-core:35064] [Ruby 1.9-Bug#4352] [patch] Fix eval(s, b) backtrace; make eval(s, b) consistent with eval(s)

From: "James M. Lawrence" <redmine@...>
Date: 2011-02-03 02:24:42 UTC
List: ruby-core #35064
Issue #4352 has been updated by James M. Lawrence.



> Why do you think only a binding location as a problem?

The initial problem I encountered was

  eval %{def g ; end}, nil, "(eval)", 99
  p method(:g).source_location #=> ["(eval)", 99]

  eval %{def f ; end}, binding, "(eval)", 99
  p method(:f).source_location #=> ["prob.rb", 1]

I needed source_location to be ["(eval)", 99] in the latter case,
which is solved by the patch. This could be also be done by making
eval recognize the difference between an empty file argument and an
"(eval)" file argument, however the problem seemed more fundamental.

eval should not implicitly slurp file/line info from the binding.
Creating a "dishonest" backtrace is something that should be done
explicitly by the user, as in

  eval(s, b, *b.source_location)

In the last the example in the original post, the existence of
raiser.rb:10 is an outright falsehood. Pointing to a nonexistent line
number should not be the default behavior of eval(s, b).

Since source_location claims to be "the ruby source filename and line
number containing this proc", I was thinking that source_location
could give the "true" location, ignoring the file/line "lies" passed
to eval. But this was wrong--indeed I want the "lies" to be reflected
in source_location. My problem is with eval implicitly grabbing
file/line from the binding, which is just what the patch solves.

As mentioned above, this would be nice too:

  class Binding
    def source_location
      eval "[__FILE__, __LINE__]"
    end
  end

diff --git a/proc.c b/proc.c
index 7b1d147..0042caf 100644
--- a/proc.c
+++ b/proc.c
@@ -305,6 +305,24 @@ binding_clone(VALUE self)
     return bindval;
 }
 
+/*
+ * call-seq:
+ *    binding.source_location  -> [String, Fixnum]
+ *
+ * Returns the ruby source filename and line number associated with
+ * this binding.
+ */
+static VALUE
+binding_source_location(VALUE self)
+{
+    rb_binding_t *src;
+    VALUE loc[2];
+    GetBindingPtr(self, src);
+    loc[0] = rb_str_dup_frozen(src->filename);
+    loc[1] = INT2FIX(src->line_no);
+    return rb_ary_new4(2, loc);
+}
+
 VALUE
 rb_binding_new(void)
 {
@@ -2227,6 +2245,7 @@ Init_Binding(void)
     rb_undef_method(CLASS_OF(rb_cBinding), "new");
     rb_define_method(rb_cBinding, "clone", binding_clone, 0);
     rb_define_method(rb_cBinding, "dup", binding_dup, 0);
+    rb_define_method(rb_cBinding, "source_location", binding_source_location, 0);
     rb_define_method(rb_cBinding, "eval", bind_eval, -1);
     rb_define_global_function("binding", rb_f_binding, 0);
 }

----------------------------------------
http://redmine.ruby-lang.org/issues/show/4352

----------------------------------------
http://redmine.ruby-lang.org

In This Thread