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 int spl_ptr_heap_delete_top(spl_ptr_heap *heap, void *elem, void *cmp_use
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 int spl_ptr_heap_delete_top(spl_ptr_heap *heap, void *elem, void *cmp_use
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 ;
@@ -374,10 +383,14 @@ static spl_ptr_heap *spl_ptr_heap_clone(spl_ptr_heap *from) { /* {{{ */
374
383
static void spl_ptr_heap_destroy (spl_ptr_heap * heap ) { /* {{{ */
375
384
int i ;
376
385
386
+ heap -> flags |= SPL_HEAP_WRITE_LOCKED ;
387
+
377
388
for (i = 0 ; i < heap -> count ; ++ i ) {
378
389
heap -> dtor (spl_heap_elem (heap , i ));
379
390
}
380
391
392
+ heap -> flags &= ~SPL_HEAP_WRITE_LOCKED ;
393
+
381
394
efree (heap -> elements );
382
395
efree (heap );
383
396
}
@@ -597,6 +610,21 @@ PHP_METHOD(SplHeap, isEmpty)
597
610
}
598
611
/* }}} */
599
612
613
+ static zend_result spl_heap_consistency_validations (const spl_heap_object * intern , bool write )
614
+ {
615
+ if (intern -> heap -> flags & SPL_HEAP_CORRUPTED ) {
616
+ zend_throw_exception (spl_ce_RuntimeException , "Heap is corrupted, heap properties are no longer ensured." , 0 );
617
+ return FAILURE ;
618
+ }
619
+
620
+ if (write && (intern -> heap -> flags & SPL_HEAP_WRITE_LOCKED )) {
621
+ zend_throw_exception (spl_ce_RuntimeException , "Heap cannot be changed when it is already being modified." , 0 );
622
+ return FAILURE ;
623
+ }
624
+
625
+ return SUCCESS ;
626
+ }
627
+
600
628
/* {{{ Push $value on the heap */
601
629
PHP_METHOD (SplHeap , insert )
602
630
{
@@ -609,8 +637,7 @@ PHP_METHOD(SplHeap, insert)
609
637
610
638
intern = Z_SPLHEAP_P (ZEND_THIS );
611
639
612
- if (intern -> heap -> flags & SPL_HEAP_CORRUPTED ) {
613
- zend_throw_exception (spl_ce_RuntimeException , "Heap is corrupted, heap properties are no longer ensured." , 0 );
640
+ if (UNEXPECTED (spl_heap_consistency_validations (intern , true) != SUCCESS )) {
614
641
RETURN_THROWS ();
615
642
}
616
643
@@ -632,8 +659,7 @@ PHP_METHOD(SplHeap, extract)
632
659
633
660
intern = Z_SPLHEAP_P (ZEND_THIS );
634
661
635
- if (intern -> heap -> flags & SPL_HEAP_CORRUPTED ) {
636
- zend_throw_exception (spl_ce_RuntimeException , "Heap is corrupted, heap properties are no longer ensured." , 0 );
662
+ if (UNEXPECTED (spl_heap_consistency_validations (intern , true) != SUCCESS )) {
637
663
RETURN_THROWS ();
638
664
}
639
665
@@ -658,8 +684,7 @@ PHP_METHOD(SplPriorityQueue, insert)
658
684
659
685
intern = Z_SPLHEAP_P (ZEND_THIS );
660
686
661
- if (intern -> heap -> flags & SPL_HEAP_CORRUPTED ) {
662
- zend_throw_exception (spl_ce_RuntimeException , "Heap is corrupted, heap properties are no longer ensured." , 0 );
687
+ if (UNEXPECTED (spl_heap_consistency_validations (intern , true) != SUCCESS )) {
663
688
RETURN_THROWS ();
664
689
}
665
690
@@ -699,8 +724,7 @@ PHP_METHOD(SplPriorityQueue, extract)
699
724
700
725
intern = Z_SPLHEAP_P (ZEND_THIS );
701
726
702
- if (intern -> heap -> flags & SPL_HEAP_CORRUPTED ) {
703
- zend_throw_exception (spl_ce_RuntimeException , "Heap is corrupted, heap properties are no longer ensured." , 0 );
727
+ if (UNEXPECTED (spl_heap_consistency_validations (intern , true) != SUCCESS )) {
704
728
RETURN_THROWS ();
705
729
}
706
730
@@ -726,8 +750,7 @@ PHP_METHOD(SplPriorityQueue, top)
726
750
727
751
intern = Z_SPLHEAP_P (ZEND_THIS );
728
752
729
- if (intern -> heap -> flags & SPL_HEAP_CORRUPTED ) {
730
- zend_throw_exception (spl_ce_RuntimeException , "Heap is corrupted, heap properties are no longer ensured." , 0 );
753
+ if (UNEXPECTED (spl_heap_consistency_validations (intern , false) != SUCCESS )) {
731
754
RETURN_THROWS ();
732
755
}
733
756
@@ -837,8 +860,7 @@ PHP_METHOD(SplHeap, top)
837
860
838
861
intern = Z_SPLHEAP_P (ZEND_THIS );
839
862
840
- if (intern -> heap -> flags & SPL_HEAP_CORRUPTED ) {
841
- zend_throw_exception (spl_ce_RuntimeException , "Heap is corrupted, heap properties are no longer ensured." , 0 );
863
+ if (UNEXPECTED (spl_heap_consistency_validations (intern , false) != SUCCESS )) {
842
864
RETURN_THROWS ();
843
865
}
844
866
@@ -902,8 +924,7 @@ static zval *spl_heap_it_get_current_data(zend_object_iterator *iter) /* {{{ */
902
924
{
903
925
spl_heap_object * object = Z_SPLHEAP_P (& iter -> data );
904
926
905
- if (object -> heap -> flags & SPL_HEAP_CORRUPTED ) {
906
- zend_throw_exception (spl_ce_RuntimeException , "Heap is corrupted, heap properties are no longer ensured." , 0 );
927
+ if (UNEXPECTED (spl_heap_consistency_validations (object , false) != SUCCESS )) {
907
928
return NULL ;
908
929
}
909
930
@@ -920,8 +941,7 @@ static zval *spl_pqueue_it_get_current_data(zend_object_iterator *iter) /* {{{ *
920
941
zend_user_iterator * user_it = (zend_user_iterator * ) iter ;
921
942
spl_heap_object * object = Z_SPLHEAP_P (& iter -> data );
922
943
923
- if (object -> heap -> flags & SPL_HEAP_CORRUPTED ) {
924
- zend_throw_exception (spl_ce_RuntimeException , "Heap is corrupted, heap properties are no longer ensured." , 0 );
944
+ if (UNEXPECTED (spl_heap_consistency_validations (object , false) != SUCCESS )) {
925
945
return NULL ;
926
946
}
927
947
@@ -949,8 +969,7 @@ static void spl_heap_it_move_forward(zend_object_iterator *iter) /* {{{ */
949
969
{
950
970
spl_heap_object * object = Z_SPLHEAP_P (& iter -> data );
951
971
952
- if (object -> heap -> flags & SPL_HEAP_CORRUPTED ) {
953
- zend_throw_exception (spl_ce_RuntimeException , "Heap is corrupted, heap properties are no longer ensured." , 0 );
972
+ if (UNEXPECTED (spl_heap_consistency_validations (object , false) != SUCCESS )) {
954
973
return ;
955
974
}
956
975
0 commit comments