3232#define PTR_HEAP_BLOCK_SIZE 64
3333
3434#define SPL_HEAP_CORRUPTED 0x00000001
35+ #define SPL_HEAP_WRITE_LOCKED 0x00000002
3536
3637zend_object_handlers spl_handler_SplHeap ;
3738zend_object_handlers spl_handler_SplPriorityQueue ;
@@ -278,12 +279,16 @@ static void spl_ptr_heap_insert(spl_ptr_heap *heap, void *elem, void *cmp_userda
278279 heap -> max_size *= 2 ;
279280 }
280281
282+ heap -> flags |= SPL_HEAP_WRITE_LOCKED ;
283+
281284 /* sifting up */
282285 for (i = heap -> count ; i > 0 && heap -> cmp (spl_heap_elem (heap , (i - 1 )/2 ), elem , cmp_userdata ) < 0 ; i = (i - 1 )/2 ) {
283286 spl_heap_elem_copy (heap , spl_heap_elem (heap , i ), spl_heap_elem (heap , (i - 1 )/2 ));
284287 }
285288 heap -> count ++ ;
286289
290+ heap -> flags &= ~SPL_HEAP_WRITE_LOCKED ;
291+
287292 if (EG (exception )) {
288293 /* exception thrown during comparison */
289294 heap -> flags |= SPL_HEAP_CORRUPTED ;
@@ -311,6 +316,8 @@ static zend_result spl_ptr_heap_delete_top(spl_ptr_heap *heap, void *elem, void
311316 return FAILURE ;
312317 }
313318
319+ heap -> flags |= SPL_HEAP_WRITE_LOCKED ;
320+
314321 if (elem ) {
315322 spl_heap_elem_copy (heap , elem , spl_heap_elem (heap , 0 ));
316323 } else {
@@ -334,6 +341,8 @@ static zend_result spl_ptr_heap_delete_top(spl_ptr_heap *heap, void *elem, void
334341 }
335342 }
336343
344+ heap -> flags &= ~SPL_HEAP_WRITE_LOCKED ;
345+
337346 if (EG (exception )) {
338347 /* exception thrown during comparison */
339348 heap -> flags |= SPL_HEAP_CORRUPTED ;
@@ -379,10 +388,14 @@ static void spl_ptr_heap_destroy(spl_ptr_heap *heap) { /* {{{ */
379388
380389 int i ;
381390
391+ heap -> flags |= SPL_HEAP_WRITE_LOCKED ;
392+
382393 for (i = 0 ; i < heap -> count ; ++ i ) {
383394 heap -> dtor (spl_heap_elem (heap , i ));
384395 }
385396
397+ heap -> flags &= ~SPL_HEAP_WRITE_LOCKED ;
398+
386399 efree (heap -> elements );
387400 efree (heap );
388401}
@@ -601,6 +614,21 @@ PHP_METHOD(SplHeap, isEmpty)
601614}
602615/* }}} */
603616
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+
604632/* {{{ Push $value on the heap */
605633PHP_METHOD (SplHeap , insert )
606634{
@@ -613,8 +641,7 @@ PHP_METHOD(SplHeap, insert)
613641
614642 intern = Z_SPLHEAP_P (ZEND_THIS );
615643
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 )) {
618645 RETURN_THROWS ();
619646 }
620647
@@ -636,8 +663,7 @@ PHP_METHOD(SplHeap, extract)
636663
637664 intern = Z_SPLHEAP_P (ZEND_THIS );
638665
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 )) {
641667 RETURN_THROWS ();
642668 }
643669
@@ -662,8 +688,7 @@ PHP_METHOD(SplPriorityQueue, insert)
662688
663689 intern = Z_SPLHEAP_P (ZEND_THIS );
664690
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 )) {
667692 RETURN_THROWS ();
668693 }
669694
@@ -703,8 +728,7 @@ PHP_METHOD(SplPriorityQueue, extract)
703728
704729 intern = Z_SPLHEAP_P (ZEND_THIS );
705730
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 )) {
708732 RETURN_THROWS ();
709733 }
710734
@@ -730,8 +754,7 @@ PHP_METHOD(SplPriorityQueue, top)
730754
731755 intern = Z_SPLHEAP_P (ZEND_THIS );
732756
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 )) {
735758 RETURN_THROWS ();
736759 }
737760
@@ -841,8 +864,7 @@ PHP_METHOD(SplHeap, top)
841864
842865 intern = Z_SPLHEAP_P (ZEND_THIS );
843866
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 )) {
846868 RETURN_THROWS ();
847869 }
848870
@@ -906,8 +928,7 @@ static zval *spl_heap_it_get_current_data(zend_object_iterator *iter) /* {{{ */
906928{
907929 spl_heap_object * object = Z_SPLHEAP_P (& iter -> data );
908930
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 )) {
911932 return NULL ;
912933 }
913934
@@ -924,8 +945,7 @@ static zval *spl_pqueue_it_get_current_data(zend_object_iterator *iter) /* {{{ *
924945 zend_user_iterator * user_it = (zend_user_iterator * ) iter ;
925946 spl_heap_object * object = Z_SPLHEAP_P (& iter -> data );
926947
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 )) {
929949 return NULL ;
930950 }
931951
@@ -953,8 +973,7 @@ static void spl_heap_it_move_forward(zend_object_iterator *iter) /* {{{ */
953973{
954974 spl_heap_object * object = Z_SPLHEAP_P (& iter -> data );
955975
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 )) {
958977 return ;
959978 }
960979
0 commit comments