|
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_arginfo.h"
|
34 | 35 |
|
| 36 | +// `php.h` sets `NDEBUG` when not `PHP_DEBUG` which will make `assert()` from |
| 37 | +// assert.h a no-op. In order to have `assert()` working on NDEBUG builds, we |
| 38 | +// undefine `NDEBUG` and re-include assert.h |
| 39 | +#undef NDEBUG |
| 40 | +#include "assert.h" |
| 41 | + |
35 | 42 | #if defined(HAVE_LIBXML) && !defined(PHP_WIN32)
|
36 | 43 | # include <libxml/globals.h>
|
37 | 44 | # include <libxml/parser.h>
|
@@ -364,6 +371,68 @@ static ZEND_FUNCTION(zend_test_crash)
|
364 | 371 | php_printf("%s", invalid);
|
365 | 372 | }
|
366 | 373 |
|
| 374 | +static bool has_opline(zend_execute_data *execute_data) |
| 375 | +{ |
| 376 | + return execute_data |
| 377 | + && execute_data->func |
| 378 | + && ZEND_USER_CODE(execute_data->func->type) |
| 379 | + && execute_data->opline |
| 380 | + ; |
| 381 | +} |
| 382 | + |
| 383 | +void * zend_test_custom_malloc(size_t len) |
| 384 | +{ |
| 385 | + if (has_opline(EG(current_execute_data))) { |
| 386 | + assert(EG(current_execute_data)->opline->lineno != (uint32_t)-1); |
| 387 | + } |
| 388 | + return _zend_mm_alloc(ZT_G(zend_orig_heap), len ZEND_FILE_LINE_EMPTY_CC ZEND_FILE_LINE_EMPTY_CC); |
| 389 | +} |
| 390 | + |
| 391 | +void zend_test_custom_free(void *ptr) |
| 392 | +{ |
| 393 | + if (has_opline(EG(current_execute_data))) { |
| 394 | + assert(EG(current_execute_data)->opline->lineno != (uint32_t)-1); |
| 395 | + } |
| 396 | + _zend_mm_free(ZT_G(zend_orig_heap), ptr ZEND_FILE_LINE_EMPTY_CC ZEND_FILE_LINE_EMPTY_CC); |
| 397 | +} |
| 398 | + |
| 399 | +void * zend_test_custom_realloc(void * ptr, size_t len) |
| 400 | +{ |
| 401 | + if (has_opline(EG(current_execute_data))) { |
| 402 | + assert(EG(current_execute_data)->opline->lineno != (uint32_t)-1); |
| 403 | + } |
| 404 | + return _zend_mm_realloc(ZT_G(zend_orig_heap), ptr, len ZEND_FILE_LINE_EMPTY_CC ZEND_FILE_LINE_EMPTY_CC); |
| 405 | +} |
| 406 | + |
| 407 | +static PHP_INI_MH(OnUpdateZendTestObserveOplineInZendMM) |
| 408 | +{ |
| 409 | + if (new_value == NULL) { |
| 410 | + return FAILURE; |
| 411 | + } |
| 412 | + |
| 413 | + int int_value = zend_ini_parse_bool(new_value); |
| 414 | + |
| 415 | + if (int_value == 1) { |
| 416 | + // `zend_mm_heap` is a private struct, so we have not way to find the |
| 417 | + // actual size, but 4096 bytes should be enough |
| 418 | + ZT_G(zend_test_heap) = malloc(4096); |
| 419 | + memset(ZT_G(zend_test_heap), 0, 4096); |
| 420 | + zend_mm_set_custom_handlers( |
| 421 | + ZT_G(zend_test_heap), |
| 422 | + zend_test_custom_malloc, |
| 423 | + zend_test_custom_free, |
| 424 | + zend_test_custom_realloc |
| 425 | + ); |
| 426 | + ZT_G(zend_orig_heap) = zend_mm_get_heap(); |
| 427 | + zend_mm_set_heap(ZT_G(zend_test_heap)); |
| 428 | + } else if (ZT_G(zend_test_heap)) { |
| 429 | + free(ZT_G(zend_test_heap)); |
| 430 | + ZT_G(zend_test_heap) = NULL; |
| 431 | + zend_mm_set_heap(ZT_G(zend_orig_heap)); |
| 432 | + } |
| 433 | + return OnUpdateBool(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage); |
| 434 | +} |
| 435 | + |
367 | 436 | static ZEND_FUNCTION(zend_test_is_pcre_bundled)
|
368 | 437 | {
|
369 | 438 | ZEND_PARSE_PARAMETERS_NONE();
|
@@ -558,6 +627,7 @@ static ZEND_METHOD(ZendTestChildClassWithMethodWithParameterAttribute, override)
|
558 | 627 | PHP_INI_BEGIN()
|
559 | 628 | STD_PHP_INI_BOOLEAN("zend_test.replace_zend_execute_ex", "0", PHP_INI_SYSTEM, OnUpdateBool, replace_zend_execute_ex, zend_zend_test_globals, zend_test_globals)
|
560 | 629 | STD_PHP_INI_BOOLEAN("zend_test.register_passes", "0", PHP_INI_SYSTEM, OnUpdateBool, register_passes, zend_zend_test_globals, zend_test_globals)
|
| 630 | + 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) |
561 | 631 | PHP_INI_END()
|
562 | 632 |
|
563 | 633 | void (*old_zend_execute_ex)(zend_execute_data *execute_data);
|
@@ -700,6 +770,13 @@ PHP_RSHUTDOWN_FUNCTION(zend_test)
|
700 | 770 | zend_weakrefs_hash_del(&ZT_G(global_weakmap), (zend_object *)(uintptr_t)objptr);
|
701 | 771 | } ZEND_HASH_FOREACH_END();
|
702 | 772 | zend_hash_destroy(&ZT_G(global_weakmap));
|
| 773 | + |
| 774 | + if (ZT_G(zend_test_heap)) { |
| 775 | + free(ZT_G(zend_test_heap)); |
| 776 | + ZT_G(zend_test_heap) = NULL; |
| 777 | + zend_mm_set_heap(ZT_G(zend_orig_heap)); |
| 778 | + } |
| 779 | + |
703 | 780 | return SUCCESS;
|
704 | 781 | }
|
705 | 782 |
|
|
0 commit comments