Project

General

Profile

Feature #6440 » patch2.diff

Glass_saga (Masaki Matsushita), 06/11/2012 10:25 PM

View differences:

marshal.c
958 958

  
959 959
struct load_arg {
960 960
    VALUE src;
961
    char *buf;
962
    long buflen;
963
    long readable;
961 964
    long offset;
962 965
    st_table *symbols;
963 966
    st_table *data;
......
1011 1014
static ID r_symbol(struct load_arg *arg);
1012 1015
static VALUE path2class(VALUE path);
1013 1016

  
1017
NORETURN(static void too_short(void));
1018
static void
1019
too_short(void)
1020
{
1021
    rb_raise(rb_eArgError, "marshal data too short");
1022
}
1023

  
1014 1024
static st_index_t
1015 1025
r_prepare(struct load_arg *arg)
1016 1026
{
......
1020 1030
    return idx;
1021 1031
}
1022 1032

  
1033
static unsigned char
1034
r_byte1_buffered(struct load_arg *arg)
1035
{
1036
    if (arg->buflen == 0) {
1037
	long readable = arg->readable < BUFSIZ ? arg->readable : BUFSIZ;
1038
	VALUE str, n = LONG2NUM(readable);
1039

  
1040
	str = rb_funcall2(arg->src, s_read, 1, &n);
1041

  
1042
	check_load_arg(arg, s_read);
1043
	if (NIL_P(str)) too_short();
1044
	StringValue(str);
1045
	arg->infection |= (int)FL_TEST(str, MARSHAL_INFECTION);
1046
	memcpy(arg->buf, RSTRING_PTR(str), RSTRING_LEN(str));
1047
	arg->offset = 0;
1048
	arg->buflen = RSTRING_LEN(str);
1049
    }
1050
    arg->buflen--;
1051
    return arg->buf[arg->offset++];
1052
}
1053

  
1023 1054
static int
1024 1055
r_byte(struct load_arg *arg)
1025 1056
{
......
1030 1061
	    c = (unsigned char)RSTRING_PTR(arg->src)[arg->offset++];
1031 1062
	}
1032 1063
	else {
1033
	    rb_raise(rb_eArgError, "marshal data too short");
1064
	    too_short();
1034 1065
	}
1035 1066
    }
1036 1067
    else {
1037
	VALUE src = arg->src;
1038
	VALUE v = rb_funcall2(src, s_getbyte, 0, 0);
1039
	check_load_arg(arg, s_getbyte);
1040
	if (NIL_P(v)) rb_eof_error();
1041
	c = (unsigned char)NUM2CHR(v);
1068
	if (arg->readable >0 || arg->buflen > 0) {
1069
	    c = r_byte1_buffered(arg);
1070
	}
1071
	else {
1072
	    VALUE v = rb_funcall2(arg->src, s_getbyte, 0, 0);
1073
	    check_load_arg(arg, s_getbyte);
1074
	    if (NIL_P(v)) rb_eof_error();
1075
	    c = (unsigned char)NUM2CHR(v);
1076
	}
1042 1077
    }
1043 1078
    return c;
1044 1079
}
......
1091 1126
    return x;
1092 1127
}
1093 1128

  
1129
static VALUE
1130
r_bytes1(long len, struct load_arg *arg)
1131
{
1132
    VALUE str, n = LONG2NUM(len);
1133

  
1134
    str = rb_funcall2(arg->src, s_read, 1, &n);
1135
    check_load_arg(arg, s_read);
1136
    if (NIL_P(str)) too_short();
1137
    StringValue(str);
1138
    if (RSTRING_LEN(str) != len) too_short();
1139
    arg->infection |= (int)FL_TEST(str, MARSHAL_INFECTION);
1140

  
1141
    return str;
1142
}
1143

  
1144
static VALUE
1145
r_bytes1_buffered(long len, struct load_arg *arg)
1146
{
1147
    VALUE str;
1148

  
1149
    if (len <= arg->buflen) {
1150
	str = rb_str_new(arg->buf+arg->offset, len);
1151
	arg->offset += len;
1152
	arg->buflen -= len;
1153
    }
1154
    else {
1155
	long buflen = arg->buflen;
1156
	long readable = arg->readable + 1;
1157
	long tmp_len, read_len, need_len = len - buflen;
1158
	VALUE tmp, n;
1159

  
1160
	read_len = need_len > readable ? need_len : readable;
1161
	read_len = read_len < BUFSIZ ? read_len : BUFSIZ;
1162
	n = LONG2NUM(read_len);
1163
	tmp = rb_funcall2(arg->src, s_read, 1, &n);
1164

  
1165
	check_load_arg(arg, s_read);
1166
	if (NIL_P(tmp)) too_short();
1167
	StringValue(tmp);
1168

  
1169
	tmp_len = RSTRING_LEN(tmp);
1170

  
1171
	if (tmp_len < need_len) too_short();
1172
	arg->infection |= (int)FL_TEST(tmp, MARSHAL_INFECTION);
1173

  
1174
	str = rb_str_new(arg->buf+arg->offset, buflen);
1175
	rb_str_cat(str, RSTRING_PTR(tmp), need_len);
1176

  
1177
	if (tmp_len > need_len) {
1178
	    buflen = tmp_len - need_len;
1179
	    memcpy(arg->buf, RSTRING_PTR(tmp)+need_len, buflen);
1180
	    arg->buflen = buflen;
1181
	}
1182
	else {
1183
	    arg->buflen = 0;
1184
	}
1185
	arg->offset = 0;
1186
    }
1187

  
1188
    return str;
1189
}
1190

  
1094 1191
#define r_bytes(arg) r_bytes0(r_long(arg), (arg))
1095 1192

  
1096 1193
static VALUE
......
1105 1202
	    arg->offset += len;
1106 1203
	}
1107 1204
	else {
1108
	  too_short:
1109
	    rb_raise(rb_eArgError, "marshal data too short");
1205
	    too_short();
1110 1206
	}
1111 1207
    }
1112 1208
    else {
1113
	VALUE src = arg->src;
1114
	VALUE n = LONG2NUM(len);
1115
	str = rb_funcall2(src, s_read, 1, &n);
1116
	check_load_arg(arg, s_read);
1117
	if (NIL_P(str)) goto too_short;
1118
	StringValue(str);
1119
	if (RSTRING_LEN(str) != len) goto too_short;
1120
	arg->infection |= (int)FL_TEST(str, MARSHAL_INFECTION);
1209
	if (arg->readable > 0 || arg->buflen > 0) {
1210
	    str = r_bytes1_buffered(len, arg);
1211
	}
1212
	else {
1213
	    str = r_bytes1(len, arg);
1214
	}
1121 1215
    }
1122 1216
    return str;
1123 1217
}
......
1535 1629

  
1536 1630
	    v = rb_ary_new2(len);
1537 1631
	    v = r_entry(v, arg);
1632
	    arg->readable += len - 1;
1538 1633
	    while (len--) {
1539 1634
		rb_ary_push(v, r_object(arg));
1635
		arg->readable--;
1540 1636
	    }
1541 1637
            v = r_leave(v, arg);
1638
	    arg->readable++;
1542 1639
	}
1543 1640
	break;
1544 1641

  
......
1549 1646

  
1550 1647
	    v = rb_hash_new();
1551 1648
	    v = r_entry(v, arg);
1649
	    arg->readable += (len - 1) * 2;
1552 1650
	    while (len--) {
1553 1651
		VALUE key = r_object(arg);
1554 1652
		VALUE value = r_object(arg);
1555 1653
		rb_hash_aset(v, key, value);
1654
		arg->readable -= 2;
1556 1655
	    }
1656
	    arg->readable += 2;
1557 1657
	    if (type == TYPE_HASH_DEF) {
1558 1658
		RHASH_IFNONE(v) = r_object(arg);
1559 1659
	    }
......
1580 1680
                         rb_class2name(klass));
1581 1681
            }
1582 1682

  
1683
	    arg->readable += (len - 1) * 2;
1583 1684
	    v = r_entry0(v, idx, arg);
1584 1685
	    values = rb_ary_new2(len);
1585 1686
	    for (i=0; i<len; i++) {
......
1592 1693
			     rb_id2name(SYM2ID(RARRAY_PTR(mem)[i])));
1593 1694
		}
1594 1695
                rb_ary_push(values, r_object(arg));
1696
		arg->readable -= 2;
1595 1697
	    }
1596 1698
            rb_struct_initialize(v, values);
1597 1699
            v = r_leave(v, arg);
1700
	    arg->readable += 2;
1598 1701
	}
1599 1702
	break;
1600 1703

  
......
1741 1844
static void
1742 1845
clear_load_arg(struct load_arg *arg)
1743 1846
{
1847
    if (arg->buf) {
1848
	xfree(arg->buf);
1849
	arg->buf = 0;
1850
    }
1851
    arg->buflen = 0;
1852
    arg->offset = 0;
1853
    arg->readable = 0;
1744 1854
    if (!arg->symbols) return;
1745 1855
    st_free_table(arg->symbols);
1746 1856
    arg->symbols = 0;
......
1793 1903
    arg->data    = st_init_numtable();
1794 1904
    arg->compat_tbl = st_init_numtable();
1795 1905
    arg->proc = 0;
1906
    arg->readable = 0;
1907

  
1908
    if (NIL_P(v))
1909
	arg->buf = xmalloc(BUFSIZ);
1910
    else
1911
	arg->buf = 0;
1796 1912

  
1797 1913
    major = r_byte(arg);
1798 1914
    minor = r_byte(arg);