3030#define PTR_HEAP_BLOCK_SIZE 64
3131
3232#define SPL_HEAP_CORRUPTED 0x00000001
33+ #define SPL_HEAP_WRITE_LOCKED 0x00000002
3334
3435static zend_object_handlers spl_handler_SplHeap ;
3536static zend_object_handlers spl_handler_SplPriorityQueue ;
@@ -276,12 +277,16 @@ static void spl_ptr_heap_insert(spl_ptr_heap *heap, void *elem, void *cmp_userda
276277 heap -> max_size *= 2 ;
277278 }
278279
280+ heap -> flags |= SPL_HEAP_WRITE_LOCKED ;
281+
279282 /* sifting up */
280283 for (i = heap -> count ; i > 0 && heap -> cmp (spl_heap_elem (heap , (i - 1 )/2 ), elem , cmp_userdata ) < 0 ; i = (i - 1 )/2 ) {
281284 spl_heap_elem_copy (heap , spl_heap_elem (heap , i ), spl_heap_elem (heap , (i - 1 )/2 ));
282285 }
283286 heap -> count ++ ;
284287
288+ heap -> flags &= ~SPL_HEAP_WRITE_LOCKED ;
289+
285290 if (EG (exception )) {
286291 /* exception thrown during comparison */
287292 heap -> flags |= SPL_HEAP_CORRUPTED ;
@@ -309,6 +314,8 @@ static zend_result spl_ptr_heap_delete_top(spl_ptr_heap *heap, void *elem, void
309314 return FAILURE ;
310315 }
311316
317+ heap -> flags |= SPL_HEAP_WRITE_LOCKED ;
318+
312319 if (elem ) {
313320 spl_heap_elem_copy (heap , elem , spl_heap_elem (heap , 0 ));
314321 } else {
@@ -332,6 +339,8 @@ static zend_result spl_ptr_heap_delete_top(spl_ptr_heap *heap, void *elem, void
332339 }
333340 }
334341
342+ heap -> flags &= ~SPL_HEAP_WRITE_LOCKED ;
343+
335344 if (EG (exception )) {
336345 /* exception thrown during comparison */
337346 heap -> flags |= SPL_HEAP_CORRUPTED ;
@@ -377,10 +386,14 @@ static void spl_ptr_heap_destroy(spl_ptr_heap *heap) { /* {{{ */
377386
378387 int i ;
379388
389+ heap -> flags |= SPL_HEAP_WRITE_LOCKED ;
390+
380391 for (i = 0 ; i < heap -> count ; ++ i ) {
381392 heap -> dtor (spl_heap_elem (heap , i ));
382393 }
383394
395+ heap -> flags &= ~SPL_HEAP_WRITE_LOCKED ;
396+
384397 efree (heap -> elements );
385398 efree (heap );
386399}
@@ -589,6 +602,21 @@ PHP_METHOD(SplHeap, isEmpty)
589602}
590603/* }}} */
591604
605+ static zend_result spl_heap_consistency_validations (const spl_heap_object * intern , bool write )
606+ {
607+ if (intern -> heap -> flags & SPL_HEAP_CORRUPTED ) {
608+ zend_throw_exception (spl_ce_RuntimeException , "Heap is corrupted, heap properties are no longer ensured." , 0 );
609+ return FAILURE ;
610+ }
611+
612+ if (write && (intern -> heap -> flags & SPL_HEAP_WRITE_LOCKED )) {
613+ zend_throw_exception (spl_ce_RuntimeException , "Heap cannot be changed when it is already being modified." , 0 );
614+ return FAILURE ;
615+ }
616+
617+ return SUCCESS ;
618+ }
619+
592620/* {{{ Push $value on the heap */
593621PHP_METHOD (SplHeap , insert )
594622{
@@ -601,8 +629,7 @@ PHP_METHOD(SplHeap, insert)
601629
602630 intern = Z_SPLHEAP_P (ZEND_THIS );
603631
604- if (intern -> heap -> flags & SPL_HEAP_CORRUPTED ) {
605- zend_throw_exception (spl_ce_RuntimeException , "Heap is corrupted, heap properties are no longer ensured." , 0 );
632+ if (UNEXPECTED (spl_heap_consistency_validations (intern , true) != SUCCESS )) {
606633 RETURN_THROWS ();
607634 }
608635
@@ -624,8 +651,7 @@ PHP_METHOD(SplHeap, extract)
624651
625652 intern = Z_SPLHEAP_P (ZEND_THIS );
626653
627- if (intern -> heap -> flags & SPL_HEAP_CORRUPTED ) {
628- zend_throw_exception (spl_ce_RuntimeException , "Heap is corrupted, heap properties are no longer ensured." , 0 );
654+ if (UNEXPECTED (spl_heap_consistency_validations (intern , true) != SUCCESS )) {
629655 RETURN_THROWS ();
630656 }
631657
@@ -650,8 +676,7 @@ PHP_METHOD(SplPriorityQueue, insert)
650676
651677 intern = Z_SPLHEAP_P (ZEND_THIS );
652678
653- if (intern -> heap -> flags & SPL_HEAP_CORRUPTED ) {
654- zend_throw_exception (spl_ce_RuntimeException , "Heap is corrupted, heap properties are no longer ensured." , 0 );
679+ if (UNEXPECTED (spl_heap_consistency_validations (intern , true) != SUCCESS )) {
655680 RETURN_THROWS ();
656681 }
657682
@@ -691,8 +716,7 @@ PHP_METHOD(SplPriorityQueue, extract)
691716
692717 intern = Z_SPLHEAP_P (ZEND_THIS );
693718
694- if (intern -> heap -> flags & SPL_HEAP_CORRUPTED ) {
695- zend_throw_exception (spl_ce_RuntimeException , "Heap is corrupted, heap properties are no longer ensured." , 0 );
719+ if (UNEXPECTED (spl_heap_consistency_validations (intern , true) != SUCCESS )) {
696720 RETURN_THROWS ();
697721 }
698722
@@ -718,8 +742,7 @@ PHP_METHOD(SplPriorityQueue, top)
718742
719743 intern = Z_SPLHEAP_P (ZEND_THIS );
720744
721- if (intern -> heap -> flags & SPL_HEAP_CORRUPTED ) {
722- zend_throw_exception (spl_ce_RuntimeException , "Heap is corrupted, heap properties are no longer ensured." , 0 );
745+ if (UNEXPECTED (spl_heap_consistency_validations (intern , false) != SUCCESS )) {
723746 RETURN_THROWS ();
724747 }
725748
@@ -829,8 +852,7 @@ PHP_METHOD(SplHeap, top)
829852
830853 intern = Z_SPLHEAP_P (ZEND_THIS );
831854
832- if (intern -> heap -> flags & SPL_HEAP_CORRUPTED ) {
833- zend_throw_exception (spl_ce_RuntimeException , "Heap is corrupted, heap properties are no longer ensured." , 0 );
855+ if (UNEXPECTED (spl_heap_consistency_validations (intern , false) != SUCCESS )) {
834856 RETURN_THROWS ();
835857 }
836858
@@ -894,8 +916,7 @@ static zval *spl_heap_it_get_current_data(zend_object_iterator *iter) /* {{{ */
894916{
895917 spl_heap_object * object = Z_SPLHEAP_P (& iter -> data );
896918
897- if (object -> heap -> flags & SPL_HEAP_CORRUPTED ) {
898- zend_throw_exception (spl_ce_RuntimeException , "Heap is corrupted, heap properties are no longer ensured." , 0 );
919+ if (UNEXPECTED (spl_heap_consistency_validations (object , false) != SUCCESS )) {
899920 return NULL ;
900921 }
901922
@@ -912,8 +933,7 @@ static zval *spl_pqueue_it_get_current_data(zend_object_iterator *iter) /* {{{ *
912933 zend_user_iterator * user_it = (zend_user_iterator * ) iter ;
913934 spl_heap_object * object = Z_SPLHEAP_P (& iter -> data );
914935
915- if (object -> heap -> flags & SPL_HEAP_CORRUPTED ) {
916- zend_throw_exception (spl_ce_RuntimeException , "Heap is corrupted, heap properties are no longer ensured." , 0 );
936+ if (UNEXPECTED (spl_heap_consistency_validations (object , false) != SUCCESS )) {
917937 return NULL ;
918938 }
919939
@@ -941,8 +961,7 @@ static void spl_heap_it_move_forward(zend_object_iterator *iter) /* {{{ */
941961{
942962 spl_heap_object * object = Z_SPLHEAP_P (& iter -> data );
943963
944- if (object -> heap -> flags & SPL_HEAP_CORRUPTED ) {
945- zend_throw_exception (spl_ce_RuntimeException , "Heap is corrupted, heap properties are no longer ensured." , 0 );
964+ if (UNEXPECTED (spl_heap_consistency_validations (object , false) != SUCCESS )) {
946965 return ;
947966 }
948967
0 commit comments