summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-05-24 00:26:26 +0000
committermatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-05-24 00:26:26 +0000
commitf513d9ab286be1638dbf5f3cee6b6b9d606ba250 (patch)
tree5064edabd38965be265076ccd5ff62bdacb49702
parentcc1c3f525333afc3094dd8f1847e0b1a249c9ca3 (diff)
* marshal.c (reentrant_check): check reentrance via callcc.
[ruby-dev:34802] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8@16564 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog5
-rw-r--r--eval.c2
-rw-r--r--marshal.c36
3 files changed, 38 insertions, 5 deletions
diff --git a/ChangeLog b/ChangeLog
index f8af2690da..e87970f509 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -3,6 +3,11 @@ Sat May 24 00:34:59 2008 Tanaka Akira <akr@fsij.org>
* lib/rational.rb (Rational#to_i): fix rdoc. Rational(-7,4).to_i
should be -1.
+Fri May 23 20:22:44 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * marshal.c (reentrant_check): check reentrance via callcc.
+ [ruby-dev:34802]
+
Fri May 23 16:46:28 2008 Akinori MUSHA <knu@iDaemons.org>
* enumerator.c (proc_call): Remove an unused static function.
diff --git a/eval.c b/eval.c
index 2e78f4a4d9..358e79a743 100644
--- a/eval.c
+++ b/eval.c
@@ -5542,7 +5542,7 @@ rb_ensure(b_proc, data1, e_proc, data2)
POP_TAG();
retval = prot_tag ? prot_tag->retval : Qnil; /* save retval */
if (!thread_no_ensure()) {
- (*e_proc)(data2);
+ (*e_proc)(data2);
}
if (prot_tag) return_value(retval);
if (state) JUMP_TAG(state);
diff --git a/marshal.c b/marshal.c
index cf7a312b9c..9dd83966a7 100644
--- a/marshal.c
+++ b/marshal.c
@@ -84,6 +84,16 @@ static ID s_dump, s_load, s_mdump, s_mload;
static ID s_dump_data, s_load_data, s_alloc;
static ID s_getc, s_read, s_write, s_binmode;
+static void
+reentrant_check(obj, sym)
+ VALUE obj;
+ ID sym;
+{
+ if (RBASIC(obj)->klass) {
+ rb_raise(rb_eRuntimeError, "%s reentered", rb_id2name(sym));
+ }
+}
+
struct dump_arg {
VALUE obj;
VALUE str, dest;
@@ -505,6 +515,7 @@ w_object(obj, arg, limit)
volatile VALUE v;
v = rb_funcall(obj, s_mdump, 0, 0);
+ reentrant_check(arg->str, s_mdump);
w_class(TYPE_USRMARSHAL, obj, arg, Qfalse);
w_object(v, arg, limit);
if (ivtbl) w_ivar(0, &c_arg);
@@ -514,6 +525,7 @@ w_object(obj, arg, limit)
VALUE v;
v = rb_funcall(obj, s_dump, 1, INT2NUM(limit));
+ reentrant_check(arg->str, s_dump);
if (TYPE(v) != T_STRING) {
rb_raise(rb_eTypeError, "_dump() must return string");
}
@@ -658,6 +670,7 @@ w_object(obj, arg, limit)
rb_obj_classname(obj));
}
v = rb_funcall(obj, s_dump_data, 0);
+ reentrant_check(arg->str, s_dump_data);
w_class(TYPE_DATA, obj, arg, Qtrue);
w_object(v, arg, limit);
}
@@ -690,11 +703,13 @@ static VALUE
dump_ensure(arg)
struct dump_arg *arg;
{
+ if (RBASIC(arg->str)->klass) return; /* ignore reentrant */
st_free_table(arg->symbols);
st_free_table(arg->data);
if (arg->taint) {
OBJ_TAINT(arg->str);
}
+
return 0;
}
@@ -747,20 +762,21 @@ marshal_dump(argc, argv)
else port = a1;
}
arg.dest = 0;
+ arg.str = rb_str_buf_new(0);
+ RBASIC(arg.str)->klass = 0;
if (!NIL_P(port)) {
if (!rb_respond_to(port, s_write)) {
type_error:
rb_raise(rb_eTypeError, "instance of IO needed");
}
- arg.str = rb_str_buf_new(0);
arg.dest = port;
if (rb_respond_to(port, s_binmode)) {
rb_funcall2(port, s_binmode, 0, 0);
+ reentrant_check(arg.str, s_dump_data);
}
}
else {
- port = rb_str_buf_new(0);
- arg.str = port;
+ port = arg.str;
}
arg.symbols = st_init_numtable();
@@ -774,6 +790,7 @@ marshal_dump(argc, argv)
w_byte(MARSHAL_MINOR, &arg);
rb_ensure(dump, (VALUE)&c_arg, dump_ensure, (VALUE)&arg);
+ RBASIC(arg.str)->klass = rb_cString;
return port;
}
@@ -806,6 +823,7 @@ r_byte(arg)
else {
VALUE src = arg->src;
VALUE v = rb_funcall2(src, s_getc, 0, 0);
+ reentrant_check(arg->data, s_getc);
if (NIL_P(v)) rb_eof_error();
c = (unsigned char)FIX2INT(v);
}
@@ -886,6 +904,7 @@ r_bytes0(len, arg)
VALUE src = arg->src;
VALUE n = LONG2NUM(len);
str = rb_funcall2(src, s_read, 1, &n);
+ reentrant_check(arg->data, s_read);
if (NIL_P(str)) goto too_short;
StringValue(str);
if (RSTRING(str)->len != len) goto too_short;
@@ -1236,6 +1255,7 @@ r_object0(arg, proc, ivp, extmod)
*ivp = Qfalse;
}
v = rb_funcall(klass, s_load, 1, data);
+ reentrant_check(arg->data, s_load);
r_entry(v, arg);
}
break;
@@ -1259,6 +1279,7 @@ r_object0(arg, proc, ivp, extmod)
r_entry(v, arg);
data = r_object(arg);
rb_funcall(v, s_mload, 1, data);
+ reentrant_check(arg->data, s_mload);
}
break;
@@ -1285,6 +1306,7 @@ r_object0(arg, proc, ivp, extmod)
warn = Qfalse;
}
v = rb_funcall(klass, s_alloc, 0);
+ reentrant_check(arg->data, s_alloc);
}
else {
v = rb_obj_alloc(klass);
@@ -1299,6 +1321,7 @@ r_object0(arg, proc, ivp, extmod)
rb_class2name(klass));
}
rb_funcall(v, s_load_data, 1, r_object0(arg, 0, 0, extmod));
+ reentrant_check(arg->data, s_load_data);
}
break;
@@ -1341,7 +1364,9 @@ r_object0(arg, proc, ivp, extmod)
break;
}
if (proc) {
- rb_funcall(proc, rb_intern("call"), 1, v);
+ ID s_call =
+ rb_funcall(proc, s_call, 1, v);
+ reentrant_check(arg->data, s_call);
}
return v;
}
@@ -1364,6 +1389,7 @@ static VALUE
load_ensure(arg)
struct load_arg *arg;
{
+ if (RBASIC(arg->data)->klass) return; /* ignore reentrant */
st_free_table(arg->symbols);
return 0;
}
@@ -1421,9 +1447,11 @@ marshal_load(argc, argv)
arg.symbols = st_init_numtable();
arg.data = rb_hash_new();
+ RBASIC(arg.data)->klass = 0;
if (NIL_P(proc)) arg.proc = 0;
else arg.proc = proc;
v = rb_ensure(load, (VALUE)&arg, load_ensure, (VALUE)&arg);
+ RBASIC(arg.data)->klass = rb_cHash;
return v;
}