summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog14
-rw-r--r--gc.c25
-rw-r--r--intern.h1
-rw-r--r--marshal.c107
-rw-r--r--test/ruby/marshaltestlib.rb6
-rw-r--r--test/ruby/test_marshal.rb6
-rw-r--r--version.h8
7 files changed, 129 insertions, 38 deletions
diff --git a/ChangeLog b/ChangeLog
index 3e7b575fe0..c335eedbde 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+Thu Jan 22 15:19:39 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * marshal.c (marshal_load): arg.data is no longer a VALUE but a
+ st_table, and freed in load_ensure. pointed out by pegacorn.
+ [ruby-dev:37008]
+
+Thu Jan 22 15:19:39 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * gc.c (rb_mark_set): new function to mark keys.
+
+ * marshal.c (struct dump_arg, struct load_arg): added wrappers to mark
+ data entries. backport from trunk r13527,r13528,r13961,r16533.
+ [ruby-dev:36082]
+
Wed Jan 21 11:12:55 2009 NAKAMURA Usaku <usa@ruby-lang.org>
* win32/win32.c (filetime_to_timeval): new function, split from
diff --git a/gc.c b/gc.c
index 6edd5b433f..111220eb76 100644
--- a/gc.c
+++ b/gc.c
@@ -724,6 +724,31 @@ rb_mark_tbl(tbl)
}
static int
+mark_key(key, value, lev)
+ VALUE key, value;
+ int lev;
+{
+ gc_mark(key, lev);
+ return ST_CONTINUE;
+}
+
+static void
+mark_set(tbl, lev)
+ st_table *tbl;
+ int lev;
+{
+ if (!tbl) return;
+ st_foreach(tbl, mark_key, lev);
+}
+
+void
+rb_mark_set(tbl)
+ st_table *tbl;
+{
+ mark_set(tbl, 0);
+}
+
+static int
mark_keyvalue(key, value, lev)
VALUE key;
VALUE value;
diff --git a/intern.h b/intern.h
index 00bb8f16b5..47f0cddaa2 100644
--- a/intern.h
+++ b/intern.h
@@ -256,6 +256,7 @@ int rb_during_gc _((void));
char *rb_source_filename _((const char*));
void rb_gc_mark_locations _((VALUE*, VALUE*));
void rb_mark_tbl _((struct st_table*));
+void rb_mark_set _((struct st_table*));
void rb_mark_hash _((struct st_table*));
void rb_gc_mark_maybe _((VALUE));
void rb_gc_mark _((VALUE));
diff --git a/marshal.c b/marshal.c
index f643450abd..6b5a81cfc1 100644
--- a/marshal.c
+++ b/marshal.c
@@ -84,22 +84,13 @@ static ID s_dump, s_load, s_mdump, s_mload;
static ID s_dump_data, s_load_data, s_alloc, s_call;
static ID s_getc, s_read, s_write, s_binmode;
-static void
-reentrant_check(obj, sym)
- VALUE obj;
- ID sym;
-{
- if (obj && RBASIC(obj)->klass) {
- rb_raise(rb_eRuntimeError, "%s reentered", rb_id2name(sym));
- }
-}
-
struct dump_arg {
VALUE obj;
VALUE str, dest;
st_table *symbols;
st_table *data;
int taint;
+ VALUE wrapper;
};
struct dump_call_arg {
@@ -108,6 +99,27 @@ struct dump_call_arg {
int limit;
};
+static void
+check_dump_arg(arg, sym)
+ struct dump_arg *arg;
+ ID sym;
+{
+ if (!DATA_PTR(arg->wrapper)) {
+ rb_raise(rb_eRuntimeError, "Marshal.dump reentered at %s",
+ rb_id2name(sym));
+ }
+}
+
+static void
+mark_dump_arg(ptr)
+ void *ptr;
+{
+ struct dump_arg *p = ptr;
+ if (!ptr)
+ return;
+ rb_mark_set(p->data);
+}
+
static VALUE
class2path(klass)
VALUE klass;
@@ -515,7 +527,7 @@ w_object(obj, arg, limit)
volatile VALUE v;
v = rb_funcall(obj, s_mdump, 0, 0);
- reentrant_check(arg->str, s_mdump);
+ check_dump_arg(arg, s_mdump);
w_class(TYPE_USRMARSHAL, obj, arg, Qfalse);
w_object(v, arg, limit);
if (ivtbl) w_ivar(0, &c_arg);
@@ -525,7 +537,7 @@ w_object(obj, arg, limit)
VALUE v;
v = rb_funcall(obj, s_dump, 1, INT2NUM(limit));
- reentrant_check(arg->str, s_dump);
+ check_dump_arg(arg, s_dump);
if (TYPE(v) != T_STRING) {
rb_raise(rb_eTypeError, "_dump() must return string");
}
@@ -670,7 +682,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);
+ check_dump_arg(arg, s_dump_data);
w_class(TYPE_DATA, obj, arg, Qtrue);
w_object(v, arg, limit);
}
@@ -703,9 +715,11 @@ static VALUE
dump_ensure(arg)
struct dump_arg *arg;
{
- if (RBASIC(arg->str)->klass) return 0; /* ignore reentrant */
+ if (!DATA_PTR(arg->wrapper)) return 0;
st_free_table(arg->symbols);
st_free_table(arg->data);
+ DATA_PTR(arg->wrapper) = 0;
+ arg->wrapper = 0;
if (arg->taint) {
OBJ_TAINT(arg->str);
}
@@ -772,7 +786,7 @@ marshal_dump(argc, argv)
arg.dest = port;
if (rb_respond_to(port, s_binmode)) {
rb_funcall2(port, s_binmode, 0, 0);
- reentrant_check(arg.str, s_dump_data);
+ check_dump_arg(&arg, s_dump_data);
}
}
else {
@@ -782,6 +796,7 @@ marshal_dump(argc, argv)
arg.symbols = st_init_numtable();
arg.data = st_init_numtable();
arg.taint = Qfalse;
+ arg.wrapper = Data_Wrap_Struct(rb_cData, mark_dump_arg, 0, &arg);
c_arg.obj = obj;
c_arg.arg = &arg;
c_arg.limit = limit;
@@ -799,11 +814,33 @@ struct load_arg {
VALUE src;
long offset;
st_table *symbols;
- VALUE data;
+ st_table *data;
VALUE proc;
int taint;
+ VALUE wrapper;
};
+static void
+check_load_arg(arg, sym)
+ struct load_arg *arg;
+ ID sym;
+{
+ if (!DATA_PTR(arg->wrapper)) {
+ rb_raise(rb_eRuntimeError, "Marshal.load reentered at %s",
+ rb_id2name(sym));
+ }
+}
+
+static void
+mark_load_arg(ptr)
+ void *ptr;
+{
+ struct load_arg *p = ptr;
+ if (!ptr)
+ return;
+ rb_mark_tbl(p->data);
+}
+
static VALUE r_object _((struct load_arg *arg));
static int
@@ -823,7 +860,7 @@ r_byte(arg)
else {
VALUE src = arg->src;
VALUE v = rb_funcall2(src, s_getc, 0, 0);
- reentrant_check(arg->data, s_getc);
+ check_load_arg(arg, s_getc);
if (NIL_P(v)) rb_eof_error();
c = (unsigned char)FIX2INT(v);
}
@@ -904,7 +941,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);
+ check_load_arg(arg, s_read);
if (NIL_P(str)) goto too_short;
StringValue(str);
if (RSTRING(str)->len != len) goto too_short;
@@ -967,7 +1004,7 @@ r_entry(v, arg)
VALUE v;
struct load_arg *arg;
{
- rb_hash_aset(arg->data, INT2FIX(RHASH(arg->data)->tbl->num_entries), v);
+ st_insert(arg->data, arg->data->num_entries, (st_data_t)v);
if (arg->taint) OBJ_TAINT(v);
return v;
}
@@ -1023,14 +1060,15 @@ r_object0(arg, proc, ivp, extmod)
VALUE v = Qnil;
int type = r_byte(arg);
long id;
+ st_data_t link;
switch (type) {
case TYPE_LINK:
id = r_long(arg);
- v = rb_hash_aref(arg->data, LONG2FIX(id));
- if (NIL_P(v)) {
+ if (!st_lookup(arg->data, (st_data_t)id, &link)) {
rb_raise(rb_eArgError, "dump format error (unlinked)");
}
+ v = (st_data_t)link;
return v;
case TYPE_IVAR:
@@ -1255,7 +1293,7 @@ r_object0(arg, proc, ivp, extmod)
*ivp = Qfalse;
}
v = rb_funcall(klass, s_load, 1, data);
- reentrant_check(arg->data, s_load);
+ check_load_arg(arg, s_load);
r_entry(v, arg);
}
break;
@@ -1279,7 +1317,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);
+ check_load_arg(arg, s_mload);
}
break;
@@ -1306,7 +1344,7 @@ r_object0(arg, proc, ivp, extmod)
warn = Qfalse;
}
v = rb_funcall(klass, s_alloc, 0);
- reentrant_check(arg->data, s_alloc);
+ check_load_arg(arg, s_alloc);
}
else {
v = rb_obj_alloc(klass);
@@ -1321,7 +1359,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);
+ check_load_arg(arg, s_load_data);
}
break;
@@ -1365,7 +1403,7 @@ r_object0(arg, proc, ivp, extmod)
}
if (proc) {
rb_funcall(proc, s_call, 1, v);
- reentrant_check(arg->data, s_call);
+ check_load_arg(arg, s_call);
}
return v;
}
@@ -1388,8 +1426,11 @@ static VALUE
load_ensure(arg)
struct load_arg *arg;
{
- if (RBASIC(arg->data)->klass) return 0; /* ignore reentrant */
+ if (!DATA_PTR(arg->wrapper)) return 0;
st_free_table(arg->symbols);
+ st_free_table(arg->data);
+ DATA_PTR(arg->wrapper) = 0;
+ arg->wrapper = 0;
return 0;
}
@@ -1431,7 +1472,10 @@ marshal_load(argc, argv)
}
arg.src = port;
arg.offset = 0;
- arg.data = 0;
+ arg.symbols = st_init_numtable();
+ arg.data = st_init_numtable();
+ arg.proc = 0;
+ arg.wrapper = Data_Wrap_Struct(rb_cData, mark_load_arg, 0, &arg);
major = r_byte(&arg);
minor = r_byte(&arg);
@@ -1446,13 +1490,8 @@ marshal_load(argc, argv)
MARSHAL_MAJOR, MARSHAL_MINOR, major, minor);
}
- 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;
+ if (!NIL_P(proc)) arg.proc = proc;
v = rb_ensure(load, (VALUE)&arg, load_ensure, (VALUE)&arg);
- RBASIC(arg.data)->klass = rb_cHash;
return v;
}
diff --git a/test/ruby/marshaltestlib.rb b/test/ruby/marshaltestlib.rb
index 891f43b1f7..ae60cd8479 100644
--- a/test/ruby/marshaltestlib.rb
+++ b/test/ruby/marshaltestlib.rb
@@ -193,6 +193,12 @@ module MarshalTestLib
1.instance_eval { remove_instance_variable("@iv") }
end
+ def test_fixnum_64bit
+ obj = [1220278665, 1220278662, 1220278661, 1220278661, 1220278656]
+
+ marshal_equal(obj)
+ end
+
def test_float
marshal_equal(-1.0)
marshal_equal(0.0)
diff --git a/test/ruby/test_marshal.rb b/test/ruby/test_marshal.rb
index 11f3583076..68f50ff728 100644
--- a/test/ruby/test_marshal.rb
+++ b/test/ruby/test_marshal.rb
@@ -12,11 +12,17 @@ class TestMarshal < Test::Unit::TestCase
include MarshalTestLib
def encode(o)
+ stress, GC.stress = GC.stress, true
Marshal.dump(o)
+ ensure
+ GC.stress = stress
end
def decode(s)
+ stress, GC.stress = GC.stress, true
Marshal.load(s)
+ ensure
+ GC.stress = stress
end
def fact(n)
diff --git a/version.h b/version.h
index 6fb2c6d437..1498e0742a 100644
--- a/version.h
+++ b/version.h
@@ -1,15 +1,15 @@
#define RUBY_VERSION "1.8.7"
-#define RUBY_RELEASE_DATE "2009-01-21"
+#define RUBY_RELEASE_DATE "2009-01-22"
#define RUBY_VERSION_CODE 187
-#define RUBY_RELEASE_CODE 20090121
-#define RUBY_PATCHLEVEL 91
+#define RUBY_RELEASE_CODE 20090122
+#define RUBY_PATCHLEVEL 92
#define RUBY_VERSION_MAJOR 1
#define RUBY_VERSION_MINOR 8
#define RUBY_VERSION_TEENY 7
#define RUBY_RELEASE_YEAR 2009
#define RUBY_RELEASE_MONTH 1
-#define RUBY_RELEASE_DAY 21
+#define RUBY_RELEASE_DAY 22
#ifdef RUBY_EXTERN
RUBY_EXTERN const char ruby_version[];