зеркало из https://github.com/github/ruby.git
compatible loader
* marshal.c (r_object0): also load TYPE_USRMARSHAL, TYPE_DATA using compatible loader. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@35898 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
Родитель
2493e48d40
Коммит
81a0c608eb
|
@ -1,3 +1,8 @@
|
|||
Mon Jun 4 11:40:28 2012 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||
|
||||
* marshal.c (r_object0): also load TYPE_USRMARSHAL, TYPE_DATA using
|
||||
compatible loader.
|
||||
|
||||
Mon Jun 4 11:33:42 2012 NAKAMURA Usaku <usa@ruby-lang.org>
|
||||
|
||||
* process.c (rb_run_exec_options_err): restore save_env() call for
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
create_makefile("-test-/marshal/compat")
|
|
@ -0,0 +1,32 @@
|
|||
#include <ruby.h>
|
||||
|
||||
static VALUE
|
||||
usr_dumper(VALUE self)
|
||||
{
|
||||
return self;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
usr_loader(VALUE self, VALUE m)
|
||||
{
|
||||
VALUE val = rb_ivar_get(m, rb_intern("@value"));
|
||||
*(int *)DATA_PTR(self) = NUM2INT(val);
|
||||
return self;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
compat_mload(VALUE self, VALUE data)
|
||||
{
|
||||
rb_ivar_set(self, rb_intern("@value"), data);
|
||||
return self;
|
||||
}
|
||||
|
||||
void
|
||||
Init_compat(void)
|
||||
{
|
||||
VALUE newclass = rb_path2class("Bug::Marshal::UsrMarshal");
|
||||
VALUE oldclass = rb_define_class_under(newclass, "compat", rb_cObject);
|
||||
|
||||
rb_define_method(oldclass, "marshal_load", compat_mload, 1);
|
||||
rb_marshal_define_compat(newclass, oldclass, usr_dumper, usr_loader);
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
create_makefile("-test-/marshal/usr")
|
|
@ -0,0 +1,35 @@
|
|||
#include <ruby.h>
|
||||
|
||||
static VALUE
|
||||
usr_alloc(VALUE klass)
|
||||
{
|
||||
int *p;
|
||||
return Data_Make_Struct(klass, int, 0, RUBY_DEFAULT_FREE, p);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
usr_init(VALUE self, VALUE val)
|
||||
{
|
||||
*(int *)DATA_PTR(self) = NUM2INT(val);
|
||||
return self;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
usr_value(VALUE self)
|
||||
{
|
||||
int val = *(int *)DATA_PTR(self);
|
||||
return INT2NUM(val);
|
||||
}
|
||||
|
||||
void
|
||||
Init_usr(void)
|
||||
{
|
||||
VALUE mMarshal = rb_define_module_under(rb_define_module("Bug"), "Marshal");
|
||||
VALUE newclass = rb_define_class_under(mMarshal, "UsrMarshal", rb_cObject);
|
||||
|
||||
rb_define_alloc_func(newclass, usr_alloc);
|
||||
rb_define_method(newclass, "initialize", usr_init, 1);
|
||||
rb_define_method(newclass, "value", usr_value, 0);
|
||||
rb_define_method(newclass, "marshal_load", usr_init, 1);
|
||||
rb_define_method(newclass, "marshal_dump", usr_value, 0);
|
||||
}
|
41
marshal.c
41
marshal.c
|
@ -1293,19 +1293,17 @@ path2module(VALUE path)
|
|||
}
|
||||
|
||||
static VALUE
|
||||
obj_alloc_by_path(VALUE path, struct load_arg *arg)
|
||||
obj_alloc_by_klass(VALUE klass, struct load_arg *arg, VALUE *oldclass)
|
||||
{
|
||||
VALUE klass;
|
||||
st_data_t data;
|
||||
rb_alloc_func_t allocator;
|
||||
|
||||
klass = path2class(path);
|
||||
|
||||
allocator = rb_get_alloc_func(klass);
|
||||
if (st_lookup(compat_allocator_tbl, (st_data_t)allocator, &data)) {
|
||||
marshal_compat_t *compat = (marshal_compat_t*)data;
|
||||
VALUE real_obj = rb_obj_alloc(klass);
|
||||
VALUE obj = rb_obj_alloc(compat->oldclass);
|
||||
if (oldclass) *oldclass = compat->oldclass;
|
||||
st_insert(arg->compat_tbl, (st_data_t)obj, (st_data_t)real_obj);
|
||||
return obj;
|
||||
}
|
||||
|
@ -1313,6 +1311,23 @@ obj_alloc_by_path(VALUE path, struct load_arg *arg)
|
|||
return rb_obj_alloc(klass);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
obj_alloc_by_path(VALUE path, struct load_arg *arg)
|
||||
{
|
||||
return obj_alloc_by_klass(path2class(path), arg, 0);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
append_extmod(VALUE obj, VALUE extmod)
|
||||
{
|
||||
long i = RARRAY_LEN(extmod);
|
||||
while (i > 0) {
|
||||
VALUE m = RARRAY_PTR(extmod)[--i];
|
||||
rb_extend_object(obj, m);
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
r_object0(struct load_arg *arg, int *ivp, VALUE extmod)
|
||||
{
|
||||
|
@ -1347,7 +1362,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod)
|
|||
{
|
||||
VALUE m = path2module(r_unique(arg));
|
||||
|
||||
if (NIL_P(extmod)) extmod = rb_ary_new2(0);
|
||||
if (NIL_P(extmod)) extmod = rb_ary_tmp_new(0);
|
||||
rb_ary_push(extmod, m);
|
||||
|
||||
v = r_object0(arg, 0, extmod);
|
||||
|
@ -1607,14 +1622,13 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod)
|
|||
case TYPE_USRMARSHAL:
|
||||
{
|
||||
VALUE klass = path2class(r_unique(arg));
|
||||
VALUE oldclass = 0;
|
||||
VALUE data;
|
||||
|
||||
v = rb_obj_alloc(klass);
|
||||
v = obj_alloc_by_klass(klass, arg, &oldclass);
|
||||
if (!NIL_P(extmod)) {
|
||||
while (RARRAY_LEN(extmod) > 0) {
|
||||
VALUE m = rb_ary_pop(extmod);
|
||||
rb_extend_object(v, m);
|
||||
}
|
||||
/* for the case marshal_load is overridden */
|
||||
append_extmod(v, extmod);
|
||||
}
|
||||
if (!rb_respond_to(v, s_mload)) {
|
||||
rb_raise(rb_eTypeError, "instance of %s needs to have method `marshal_load'",
|
||||
|
@ -1625,6 +1639,10 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod)
|
|||
rb_funcall(v, s_mload, 1, data);
|
||||
check_load_arg(arg, s_mload);
|
||||
v = r_leave(v, arg);
|
||||
if (!NIL_P(extmod)) {
|
||||
if (oldclass) append_extmod(v, extmod);
|
||||
rb_ary_clear(extmod);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1644,8 +1662,9 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod)
|
|||
case TYPE_DATA:
|
||||
{
|
||||
VALUE klass = path2class(r_unique(arg));
|
||||
VALUE oldclass = 0;
|
||||
|
||||
v = rb_obj_alloc(klass);
|
||||
v = obj_alloc_by_klass(klass, arg, &oldclass);
|
||||
if (!RB_TYPE_P(v, T_DATA)) {
|
||||
rb_raise(rb_eArgError, "dump format error");
|
||||
}
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
require 'test/unit'
|
||||
require_relative '../../ruby/envutil'
|
||||
require '-test-/marshal/usr'
|
||||
|
||||
module Bug end
|
||||
|
||||
module Bug::Marshal
|
||||
class TestUsrMarshal < Test::Unit::TestCase
|
||||
def old_dump
|
||||
@old_dump ||=
|
||||
begin
|
||||
src = "module Bug; module Marshal; class UsrMarshal; def initialize(val) @value = val; end; end; ::Marshal.dump(UsrMarshal.new(42), STDOUT); end; end"
|
||||
EnvUtil.invoke_ruby([], src, true)[0]
|
||||
end
|
||||
end
|
||||
|
||||
def test_marshal
|
||||
v = ::Marshal.load(::Marshal.dump(UsrMarshal.new(42)))
|
||||
assert_instance_of(UsrMarshal, v)
|
||||
assert_equal(42, v.value)
|
||||
end
|
||||
|
||||
def test_incompat
|
||||
e = assert_raise(ArgumentError) {::Marshal.load(old_dump)}
|
||||
assert_equal("dump format error", e.message)
|
||||
end
|
||||
|
||||
def test_compat
|
||||
out, err = EnvUtil.invoke_ruby(["-r-test-/marshal/usr", "-r-test-/marshal/compat", "-e", "::Marshal.dump(::Marshal.load(STDIN), STDOUT)"], old_dump, true, true)
|
||||
assert_equal(::Marshal.dump(UsrMarshal.new(42)), out)
|
||||
assert_equal("", err)
|
||||
end
|
||||
end
|
||||
end
|
Загрузка…
Ссылка в новой задаче