32
32
#define PTR_HEAP_BLOCK_SIZE 64
33
33
34
34
#define SPL_HEAP_CORRUPTED 0x00000001
35
+ #define SPL_HEAP_WRITE_LOCKED 0x00000002
35
36
36
37
zend_object_handlers spl_handler_SplHeap ;
37
38
zend_object_handlers spl_handler_SplPriorityQueue ;
@@ -278,12 +279,16 @@ static void spl_ptr_heap_insert(spl_ptr_heap *heap, void *elem, void *cmp_userda
278
279
heap -> max_size *= 2 ;
279
280
}
280
281
282
+ heap -> flags |= SPL_HEAP_WRITE_LOCKED ;
283
+
281
284
/* sifting up */
282
285
for (i = heap -> count ; i > 0 && heap -> cmp (spl_heap_elem (heap , (i - 1 )/2 ), elem , cmp_userdata ) < 0 ; i = (i - 1 )/2 ) {
283
286
spl_heap_elem_copy (heap , spl_heap_elem (heap , i ), spl_heap_elem (heap , (i - 1 )/2 ));
284
287
}
285
288
heap -> count ++ ;
286
289
290
+ heap -> flags &= ~SPL_HEAP_WRITE_LOCKED ;
291
+
287
292
if (EG (exception )) {
288
293
/* exception thrown during comparison */
289
294
heap -> flags |= SPL_HEAP_CORRUPTED ;
@@ -311,6 +316,8 @@ static zend_result spl_ptr_heap_delete_top(spl_ptr_heap *heap, void *elem, void
311
316
return FAILURE ;
312
317
}
313
318
319
+ heap -> flags |= SPL_HEAP_WRITE_LOCKED ;
320
+
314
321
if (elem ) {
315
322
spl_heap_elem_copy (heap , elem , spl_heap_elem (heap , 0 ));
316
323
} else {
@@ -334,6 +341,8 @@ static zend_result spl_ptr_heap_delete_top(spl_ptr_heap *heap, void *elem, void
334
341
}
335
342
}
336
343
344
+ heap -> flags &= ~SPL_HEAP_WRITE_LOCKED ;
345
+
337
346
if (EG (exception )) {
338
347
/* exception thrown during comparison */
339
348
heap -> flags |= SPL_HEAP_CORRUPTED ;
@@ -379,10 +388,14 @@ static void spl_ptr_heap_destroy(spl_ptr_heap *heap) { /* {{{ */
379
388
380
389
int i ;
381
390
391
+ heap -> flags |= SPL_HEAP_WRITE_LOCKED ;
392
+
382
393
for (i = 0 ; i < heap -> count ; ++ i ) {
383
394
heap -> dtor (spl_heap_elem (heap , i ));
384
395
}
385
396
397
+ heap -> flags &= ~SPL_HEAP_WRITE_LOCKED ;
398
+
386
399
efree (heap -> elements );
387
400
efree (heap );
388
401
}
@@ -601,6 +614,21 @@ PHP_METHOD(SplHeap, isEmpty)
601
614
}
602
615
/* }}} */
603
616
617
+ static zend_result spl_heap_consistency_validations (const spl_heap_object * intern , bool write )
618
+ {
619
+ if (intern -> heap -> flags & SPL_HEAP_CORRUPTED ) {
620
+ zend_throw_exception (spl_ce_RuntimeException , "Heap is corrupted, heap properties are no longer ensured." , 0 );
621
+ return FAILURE ;
622
+ }
623
+
624
+ if (write && (intern -> heap -> flags & SPL_HEAP_WRITE_LOCKED )) {
625
+ zend_throw_exception (spl_ce_RuntimeException , "Heap cannot be changed when it is already being modified." , 0 );
626
+ return FAILURE ;
627
+ }
628
+
629
+ return SUCCESS ;
630
+ }
631
+
604
632
/* {{{ Push $value on the heap */
605
633
PHP_METHOD (SplHeap , insert )
606
634
{
@@ -613,8 +641,7 @@ PHP_METHOD(SplHeap, insert)
613
641
614
642
intern = Z_SPLHEAP_P (ZEND_THIS );
615
643
616
- if (intern -> heap -> flags & SPL_HEAP_CORRUPTED ) {
617
- zend_throw_exception (spl_ce_RuntimeException , "Heap is corrupted, heap properties are no longer ensured." , 0 );
644
+ if (UNEXPECTED (spl_heap_consistency_validations (intern , true) != SUCCESS )) {
618
645
RETURN_THROWS ();
619
646
}
620
647
@@ -636,8 +663,7 @@ PHP_METHOD(SplHeap, extract)
636
663
637
664
intern = Z_SPLHEAP_P (ZEND_THIS );
638
665
639
- if (intern -> heap -> flags & SPL_HEAP_CORRUPTED ) {
640
- zend_throw_exception (spl_ce_RuntimeException , "Heap is corrupted, heap properties are no longer ensured." , 0 );
666
+ if (UNEXPECTED (spl_heap_consistency_validations (intern , true) != SUCCESS )) {
641
667
RETURN_THROWS ();
642
668
}
643
669
@@ -662,8 +688,7 @@ PHP_METHOD(SplPriorityQueue, insert)
662
688
663
689
intern = Z_SPLHEAP_P (ZEND_THIS );
664
690
665
- if (intern -> heap -> flags & SPL_HEAP_CORRUPTED ) {
666
- zend_throw_exception (spl_ce_RuntimeException , "Heap is corrupted, heap properties are no longer ensured." , 0 );
691
+ if (UNEXPECTED (spl_heap_consistency_validations (intern , true) != SUCCESS )) {
667
692
RETURN_THROWS ();
668
693
}
669
694
@@ -703,8 +728,7 @@ PHP_METHOD(SplPriorityQueue, extract)
703
728
704
729
intern = Z_SPLHEAP_P (ZEND_THIS );
705
730
706
- if (intern -> heap -> flags & SPL_HEAP_CORRUPTED ) {
707
- zend_throw_exception (spl_ce_RuntimeException , "Heap is corrupted, heap properties are no longer ensured." , 0 );
731
+ if (UNEXPECTED (spl_heap_consistency_validations (intern , true) != SUCCESS )) {
708
732
RETURN_THROWS ();
709
733
}
710
734
@@ -730,8 +754,7 @@ PHP_METHOD(SplPriorityQueue, top)
730
754
731
755
intern = Z_SPLHEAP_P (ZEND_THIS );
732
756
733
- if (intern -> heap -> flags & SPL_HEAP_CORRUPTED ) {
734
- zend_throw_exception (spl_ce_RuntimeException , "Heap is corrupted, heap properties are no longer ensured." , 0 );
757
+ if (UNEXPECTED (spl_heap_consistency_validations (intern , false) != SUCCESS )) {
735
758
RETURN_THROWS ();
736
759
}
737
760
@@ -841,8 +864,7 @@ PHP_METHOD(SplHeap, top)
841
864
842
865
intern = Z_SPLHEAP_P (ZEND_THIS );
843
866
844
- if (intern -> heap -> flags & SPL_HEAP_CORRUPTED ) {
845
- zend_throw_exception (spl_ce_RuntimeException , "Heap is corrupted, heap properties are no longer ensured." , 0 );
867
+ if (UNEXPECTED (spl_heap_consistency_validations (intern , false) != SUCCESS )) {
846
868
RETURN_THROWS ();
847
869
}
848
870
@@ -906,8 +928,7 @@ static zval *spl_heap_it_get_current_data(zend_object_iterator *iter) /* {{{ */
906
928
{
907
929
spl_heap_object * object = Z_SPLHEAP_P (& iter -> data );
908
930
909
- if (object -> heap -> flags & SPL_HEAP_CORRUPTED ) {
910
- zend_throw_exception (spl_ce_RuntimeException , "Heap is corrupted, heap properties are no longer ensured." , 0 );
931
+ if (UNEXPECTED (spl_heap_consistency_validations (object , false) != SUCCESS )) {
911
932
return NULL ;
912
933
}
913
934
@@ -924,8 +945,7 @@ static zval *spl_pqueue_it_get_current_data(zend_object_iterator *iter) /* {{{ *
924
945
zend_user_iterator * user_it = (zend_user_iterator * ) iter ;
925
946
spl_heap_object * object = Z_SPLHEAP_P (& iter -> data );
926
947
927
- if (object -> heap -> flags & SPL_HEAP_CORRUPTED ) {
928
- zend_throw_exception (spl_ce_RuntimeException , "Heap is corrupted, heap properties are no longer ensured." , 0 );
948
+ if (UNEXPECTED (spl_heap_consistency_validations (object , false) != SUCCESS )) {
929
949
return NULL ;
930
950
}
931
951
@@ -953,8 +973,7 @@ static void spl_heap_it_move_forward(zend_object_iterator *iter) /* {{{ */
953
973
{
954
974
spl_heap_object * object = Z_SPLHEAP_P (& iter -> data );
955
975
956
- if (object -> heap -> flags & SPL_HEAP_CORRUPTED ) {
957
- zend_throw_exception (spl_ce_RuntimeException , "Heap is corrupted, heap properties are no longer ensured." , 0 );
976
+ if (UNEXPECTED (spl_heap_consistency_validations (object , false) != SUCCESS )) {
958
977
return ;
959
978
}
960
979
0 commit comments