@@ -362,16 +362,20 @@ typedef struct stcxt {
362
362
SV * (* * retrieve_vtbl )(pTHX_ struct stcxt * , const char * ); /* retrieve dispatch table */
363
363
SV * prev ; /* contexts chained backwards in real recursion */
364
364
SV * my_sv ; /* the blessed scalar who's SvPVX() I am */
365
+ SV * recur_sv ; /* check only one recursive SV */
365
366
int in_retrieve_overloaded ; /* performance hack for retrieving overloaded objects */
366
367
int flags ; /* controls whether to bless or tie objects */
367
- U16 av_depth ; /* avoid stack overflows RT #97526 */
368
- U16 hv_depth ; /* avoid stack overflows RT #97526 */
368
+ U16 recur_depth ; /* avoid stack overflows RT #97526 */
369
369
} stcxt_t ;
370
370
371
371
/* Note: We dont count nested scalars. This will have to count all refs
372
372
without any recursion detection. */
373
373
/* JSON::XS has 512 */
374
- #define MAX_DEPTH 3000
374
+ #if PTRSIZE == 8
375
+ # define MAX_DEPTH 2000
376
+ #else
377
+ # define MAX_DEPTH 1200
378
+ #endif
375
379
#define MAX_DEPTH_ERROR "Max. recursion depth with nested structures exceeded"
376
380
377
381
static int storable_free (pTHX_ SV * sv , MAGIC * mg );
@@ -1430,8 +1434,8 @@ static void reset_context(stcxt_t *cxt)
1430
1434
{
1431
1435
cxt -> entry = 0 ;
1432
1436
cxt -> s_dirty = 0 ;
1433
- cxt -> av_depth = 0 ;
1434
- cxt -> hv_depth = 0 ;
1437
+ cxt -> recur_sv = NULL ;
1438
+ cxt -> recur_depth = 0 ;
1435
1439
cxt -> optype &= ~(ST_STORE |ST_RETRIEVE ); /* Leave ST_CLONE alone */
1436
1440
}
1437
1441
@@ -2123,6 +2127,7 @@ static int known_class(pTHX_
2123
2127
*/
2124
2128
static int store_ref (pTHX_ stcxt_t * cxt , SV * sv )
2125
2129
{
2130
+ int retval ;
2126
2131
int is_weak = 0 ;
2127
2132
TRACEME (("store_ref (0x%" UVxf ")" , PTR2UV (sv )));
2128
2133
@@ -2148,10 +2153,21 @@ static int store_ref(pTHX_ stcxt_t *cxt, SV *sv)
2148
2153
} else
2149
2154
PUTMARK (is_weak ? SX_WEAKREF : SX_REF );
2150
2155
2151
- /*if (cxt->entry && ++cxt->ref_cnt > MAX_REF_CNT) {
2152
- CROAK(("Max. recursion depth with nested refs exceeded"));
2153
- }*/
2154
- return store (aTHX_ cxt , sv );
2156
+ TRACEME (("recur_depth %u, recur_sv (0x%" UVxf ")" , cxt -> recur_depth ,
2157
+ PTR2UV (cxt -> recur_sv )));
2158
+ if (cxt -> entry && cxt -> recur_sv == sv ) {
2159
+ if (++ cxt -> recur_depth > MAX_DEPTH ) {
2160
+ CROAK ((MAX_DEPTH_ERROR ));
2161
+ }
2162
+ }
2163
+ cxt -> recur_sv = sv ;
2164
+
2165
+ retval = store (aTHX_ cxt , sv );
2166
+ if (cxt -> entry && cxt -> recur_sv == sv && cxt -> recur_depth > 0 ) {
2167
+ TRACEME (("recur_depth --%u" , cxt -> recur_depth ));
2168
+ -- cxt -> recur_depth ;
2169
+ }
2170
+ return retval ;
2155
2171
}
2156
2172
2157
2173
/*
@@ -2424,9 +2440,14 @@ static int store_array(pTHX_ stcxt_t *cxt, AV *av)
2424
2440
TRACEME (("size = %d" , (int )l ));
2425
2441
}
2426
2442
2427
- if (cxt -> entry && ++ cxt -> av_depth > MAX_DEPTH ) {
2428
- CROAK ((MAX_DEPTH_ERROR ));
2443
+ TRACEME (("recur_depth %u, recur_sv (0x%" UVxf ")" , cxt -> recur_depth ,
2444
+ PTR2UV (cxt -> recur_sv )));
2445
+ if (cxt -> entry && cxt -> recur_sv == (SV * )av ) {
2446
+ if (++ cxt -> recur_depth > MAX_DEPTH ) {
2447
+ CROAK ((MAX_DEPTH_ERROR ));
2448
+ }
2429
2449
}
2450
+ cxt -> recur_sv = (SV * )av ;
2430
2451
2431
2452
/*
2432
2453
* Now store each item recursively.
@@ -2457,7 +2478,10 @@ static int store_array(pTHX_ stcxt_t *cxt, AV *av)
2457
2478
return ret ;
2458
2479
}
2459
2480
2460
- if (cxt -> entry ) -- cxt -> av_depth ;
2481
+ if (cxt -> entry && cxt -> recur_sv == (SV * )av && cxt -> recur_depth > 0 ) {
2482
+ TRACEME (("recur_depth --%u" , cxt -> recur_depth ));
2483
+ -- cxt -> recur_depth ;
2484
+ }
2461
2485
TRACEME (("ok (array)" ));
2462
2486
2463
2487
return 0 ;
@@ -2570,9 +2594,14 @@ static int store_hash(pTHX_ stcxt_t *cxt, HV *hv)
2570
2594
TRACEME (("size = %d, used = %d" , (int )l , (int )HvUSEDKEYS (hv )));
2571
2595
}
2572
2596
2573
- if (cxt -> entry && ++ cxt -> av_depth > MAX_DEPTH ) {
2574
- CROAK ((MAX_DEPTH_ERROR ));
2597
+ TRACEME (("recur_depth %u, recur_sv (0x%" UVxf ")" , cxt -> recur_depth ,
2598
+ PTR2UV (cxt -> recur_sv )));
2599
+ if (cxt -> entry && cxt -> recur_sv == (SV * )hv ) {
2600
+ if (++ cxt -> recur_depth > (MAX_DEPTH >> 1 )) {
2601
+ CROAK ((MAX_DEPTH_ERROR ));
2602
+ }
2575
2603
}
2604
+ cxt -> recur_sv = (SV * )hv ;
2576
2605
2577
2606
/*
2578
2607
* Save possible iteration state via each() on that table.
@@ -2852,7 +2881,10 @@ static int store_hash(pTHX_ stcxt_t *cxt, HV *hv)
2852
2881
TRACEME (("ok (hash 0x%" UVxf ")" , PTR2UV (hv )));
2853
2882
2854
2883
out :
2855
- if (cxt -> entry ) -- cxt -> hv_depth ;
2884
+ if (cxt -> entry && cxt -> recur_sv == (SV * )hv && cxt -> recur_depth > 0 ) {
2885
+ TRACEME (("recur_depth --%u" , cxt -> recur_depth ));
2886
+ -- cxt -> recur_depth ;
2887
+ }
2856
2888
HvRITER_set (hv , riter ); /* Restore hash iterator state */
2857
2889
HvEITER_set (hv , eiter );
2858
2890
@@ -2971,9 +3003,15 @@ static int store_lhash(pTHX_ stcxt_t *cxt, HV *hv, unsigned char hash_flags)
2971
3003
}
2972
3004
TRACEME (("size = %" UVuf ", used = %" UVuf , len , (UV )HvUSEDKEYS (hv )));
2973
3005
2974
- if (cxt -> entry && ++ cxt -> hv_depth > MAX_DEPTH ) {
2975
- CROAK ((MAX_DEPTH_ERROR ));
3006
+ TRACEME (("recur_depth %u, recur_sv (0x%" UVxf ")" , cxt -> recur_depth ,
3007
+ PTR2UV (cxt -> recur_sv )));
3008
+ if (cxt -> entry && cxt -> recur_sv == (SV * )hv ) {
3009
+ if (++ cxt -> recur_depth > (MAX_DEPTH >> 1 )) {
3010
+ CROAK ((MAX_DEPTH_ERROR ));
3011
+ }
2976
3012
}
3013
+ cxt -> recur_sv = (SV * )hv ;
3014
+
2977
3015
array = HvARRAY (hv );
2978
3016
for (i = 0 ; i <= (Size_t )HvMAX (hv ); i ++ ) {
2979
3017
HE * entry = array [i ];
@@ -2985,7 +3023,10 @@ static int store_lhash(pTHX_ stcxt_t *cxt, HV *hv, unsigned char hash_flags)
2985
3023
return ret ;
2986
3024
}
2987
3025
}
2988
- if (cxt -> entry ) -- cxt -> hv_depth ;
3026
+ if (cxt -> entry && cxt -> recur_sv == (SV * )hv && cxt -> recur_depth > 0 ) {
3027
+ TRACEME (("recur_depth --%u" , cxt -> recur_depth ));
3028
+ -- cxt -> recur_depth ;
3029
+ }
2989
3030
assert (ix == len );
2990
3031
return ret ;
2991
3032
}
@@ -5078,7 +5119,6 @@ static SV *retrieve_tied_array(pTHX_ stcxt_t *cxt, const char *cname)
5078
5119
return (SV * ) 0 ; /* Failed */
5079
5120
5080
5121
sv_upgrade (tv , SVt_PVAV );
5081
- AvREAL_off ((AV * )tv );
5082
5122
sv_magic (tv , sv , 'P' , (char * )NULL , 0 );
5083
5123
SvREFCNT_dec (sv ); /* Undo refcnt inc from sv_magic() */
5084
5124
0 commit comments