1717class VarCloner extends AbstractCloner
1818{
1919 private static $ gid ;
20- private static $ hashMask = 0 ;
21- private static $ hashOffset = 0 ;
2220 private static $ arrayCache = array ();
2321
2422 /**
@@ -31,10 +29,10 @@ protected function doClone($var)
3129 $ refsCounter = 0 ; // Hard references counter
3230 $ queue = array (array ($ var )); // This breadth-first queue is the return value
3331 $ indexedArrays = array (); // Map of queue indexes that hold numerically indexed arrays
34- $ hardRefs = array (); // Map of original zval hashes to stub objects
32+ $ hardRefs = array (); // Map of original zval ids to stub objects
3533 $ objRefs = array (); // Map of original object handles to their stub object couterpart
3634 $ resRefs = array (); // Map of original resource handles to their stub object couterpart
37- $ values = array (); // Map of stub objects' hashes to original values
35+ $ values = array (); // Map of stub objects' ids to original values
3836 $ maxItems = $ this ->maxItems ;
3937 $ maxString = $ this ->maxString ;
4038 $ minDepth = $ this ->minDepth ;
@@ -46,13 +44,9 @@ protected function doClone($var)
4644 $ stub = null ; // Stub capturing the main properties of an original item value
4745 // or null if the original value is used directly
4846
49- if (!self ::$ hashMask ) {
50- self ::$ gid = uniqid (mt_rand (), true ); // Unique string used to detect the special $GLOBALS variable
51- self ::initHashMask ();
47+ if (!$ gid = self ::$ gid ) {
48+ $ gid = self ::$ gid = uniqid (mt_rand (), true ); // Unique string used to detect the special $GLOBALS variable
5249 }
53- $ gid = self ::$ gid ;
54- $ hashMask = self ::$ hashMask ;
55- $ hashOffset = self ::$ hashOffset ;
5650 $ arrayStub = new Stub ();
5751 $ arrayStub ->type = Stub::TYPE_ARRAY ;
5852 $ fromObjCast = false ;
@@ -89,7 +83,7 @@ protected function doClone($var)
8983 if ($ zvalIsRef = $ vals [$ k ] === $ cookie ) {
9084 $ vals [$ k ] = &$ stub ; // Break hard references to make $queue completely
9185 unset($ stub ); // independent from the original structure
92- if ($ v instanceof Stub && isset ($ hardRefs [\spl_object_hash ($ v )])) {
86+ if ($ v instanceof Stub && isset ($ hardRefs [\spl_object_id ($ v )])) {
9387 $ vals [$ k ] = $ refs [$ k ] = $ v ;
9488 if ($ v ->value instanceof Stub && (Stub::TYPE_OBJECT === $ v ->value ->type || Stub::TYPE_RESOURCE === $ v ->value ->type )) {
9589 ++$ v ->value ->refCount ;
@@ -99,7 +93,7 @@ protected function doClone($var)
9993 }
10094 $ refs [$ k ] = $ vals [$ k ] = new Stub ();
10195 $ refs [$ k ]->value = $ v ;
102- $ h = \spl_object_hash ($ refs [$ k ]);
96+ $ h = \spl_object_id ($ refs [$ k ]);
10397 $ hardRefs [$ h ] = &$ refs [$ k ];
10498 $ values [$ h ] = $ v ;
10599 $ vals [$ k ]->handle = ++$ refsCounter ;
@@ -172,7 +166,7 @@ protected function doClone($var)
172166
173167 case \is_object ($ v ):
174168 case $ v instanceof \__PHP_Incomplete_Class:
175- if (empty ($ objRefs [$ h = $ hashMask ^ \hexdec ( \substr ( \spl_object_hash ( $ v ), $ hashOffset , \ PHP_INT_SIZE ) )])) {
169+ if (empty ($ objRefs [$ h = \spl_object_id ( $ v )])) {
176170 $ stub = new Stub ();
177171 $ stub ->type = Stub::TYPE_OBJECT ;
178172 $ stub ->class = \get_class ($ v );
@@ -183,8 +177,7 @@ protected function doClone($var)
183177 if (Stub::TYPE_OBJECT !== $ stub ->type || null === $ stub ->value ) {
184178 break ;
185179 }
186- $ h = $ hashMask ^ \hexdec (\substr (\spl_object_hash ($ stub ->value ), $ hashOffset , \PHP_INT_SIZE ));
187- $ stub ->handle = $ h ;
180+ $ stub ->handle = $ h = \spl_object_id ($ stub ->value );
188181 }
189182 $ stub ->value = null ;
190183 if (0 <= $ maxItems && $ maxItems <= $ pos && $ minimumDepthReached ) {
@@ -291,27 +284,4 @@ protected function doClone($var)
291284
292285 return $ queue ;
293286 }
294-
295- private static function initHashMask ()
296- {
297- $ obj = (object ) array ();
298- self ::$ hashOffset = 16 - PHP_INT_SIZE ;
299- self ::$ hashMask = -1 ;
300-
301- // check if we are nested in an output buffering handler to prevent a fatal error with ob_start() below
302- $ obFuncs = array ('ob_clean ' , 'ob_end_clean ' , 'ob_flush ' , 'ob_end_flush ' , 'ob_get_contents ' , 'ob_get_flush ' );
303- foreach (debug_backtrace (DEBUG_BACKTRACE_IGNORE_ARGS ) as $ frame ) {
304- if (isset ($ frame ['function ' ][0 ]) && !isset ($ frame ['class ' ]) && 'o ' === $ frame ['function ' ][0 ] && in_array ($ frame ['function ' ], $ obFuncs )) {
305- $ frame ['line ' ] = 0 ;
306- break ;
307- }
308- }
309- if (!empty ($ frame ['line ' ])) {
310- ob_start ();
311- debug_zval_dump ($ obj );
312- self ::$ hashMask = (int ) substr (ob_get_clean (), 17 );
313- }
314-
315- self ::$ hashMask ^= hexdec (substr (spl_object_hash ($ obj ), self ::$ hashOffset , PHP_INT_SIZE ));
316- }
317287}
0 commit comments