@@ -641,28 +641,110 @@ static bool has_opline(zend_execute_data *execute_data)
641
641
;
642
642
}
643
643
644
+ // When a custom memory manager is installed, ZendMM alters its behaviour. For
645
+ // example `zend_mm_gc()` will not do anything anymore, or `zend_mm_shutdown()`
646
+ // won't cleanup chunks and leak memory. This might not be a problem in tests,
647
+ // but I fear folks might see and use this implementation as a boiler plate when
648
+ // trying to use this hook
649
+ int zend_test_prepare_zendmm_for_call (zend_mm_heap * heap )
650
+ {
651
+ int flag = 0 ;
652
+ memcpy (& flag , heap , sizeof (int ));
653
+ int new_flag = 0 ;
654
+ memcpy (heap , & new_flag , sizeof (int ));
655
+ return flag ;
656
+ }
657
+
658
+ void zend_test_restore_zendmm_after_call (zend_mm_heap * heap , int flag )
659
+ {
660
+ memcpy (heap , & flag , sizeof (int ));
661
+ }
662
+
644
663
void * zend_test_custom_malloc (size_t len )
645
664
{
646
665
if (has_opline (EG (current_execute_data ))) {
647
666
assert (EG (current_execute_data )-> opline -> lineno != (uint32_t )-1 );
648
667
}
649
- return _zend_mm_alloc (ZT_G (zend_orig_heap ), len ZEND_FILE_LINE_EMPTY_CC ZEND_FILE_LINE_EMPTY_CC );
668
+ if (ZT_G (zendmm_orig_malloc )) {
669
+ return ZT_G (zendmm_orig_malloc )(len );
670
+ }
671
+ int flag = zend_test_prepare_zendmm_for_call (zend_mm_get_heap ());
672
+ void * ptr = _zend_mm_alloc (zend_mm_get_heap (), len ZEND_FILE_LINE_EMPTY_CC ZEND_FILE_LINE_EMPTY_CC );
673
+ zend_test_restore_zendmm_after_call (zend_mm_get_heap (), flag );
674
+ return ptr ;
650
675
}
651
676
652
677
void zend_test_custom_free (void * ptr )
653
678
{
654
679
if (has_opline (EG (current_execute_data ))) {
655
680
assert (EG (current_execute_data )-> opline -> lineno != (uint32_t )-1 );
656
681
}
657
- _zend_mm_free (ZT_G (zend_orig_heap ), ptr ZEND_FILE_LINE_EMPTY_CC ZEND_FILE_LINE_EMPTY_CC );
682
+ if (ZT_G (zendmm_orig_free )) {
683
+ ZT_G (zendmm_orig_free )(ptr );
684
+ return ;
685
+ }
686
+ int flag = zend_test_prepare_zendmm_for_call (zend_mm_get_heap ());
687
+ _zend_mm_free (zend_mm_get_heap (), ptr ZEND_FILE_LINE_EMPTY_CC ZEND_FILE_LINE_EMPTY_CC );
688
+ zend_test_restore_zendmm_after_call (zend_mm_get_heap (), flag );
658
689
}
659
690
660
691
void * zend_test_custom_realloc (void * ptr , size_t len )
661
692
{
662
693
if (has_opline (EG (current_execute_data ))) {
663
694
assert (EG (current_execute_data )-> opline -> lineno != (uint32_t )-1 );
664
695
}
665
- return _zend_mm_realloc (ZT_G (zend_orig_heap ), ptr , len ZEND_FILE_LINE_EMPTY_CC ZEND_FILE_LINE_EMPTY_CC );
696
+ if (ZT_G (zendmm_orig_realloc )) {
697
+ return ZT_G (zendmm_orig_realloc )(ptr , len );
698
+ }
699
+ int flag = zend_test_prepare_zendmm_for_call (zend_mm_get_heap ());
700
+ void * new_ptr = _zend_mm_realloc (zend_mm_get_heap (), ptr , len ZEND_FILE_LINE_EMPTY_CC ZEND_FILE_LINE_EMPTY_CC );
701
+ zend_test_restore_zendmm_after_call (zend_mm_get_heap (), flag );
702
+ return new_ptr ;
703
+ }
704
+
705
+ void zend_test_install_custom_mm_handler (void )
706
+ {
707
+ // fetch maybe installed previous handlers
708
+ if (!is_zend_mm ()) {
709
+ zend_mm_get_custom_handlers (
710
+ zend_mm_get_heap (),
711
+ & ZT_G (zendmm_orig_malloc ),
712
+ & ZT_G (zendmm_orig_free ),
713
+ & ZT_G (zendmm_orig_realloc )
714
+ );
715
+ }
716
+ zend_mm_set_custom_handlers (
717
+ zend_mm_get_heap (),
718
+ zend_test_custom_malloc ,
719
+ zend_test_custom_free ,
720
+ zend_test_custom_realloc
721
+ );
722
+ }
723
+
724
+ void zend_test_uninstall_custom_mm_handler (void )
725
+ {
726
+ void * (* custom_malloc )(size_t );
727
+ void (* custom_free )(void * );
728
+ void * (* custom_realloc )(void * , size_t );
729
+ zend_mm_get_custom_handlers (
730
+ zend_mm_get_heap (),
731
+ & custom_malloc ,
732
+ & custom_free ,
733
+ & custom_realloc
734
+ );
735
+ if (custom_malloc == zend_test_custom_malloc ||
736
+ custom_free == zend_test_custom_free ||
737
+ custom_realloc == zend_test_custom_realloc ) {
738
+ zend_mm_set_custom_handlers (
739
+ zend_mm_get_heap (),
740
+ ZT_G (zendmm_orig_malloc ),
741
+ ZT_G (zendmm_orig_free ),
742
+ ZT_G (zendmm_orig_realloc )
743
+ );
744
+ ZT_G (zendmm_orig_malloc ) = NULL ;
745
+ ZT_G (zendmm_orig_free ) = NULL ;
746
+ ZT_G (zendmm_orig_realloc ) = NULL ;
747
+ }
666
748
}
667
749
668
750
static PHP_INI_MH (OnUpdateZendTestObserveOplineInZendMM )
@@ -674,22 +756,9 @@ static PHP_INI_MH(OnUpdateZendTestObserveOplineInZendMM)
674
756
int int_value = zend_ini_parse_bool (new_value );
675
757
676
758
if (int_value == 1 ) {
677
- // `zend_mm_heap` is a private struct, so we have not way to find the
678
- // actual size, but 4096 bytes should be enough
679
- ZT_G (zend_test_heap ) = malloc (4096 );
680
- memset (ZT_G (zend_test_heap ), 0 , 4096 );
681
- zend_mm_set_custom_handlers (
682
- ZT_G (zend_test_heap ),
683
- zend_test_custom_malloc ,
684
- zend_test_custom_free ,
685
- zend_test_custom_realloc
686
- );
687
- ZT_G (zend_orig_heap ) = zend_mm_get_heap ();
688
- zend_mm_set_heap (ZT_G (zend_test_heap ));
689
- } else if (ZT_G (zend_test_heap )) {
690
- free (ZT_G (zend_test_heap ));
691
- ZT_G (zend_test_heap ) = NULL ;
692
- zend_mm_set_heap (ZT_G (zend_orig_heap ));
759
+ zend_test_install_custom_mm_handler ();
760
+ } else {
761
+ zend_test_uninstall_custom_mm_handler ();
693
762
}
694
763
return OnUpdateBool (entry , new_value , mh_arg1 , mh_arg2 , mh_arg3 , stage );
695
764
}
@@ -1206,6 +1275,8 @@ PHP_MSHUTDOWN_FUNCTION(zend_test)
1206
1275
1207
1276
zend_test_observer_shutdown (SHUTDOWN_FUNC_ARGS_PASSTHRU );
1208
1277
1278
+ zend_test_uninstall_custom_mm_handler ();
1279
+
1209
1280
if (ZT_G (print_stderr_mshutdown )) {
1210
1281
fprintf (stderr , "[zend_test] MSHUTDOWN\n" );
1211
1282
}
@@ -1228,12 +1299,6 @@ PHP_RSHUTDOWN_FUNCTION(zend_test)
1228
1299
} ZEND_HASH_FOREACH_END ();
1229
1300
zend_hash_destroy (& ZT_G (global_weakmap ));
1230
1301
1231
- if (ZT_G (zend_test_heap )) {
1232
- free (ZT_G (zend_test_heap ));
1233
- ZT_G (zend_test_heap ) = NULL ;
1234
- zend_mm_set_heap (ZT_G (zend_orig_heap ));
1235
- }
1236
-
1237
1302
return SUCCESS ;
1238
1303
}
1239
1304
0 commit comments