30
30
#define PTR_HEAP_BLOCK_SIZE 64
31
31
32
32
#define SPL_HEAP_CORRUPTED 0x00000001
33
+ #define SPL_HEAP_WRITE_LOCKED 0x00000002
33
34
34
35
static zend_object_handlers spl_handler_SplHeap ;
35
36
static 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
276
277
heap -> max_size *= 2 ;
277
278
}
278
279
280
+ heap -> flags |= SPL_HEAP_WRITE_LOCKED ;
281
+
279
282
/* sifting up */
280
283
for (i = heap -> count ; i > 0 && heap -> cmp (spl_heap_elem (heap , (i - 1 )/2 ), elem , cmp_userdata ) < 0 ; i = (i - 1 )/2 ) {
281
284
spl_heap_elem_copy (heap , spl_heap_elem (heap , i ), spl_heap_elem (heap , (i - 1 )/2 ));
282
285
}
283
286
heap -> count ++ ;
284
287
288
+ heap -> flags &= ~SPL_HEAP_WRITE_LOCKED ;
289
+
285
290
if (EG (exception )) {
286
291
/* exception thrown during comparison */
287
292
heap -> flags |= SPL_HEAP_CORRUPTED ;
@@ -309,6 +314,8 @@ static zend_result spl_ptr_heap_delete_top(spl_ptr_heap *heap, void *elem, void
309
314
return FAILURE ;
310
315
}
311
316
317
+ heap -> flags |= SPL_HEAP_WRITE_LOCKED ;
318
+
312
319
if (elem ) {
313
320
spl_heap_elem_copy (heap , elem , spl_heap_elem (heap , 0 ));
314
321
} else {
@@ -332,6 +339,8 @@ static zend_result spl_ptr_heap_delete_top(spl_ptr_heap *heap, void *elem, void
332
339
}
333
340
}
334
341
342
+ heap -> flags &= ~SPL_HEAP_WRITE_LOCKED ;
343
+
335
344
if (EG (exception )) {
336
345
/* exception thrown during comparison */
337
346
heap -> flags |= SPL_HEAP_CORRUPTED ;
@@ -377,10 +386,14 @@ static void spl_ptr_heap_destroy(spl_ptr_heap *heap) { /* {{{ */
377
386
378
387
int i ;
379
388
389
+ heap -> flags |= SPL_HEAP_WRITE_LOCKED ;
390
+
380
391
for (i = 0 ; i < heap -> count ; ++ i ) {
381
392
heap -> dtor (spl_heap_elem (heap , i ));
382
393
}
383
394
395
+ heap -> flags &= ~SPL_HEAP_WRITE_LOCKED ;
396
+
384
397
efree (heap -> elements );
385
398
efree (heap );
386
399
}
@@ -589,6 +602,21 @@ PHP_METHOD(SplHeap, isEmpty)
589
602
}
590
603
/* }}} */
591
604
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
+
592
620
/* {{{ Push $value on the heap */
593
621
PHP_METHOD (SplHeap , insert )
594
622
{
@@ -601,8 +629,7 @@ PHP_METHOD(SplHeap, insert)
601
629
602
630
intern = Z_SPLHEAP_P (ZEND_THIS );
603
631
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 )) {
606
633
RETURN_THROWS ();
607
634
}
608
635
@@ -624,8 +651,7 @@ PHP_METHOD(SplHeap, extract)
624
651
625
652
intern = Z_SPLHEAP_P (ZEND_THIS );
626
653
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 )) {
629
655
RETURN_THROWS ();
630
656
}
631
657
@@ -650,8 +676,7 @@ PHP_METHOD(SplPriorityQueue, insert)
650
676
651
677
intern = Z_SPLHEAP_P (ZEND_THIS );
652
678
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 )) {
655
680
RETURN_THROWS ();
656
681
}
657
682
@@ -691,8 +716,7 @@ PHP_METHOD(SplPriorityQueue, extract)
691
716
692
717
intern = Z_SPLHEAP_P (ZEND_THIS );
693
718
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 )) {
696
720
RETURN_THROWS ();
697
721
}
698
722
@@ -718,8 +742,7 @@ PHP_METHOD(SplPriorityQueue, top)
718
742
719
743
intern = Z_SPLHEAP_P (ZEND_THIS );
720
744
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 )) {
723
746
RETURN_THROWS ();
724
747
}
725
748
@@ -829,8 +852,7 @@ PHP_METHOD(SplHeap, top)
829
852
830
853
intern = Z_SPLHEAP_P (ZEND_THIS );
831
854
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 )) {
834
856
RETURN_THROWS ();
835
857
}
836
858
@@ -894,8 +916,7 @@ static zval *spl_heap_it_get_current_data(zend_object_iterator *iter) /* {{{ */
894
916
{
895
917
spl_heap_object * object = Z_SPLHEAP_P (& iter -> data );
896
918
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 )) {
899
920
return NULL ;
900
921
}
901
922
@@ -912,8 +933,7 @@ static zval *spl_pqueue_it_get_current_data(zend_object_iterator *iter) /* {{{ *
912
933
zend_user_iterator * user_it = (zend_user_iterator * ) iter ;
913
934
spl_heap_object * object = Z_SPLHEAP_P (& iter -> data );
914
935
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 )) {
917
937
return NULL ;
918
938
}
919
939
@@ -941,8 +961,7 @@ static void spl_heap_it_move_forward(zend_object_iterator *iter) /* {{{ */
941
961
{
942
962
spl_heap_object * object = Z_SPLHEAP_P (& iter -> data );
943
963
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 )) {
946
965
return ;
947
966
}
948
967
0 commit comments