|
31 | 31 | #include "zend_interfaces.h"
|
32 | 32 | #include "zend_weakrefs.h"
|
33 | 33 | #include "Zend/Optimizer/zend_optimizer.h"
|
| 34 | +#include "Zend/zend_alloc.h" |
34 | 35 | #include "test_arginfo.h"
|
35 | 36 | #include "zend_call_stack.h"
|
36 | 37 | #include "zend_exceptions.h"
|
37 | 38 |
|
| 39 | +// `php.h` sets `NDEBUG` when not `PHP_DEBUG` which will make `assert()` from |
| 40 | +// assert.h a no-op. In order to have `assert()` working on NDEBUG builds, we |
| 41 | +// undefine `NDEBUG` and re-include assert.h |
| 42 | +#undef NDEBUG |
| 43 | +#include "assert.h" |
| 44 | + |
38 | 45 | #if defined(HAVE_LIBXML) && !defined(PHP_WIN32)
|
39 | 46 | # include <libxml/globals.h>
|
40 | 47 | # include <libxml/parser.h>
|
@@ -622,6 +629,68 @@ static ZEND_FUNCTION(zend_test_crash)
|
622 | 629 | php_printf("%s", invalid);
|
623 | 630 | }
|
624 | 631 |
|
| 632 | +static bool has_opline(zend_execute_data *execute_data) |
| 633 | +{ |
| 634 | + return execute_data |
| 635 | + && execute_data->func |
| 636 | + && ZEND_USER_CODE(execute_data->func->type) |
| 637 | + && execute_data->opline |
| 638 | + ; |
| 639 | +} |
| 640 | + |
| 641 | +void * zend_test_custom_malloc(size_t len) |
| 642 | +{ |
| 643 | + if (has_opline(EG(current_execute_data))) { |
| 644 | + assert(EG(current_execute_data)->opline->lineno != (uint32_t)-1); |
| 645 | + } |
| 646 | + return _zend_mm_alloc(ZT_G(zend_orig_heap), len ZEND_FILE_LINE_EMPTY_CC ZEND_FILE_LINE_EMPTY_CC); |
| 647 | +} |
| 648 | + |
| 649 | +void zend_test_custom_free(void *ptr) |
| 650 | +{ |
| 651 | + if (has_opline(EG(current_execute_data))) { |
| 652 | + assert(EG(current_execute_data)->opline->lineno != (uint32_t)-1); |
| 653 | + } |
| 654 | + _zend_mm_free(ZT_G(zend_orig_heap), ptr ZEND_FILE_LINE_EMPTY_CC ZEND_FILE_LINE_EMPTY_CC); |
| 655 | +} |
| 656 | + |
| 657 | +void * zend_test_custom_realloc(void * ptr, size_t len) |
| 658 | +{ |
| 659 | + if (has_opline(EG(current_execute_data))) { |
| 660 | + assert(EG(current_execute_data)->opline->lineno != (uint32_t)-1); |
| 661 | + } |
| 662 | + return _zend_mm_realloc(ZT_G(zend_orig_heap), ptr, len ZEND_FILE_LINE_EMPTY_CC ZEND_FILE_LINE_EMPTY_CC); |
| 663 | +} |
| 664 | + |
| 665 | +static PHP_INI_MH(OnUpdateZendTestObserveOplineInZendMM) |
| 666 | +{ |
| 667 | + if (new_value == NULL) { |
| 668 | + return FAILURE; |
| 669 | + } |
| 670 | + |
| 671 | + int int_value = zend_ini_parse_bool(new_value); |
| 672 | + |
| 673 | + if (int_value == 1) { |
| 674 | + // `zend_mm_heap` is a private struct, so we have not way to find the |
| 675 | + // actual size, but 4096 bytes should be enough |
| 676 | + ZT_G(zend_test_heap) = malloc(4096); |
| 677 | + memset(ZT_G(zend_test_heap), 0, 4096); |
| 678 | + zend_mm_set_custom_handlers( |
| 679 | + ZT_G(zend_test_heap), |
| 680 | + zend_test_custom_malloc, |
| 681 | + zend_test_custom_free, |
| 682 | + zend_test_custom_realloc |
| 683 | + ); |
| 684 | + ZT_G(zend_orig_heap) = zend_mm_get_heap(); |
| 685 | + zend_mm_set_heap(ZT_G(zend_test_heap)); |
| 686 | + } else if (ZT_G(zend_test_heap)) { |
| 687 | + free(ZT_G(zend_test_heap)); |
| 688 | + ZT_G(zend_test_heap) = NULL; |
| 689 | + zend_mm_set_heap(ZT_G(zend_orig_heap)); |
| 690 | + } |
| 691 | + return OnUpdateBool(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage); |
| 692 | +} |
| 693 | + |
625 | 694 | static ZEND_FUNCTION(zend_test_fill_packed_array)
|
626 | 695 | {
|
627 | 696 | HashTable *parameter;
|
@@ -903,6 +972,7 @@ PHP_INI_BEGIN()
|
903 | 972 | STD_PHP_INI_ENTRY("zend_test.quantity_value", "0", PHP_INI_ALL, OnUpdateLong, quantity_value, zend_zend_test_globals, zend_test_globals)
|
904 | 973 | STD_PHP_INI_ENTRY("zend_test.str_test", "", PHP_INI_ALL, OnUpdateStr, str_test, zend_zend_test_globals, zend_test_globals)
|
905 | 974 | STD_PHP_INI_ENTRY("zend_test.not_empty_str_test", "val", PHP_INI_ALL, OnUpdateStrNotEmpty, not_empty_str_test, zend_zend_test_globals, zend_test_globals)
|
| 975 | + STD_PHP_INI_BOOLEAN("zend_test.observe_opline_in_zendmm", "0", PHP_INI_ALL, OnUpdateZendTestObserveOplineInZendMM, observe_opline_in_zendmm, zend_zend_test_globals, zend_test_globals) |
906 | 976 | PHP_INI_END()
|
907 | 977 |
|
908 | 978 | void (*old_zend_execute_ex)(zend_execute_data *execute_data);
|
@@ -1134,6 +1204,13 @@ PHP_RSHUTDOWN_FUNCTION(zend_test)
|
1134 | 1204 | zend_weakrefs_hash_del(&ZT_G(global_weakmap), zend_weakref_key_to_object(obj_key));
|
1135 | 1205 | } ZEND_HASH_FOREACH_END();
|
1136 | 1206 | zend_hash_destroy(&ZT_G(global_weakmap));
|
| 1207 | + |
| 1208 | + if (ZT_G(zend_test_heap)) { |
| 1209 | + free(ZT_G(zend_test_heap)); |
| 1210 | + ZT_G(zend_test_heap) = NULL; |
| 1211 | + zend_mm_set_heap(ZT_G(zend_orig_heap)); |
| 1212 | + } |
| 1213 | + |
1137 | 1214 | return SUCCESS;
|
1138 | 1215 | }
|
1139 | 1216 |
|
|
0 commit comments