Project

General

Profile

Feature #6440 » patch.diff

Glass_saga (Masaki Matsushita), 05/16/2012 12:49 PM

View differences:

marshal.c
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_getbyte, s_read, s_write, s_binmode;
static ID s_getbyte, s_read, s_readpartial, s_write, s_binmode;
typedef struct {
VALUE newclass;
......
struct load_arg {
VALUE src;
char *buf;
long buflen;
long offset;
int partial;
st_table *symbols;
st_table *data;
VALUE proc;
......
c = (unsigned char)RSTRING_PTR(arg->src)[arg->offset++];
}
else {
too_short:
rb_raise(rb_eArgError, "marshal data too short");
}
}
else {
VALUE src = arg->src;
VALUE v = rb_funcall2(src, s_getbyte, 0, 0);
check_load_arg(arg, s_getbyte);
if (NIL_P(v)) rb_eof_error();
c = (unsigned char)NUM2CHR(v);
if (arg->buflen == 0) {
VALUE str, n = LONG2NUM(BUFSIZ);
if (arg->partial)
str = rb_funcall2(arg->src, s_readpartial, 1, &n);
else
str = rb_funcall2(arg->src, s_read, 1, &n);
check_load_arg(arg, s_read);
if (NIL_P(str)) goto too_short;
StringValue(str);
arg->infection |= (int)FL_TEST(str, MARSHAL_INFECTION);
memcpy(arg->buf, RSTRING_PTR(str), RSTRING_LEN(str));
arg->offset = 0;
arg->buflen = RSTRING_LEN(str);
}
c = (unsigned char)arg->buf[arg->offset++];
arg->buflen--;
}
return c;
}
......
return x;
}
static VALUE
r_bytes1(long len, struct load_arg *arg)
{
VALUE str, n = LONG2NUM(len);
str = rb_funcall2(arg->src, s_read, 1, &n);
check_load_arg(arg, s_read);
if (NIL_P(str)) {
too_short:
rb_raise(rb_eArgError, "marshal data too short");
}
StringValue(str);
if (RSTRING_LEN(str) < len) goto too_short;
arg->infection |= (int)FL_TEST(str, MARSHAL_INFECTION);
return str;
}
static VALUE
r_bytes1_partial(long len, struct load_arg *arg)
{
long buflen = arg->buflen;
long tmp_len, need = len - buflen;
VALUE n = LONG2NUM(need > BUFSIZ ? need : BUFSIZ);
VALUE str, tmp;
const char *tmp_ptr;
tmp = rb_funcall2(arg->src, s_readpartial, 1, &n);
check_load_arg(arg, s_read);
if (NIL_P(tmp)) {
too_short:
rb_raise(rb_eArgError, "marshal data too short");
}
StringValue(tmp);
tmp_ptr = RSTRING_PTR(tmp);
tmp_len = RSTRING_LEN(tmp);
if (tmp_len < need) {
VALUE fill;
/* retry */
n = LONG2NUM(need-tmp_len);
fill = rb_funcall2(arg->src, s_read, 1, &n);
if (NIL_P(fill)) goto too_short;
StringValue(fill);
if (RSTRING_LEN(fill) < need-tmp_len) goto too_short;
rb_str_concat(tmp, fill);
tmp_len = RSTRING_LEN(tmp);
}
arg->infection |= (int)FL_TEST(tmp, MARSHAL_INFECTION);
str = rb_str_new(arg->buf+arg->offset, buflen);
rb_str_cat(str, tmp_ptr, need);
if (tmp_len-need > 0)
memcpy(arg->buf, tmp_ptr+need, tmp_len-need);
arg->offset = 0;
arg->buflen = tmp_len - need;
return str;
}
#define r_bytes(arg) r_bytes0(r_long(arg), (arg))
static VALUE
......
arg->offset += len;
}
else {
too_short:
rb_raise(rb_eArgError, "marshal data too short");
}
}
else {
VALUE src = arg->src;
VALUE n = LONG2NUM(len);
str = rb_funcall2(src, s_read, 1, &n);
check_load_arg(arg, s_read);
if (NIL_P(str)) goto too_short;
StringValue(str);
if (RSTRING_LEN(str) != len) goto too_short;
arg->infection |= (int)FL_TEST(str, MARSHAL_INFECTION);
if (len <= arg->buflen) {
str = rb_str_new(arg->buf+arg->offset, len);
arg->offset += len;
arg->buflen -= len;
}
else {
if (arg->partial)
str = r_bytes1_partial(len, arg);
else
str = r_bytes1(len, arg);
}
}
return str;
}
......
arg->data = st_init_numtable();
arg->compat_tbl = st_init_numtable();
arg->proc = 0;
arg->partial = 0;
if(NIL_P(v)) {
if (rb_respond_to(port, s_readpartial)) arg->partial = 1;
arg->buf = xmalloc(BUFSIZ);
}
major = r_byte(arg);
minor = r_byte(arg);
......
s_call = rb_intern("call");
s_getbyte = rb_intern("getbyte");
s_read = rb_intern("read");
s_readpartial = rb_intern("readpartial");
s_write = rb_intern("write");
s_binmode = rb_intern("binmode");
(1-1/2)