@@ -84,6 +84,16 @@ static ID s_dump, s_load, s_mdump, s_mload;
84
84
static ID s_dump_data , s_load_data , s_alloc ;
85
85
static ID s_getc , s_read , s_write , s_binmode ;
86
86
87
+ static void
88
+ reentrant_check (obj , sym )
89
+ VALUE obj ;
90
+ ID sym ;
91
+ {
92
+ if (RBASIC (obj )-> klass ) {
93
+ rb_raise (rb_eRuntimeError , "%s reentered" , rb_id2name (sym ));
94
+ }
95
+ }
96
+
87
97
struct dump_arg {
88
98
VALUE obj ;
89
99
VALUE str , dest ;
@@ -505,6 +515,7 @@ w_object(obj, arg, limit)
505
515
volatile VALUE v ;
506
516
507
517
v = rb_funcall (obj , s_mdump , 0 , 0 );
518
+ reentrant_check (arg -> str , s_mdump );
508
519
w_class (TYPE_USRMARSHAL , obj , arg , Qfalse );
509
520
w_object (v , arg , limit );
510
521
if (ivtbl ) w_ivar (0 , & c_arg );
@@ -514,6 +525,7 @@ w_object(obj, arg, limit)
514
525
VALUE v ;
515
526
516
527
v = rb_funcall (obj , s_dump , 1 , INT2NUM (limit ));
528
+ reentrant_check (arg -> str , s_dump );
517
529
if (TYPE (v ) != T_STRING ) {
518
530
rb_raise (rb_eTypeError , "_dump() must return string" );
519
531
}
@@ -658,6 +670,7 @@ w_object(obj, arg, limit)
658
670
rb_obj_classname (obj ));
659
671
}
660
672
v = rb_funcall (obj , s_dump_data , 0 );
673
+ reentrant_check (arg -> str , s_dump_data );
661
674
w_class (TYPE_DATA , obj , arg , Qtrue );
662
675
w_object (v , arg , limit );
663
676
}
@@ -690,11 +703,13 @@ static VALUE
690
703
dump_ensure (arg )
691
704
struct dump_arg * arg ;
692
705
{
706
+ if (RBASIC (arg -> str )-> klass ) return ; /* ignore reentrant */
693
707
st_free_table (arg -> symbols );
694
708
st_free_table (arg -> data );
695
709
if (arg -> taint ) {
696
710
OBJ_TAINT (arg -> str );
697
711
}
712
+
698
713
return 0 ;
699
714
}
700
715
@@ -747,20 +762,21 @@ marshal_dump(argc, argv)
747
762
else port = a1 ;
748
763
}
749
764
arg .dest = 0 ;
765
+ arg .str = rb_str_buf_new (0 );
766
+ RBASIC (arg .str )-> klass = 0 ;
750
767
if (!NIL_P (port )) {
751
768
if (!rb_respond_to (port , s_write )) {
752
769
type_error :
753
770
rb_raise (rb_eTypeError , "instance of IO needed" );
754
771
}
755
- arg .str = rb_str_buf_new (0 );
756
772
arg .dest = port ;
757
773
if (rb_respond_to (port , s_binmode )) {
758
774
rb_funcall2 (port , s_binmode , 0 , 0 );
775
+ reentrant_check (arg .str , s_dump_data );
759
776
}
760
777
}
761
778
else {
762
- port = rb_str_buf_new (0 );
763
- arg .str = port ;
779
+ port = arg .str ;
764
780
}
765
781
766
782
arg .symbols = st_init_numtable ();
@@ -774,6 +790,7 @@ marshal_dump(argc, argv)
774
790
w_byte (MARSHAL_MINOR , & arg );
775
791
776
792
rb_ensure (dump , (VALUE )& c_arg , dump_ensure , (VALUE )& arg );
793
+ RBASIC (arg .str )-> klass = rb_cString ;
777
794
778
795
return port ;
779
796
}
@@ -806,6 +823,7 @@ r_byte(arg)
806
823
else {
807
824
VALUE src = arg -> src ;
808
825
VALUE v = rb_funcall2 (src , s_getc , 0 , 0 );
826
+ reentrant_check (arg -> data , s_getc );
809
827
if (NIL_P (v )) rb_eof_error ();
810
828
c = (unsigned char )FIX2INT (v );
811
829
}
@@ -886,6 +904,7 @@ r_bytes0(len, arg)
886
904
VALUE src = arg -> src ;
887
905
VALUE n = LONG2NUM (len );
888
906
str = rb_funcall2 (src , s_read , 1 , & n );
907
+ reentrant_check (arg -> data , s_read );
889
908
if (NIL_P (str )) goto too_short ;
890
909
StringValue (str );
891
910
if (RSTRING (str )-> len != len ) goto too_short ;
@@ -1239,6 +1258,7 @@ r_object0(arg, proc, ivp, extmod)
1239
1258
* ivp = Qfalse ;
1240
1259
}
1241
1260
v = rb_funcall (klass , s_load , 1 , data );
1261
+ reentrant_check (arg -> data , s_load );
1242
1262
r_entry (v , arg );
1243
1263
}
1244
1264
break ;
@@ -1262,6 +1282,7 @@ r_object0(arg, proc, ivp, extmod)
1262
1282
r_entry (v , arg );
1263
1283
data = r_object (arg );
1264
1284
rb_funcall (v , s_mload , 1 , data );
1285
+ reentrant_check (arg -> data , s_mload );
1265
1286
}
1266
1287
break ;
1267
1288
@@ -1288,6 +1309,7 @@ r_object0(arg, proc, ivp, extmod)
1288
1309
warn = Qfalse ;
1289
1310
}
1290
1311
v = rb_funcall (klass , s_alloc , 0 );
1312
+ reentrant_check (arg -> data , s_alloc );
1291
1313
}
1292
1314
else {
1293
1315
v = rb_obj_alloc (klass );
@@ -1302,6 +1324,7 @@ r_object0(arg, proc, ivp, extmod)
1302
1324
rb_class2name (klass ));
1303
1325
}
1304
1326
rb_funcall (v , s_load_data , 1 , r_object0 (arg , 0 , 0 , extmod ));
1327
+ reentrant_check (arg -> data , s_load_data );
1305
1328
}
1306
1329
break ;
1307
1330
@@ -1344,7 +1367,9 @@ r_object0(arg, proc, ivp, extmod)
1344
1367
break ;
1345
1368
}
1346
1369
if (proc ) {
1347
- rb_funcall (proc , rb_intern ("call" ), 1 , v );
1370
+ ID s_call =
1371
+ rb_funcall (proc , s_call , 1 , v );
1372
+ reentrant_check (arg -> data , s_call );
1348
1373
}
1349
1374
return v ;
1350
1375
}
@@ -1367,6 +1392,7 @@ static VALUE
1367
1392
load_ensure (arg )
1368
1393
struct load_arg * arg ;
1369
1394
{
1395
+ if (RBASIC (arg -> data )-> klass ) return ; /* ignore reentrant */
1370
1396
st_free_table (arg -> symbols );
1371
1397
return 0 ;
1372
1398
}
@@ -1424,9 +1450,11 @@ marshal_load(argc, argv)
1424
1450
1425
1451
arg .symbols = st_init_numtable ();
1426
1452
arg .data = rb_hash_new ();
1453
+ RBASIC (arg .data )-> klass = 0 ;
1427
1454
if (NIL_P (proc )) arg .proc = 0 ;
1428
1455
else arg .proc = proc ;
1429
1456
v = rb_ensure (load , (VALUE )& arg , load_ensure , (VALUE )& arg );
1457
+ RBASIC (arg .data )-> klass = rb_cHash ;
1430
1458
1431
1459
return v ;
1432
1460
}
0 commit comments