|
30 | 30 | #include "zend_interfaces.h"
|
31 | 31 | #include "zend_weakrefs.h"
|
32 | 32 | #include "Zend/Optimizer/zend_optimizer.h"
|
| 33 | +#include "Zend/zend_alloc.h" |
33 | 34 | #include "test.h"
|
34 | 35 | #include "test_arginfo.h"
|
35 | 36 |
|
| 37 | +// `php.h` sets `NDEBUG` when not `PHP_DEBUG` which will make `assert()` from |
| 38 | +// assert.h a no-op. In order to have `assert()` working on NDEBUG builds, we |
| 39 | +// undefine `NDEBUG` and re-include assert.h |
| 40 | +#undef NDEBUG |
| 41 | +#include "assert.h" |
| 42 | + |
36 | 43 | #if defined(HAVE_LIBXML) && !defined(PHP_WIN32)
|
37 | 44 | # include <libxml/globals.h>
|
38 | 45 | # include <libxml/parser.h>
|
@@ -501,6 +508,68 @@ static ZEND_FUNCTION(zend_test_crash)
|
501 | 508 | php_printf("%s", invalid);
|
502 | 509 | }
|
503 | 510 |
|
| 511 | +static bool has_opline(zend_execute_data *execute_data) |
| 512 | +{ |
| 513 | + return execute_data |
| 514 | + && execute_data->func |
| 515 | + && ZEND_USER_CODE(execute_data->func->type) |
| 516 | + && execute_data->opline |
| 517 | + ; |
| 518 | +} |
| 519 | + |
| 520 | +void * zend_test_custom_malloc(size_t len) |
| 521 | +{ |
| 522 | + if (has_opline(EG(current_execute_data))) { |
| 523 | + assert(EG(current_execute_data)->opline->lineno != (uint32_t)-1); |
| 524 | + } |
| 525 | + return _zend_mm_alloc(ZT_G(zend_orig_heap), len ZEND_FILE_LINE_EMPTY_CC ZEND_FILE_LINE_EMPTY_CC); |
| 526 | +} |
| 527 | + |
| 528 | +void zend_test_custom_free(void *ptr) |
| 529 | +{ |
| 530 | + if (has_opline(EG(current_execute_data))) { |
| 531 | + assert(EG(current_execute_data)->opline->lineno != (uint32_t)-1); |
| 532 | + } |
| 533 | + _zend_mm_free(ZT_G(zend_orig_heap), ptr ZEND_FILE_LINE_EMPTY_CC ZEND_FILE_LINE_EMPTY_CC); |
| 534 | +} |
| 535 | + |
| 536 | +void * zend_test_custom_realloc(void * ptr, size_t len) |
| 537 | +{ |
| 538 | + if (has_opline(EG(current_execute_data))) { |
| 539 | + assert(EG(current_execute_data)->opline->lineno != (uint32_t)-1); |
| 540 | + } |
| 541 | + return _zend_mm_realloc(ZT_G(zend_orig_heap), ptr, len ZEND_FILE_LINE_EMPTY_CC ZEND_FILE_LINE_EMPTY_CC); |
| 542 | +} |
| 543 | + |
| 544 | +static PHP_INI_MH(OnUpdateZendTestObserveOplineInZendMM) |
| 545 | +{ |
| 546 | + if (new_value == NULL) { |
| 547 | + return FAILURE; |
| 548 | + } |
| 549 | + |
| 550 | + int int_value = zend_ini_parse_bool(new_value); |
| 551 | + |
| 552 | + if (int_value == 1) { |
| 553 | + // `zend_mm_heap` is a private struct, so we have not way to find the |
| 554 | + // actual size, but 4096 bytes should be enough |
| 555 | + ZT_G(zend_test_heap) = malloc(4096); |
| 556 | + memset(ZT_G(zend_test_heap), 0, 4096); |
| 557 | + zend_mm_set_custom_handlers( |
| 558 | + ZT_G(zend_test_heap), |
| 559 | + zend_test_custom_malloc, |
| 560 | + zend_test_custom_free, |
| 561 | + zend_test_custom_realloc |
| 562 | + ); |
| 563 | + ZT_G(zend_orig_heap) = zend_mm_get_heap(); |
| 564 | + zend_mm_set_heap(ZT_G(zend_test_heap)); |
| 565 | + } else if (ZT_G(zend_test_heap)) { |
| 566 | + free(ZT_G(zend_test_heap)); |
| 567 | + ZT_G(zend_test_heap) = NULL; |
| 568 | + zend_mm_set_heap(ZT_G(zend_orig_heap)); |
| 569 | + } |
| 570 | + return OnUpdateBool(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage); |
| 571 | +} |
| 572 | + |
504 | 573 | static ZEND_FUNCTION(zend_test_is_pcre_bundled)
|
505 | 574 | {
|
506 | 575 | ZEND_PARSE_PARAMETERS_NONE();
|
@@ -743,6 +812,7 @@ PHP_INI_BEGIN()
|
743 | 812 | STD_PHP_INI_ENTRY("zend_test.quantity_value", "0", PHP_INI_ALL, OnUpdateLong, quantity_value, zend_zend_test_globals, zend_test_globals)
|
744 | 813 | STD_PHP_INI_ENTRY("zend_test.str_test", "", PHP_INI_ALL, OnUpdateStr, str_test, zend_zend_test_globals, zend_test_globals)
|
745 | 814 | 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)
|
| 815 | + 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) |
746 | 816 | PHP_INI_END()
|
747 | 817 |
|
748 | 818 | void (*old_zend_execute_ex)(zend_execute_data *execute_data);
|
@@ -899,6 +969,13 @@ PHP_RSHUTDOWN_FUNCTION(zend_test)
|
899 | 969 | zend_weakrefs_hash_del(&ZT_G(global_weakmap), zend_weakref_key_to_object(obj_key));
|
900 | 970 | } ZEND_HASH_FOREACH_END();
|
901 | 971 | zend_hash_destroy(&ZT_G(global_weakmap));
|
| 972 | + |
| 973 | + if (ZT_G(zend_test_heap)) { |
| 974 | + free(ZT_G(zend_test_heap)); |
| 975 | + ZT_G(zend_test_heap) = NULL; |
| 976 | + zend_mm_set_heap(ZT_G(zend_orig_heap)); |
| 977 | + } |
| 978 | + |
902 | 979 | return SUCCESS;
|
903 | 980 | }
|
904 | 981 |
|
|
0 commit comments