Hi,
I have a question about the frame list. I am working on implementing
a capability security module in Ruby, and I find that in order to to this
in a way that is not activly painful to program I need to be able to walk
the frame list to snag a reference to the object that invoked the method I
use to test for capabilities. Here are diffs for anyone interested:
diff -ur ruby-1.6.4/eval.c ruby-1.6.4.hacked/eval.c
--- ruby-1.6.4/eval.c Tue May 29 03:59:36 2001
+++ ruby-1.6.4.hacked/eval.c Thu Jun 14 22:42:32 2001
@@ -1510,10 +1510,11 @@
rb_raise(rb_eSecurityError, "Insecure: can't undef");
}
rb_frozen_class_p(klass);
- if (id == __id__ || id == __send__) {
+/* if (id == __id__ || id == __send__) {
rb_warn("undefining `%s' may cause serious problem",
rb_id2name(id));
- }
+ }
+*/
body = search_method(ruby_class, id, &origin);
if (!body || !body->nd_body) {
char *s0 = " class";
@@ -3335,6 +3336,28 @@
}
static VALUE
+rb_f_last_caller(self, testor)
+VALUE self, testor;
+{
+ struct FRAME *foo;
+ foo = ruby_frame;
+ /* first, we have to get to the frame. It might be a couple of frames
+ * up, depending on exceptions and such. */
+ while (foo != top_frame && foo->self == self){
+ foo = foo->prev;
+ }
+ /* now that we are at the right frame, get past it. */
+ while (foo != top_frame && foo->self == testor) {
+ foo = foo->prev;
+ }
+ /* if we have a previous frame at all, we are at it now. */
+ if (foo == top_frame)
+ return Qnil;
+ else return foo->self;
+
+}
+
+static VALUE
rb_f_abort()
{
rb_secure(4);
@@ -4388,6 +4411,7 @@
}
else if (nd_type(body) == NODE_BLOCK) {
node = body->nd_head;
+
body = body->nd_next;
}
if (node) {
@@ -5896,6 +5920,7 @@
rb_define_global_function("loop", rb_f_loop, 0);
rb_define_method(rb_mKernel, "respond_to?", rb_obj_respond_to, -1);
+ rb_define_method(rb_mKernel, "last_caller", rb_f_last_caller, 1);
rb_define_global_function("raise", rb_f_raise, -1);
rb_define_global_function("fail", rb_f_raise, -1);
As you can see, I am just walking back up the frame list, stopping when I get
to one before what I am looking for or at top_frame. The question is, however,
whether this method will work correctly when threads are introduced into the
picture, or of I need to check for which frame is in what thread as I go (which
would be tricky, as I can't determine if threads have their own frame list or
if they all share the same frame list).
Comments?