2017-03-11 07:33:32 +08:00
|
|
|
/*
|
|
|
|
+----------------------------------------------------------------------+
|
2019-01-30 17:00:23 +08:00
|
|
|
| Copyright (c) The PHP Group |
|
2017-03-11 07:33:32 +08:00
|
|
|
+----------------------------------------------------------------------+
|
|
|
|
| This source file is subject to version 3.01 of the PHP license, |
|
|
|
|
| that is bundled with this package in the file LICENSE, and is |
|
|
|
|
| available through the world-wide-web at the following url: |
|
2021-05-06 18:16:35 +08:00
|
|
|
| https://www.php.net/license/3_01.txt |
|
2017-03-11 07:33:32 +08:00
|
|
|
| If you did not receive a copy of the PHP license and are unable to |
|
|
|
|
| obtain it through the world-wide-web, please send a note to |
|
|
|
|
| license@php.net so we can mail you a copy immediately. |
|
|
|
|
+----------------------------------------------------------------------+
|
|
|
|
| Author: |
|
|
|
|
+----------------------------------------------------------------------+
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
2021-06-12 01:25:47 +08:00
|
|
|
# include "config.h"
|
2017-03-11 07:33:32 +08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "php.h"
|
|
|
|
#include "php_ini.h"
|
|
|
|
#include "ext/standard/info.h"
|
|
|
|
#include "php_test.h"
|
2021-06-12 01:25:47 +08:00
|
|
|
#include "observer.h"
|
|
|
|
#include "fiber.h"
|
2023-08-28 00:06:10 +08:00
|
|
|
#include "iterators.h"
|
2023-08-03 01:52:55 +08:00
|
|
|
#include "object_handlers.h"
|
2020-05-25 02:57:00 +08:00
|
|
|
#include "zend_attributes.h"
|
2021-07-22 21:13:38 +08:00
|
|
|
#include "zend_enum.h"
|
2022-06-01 00:02:22 +08:00
|
|
|
#include "zend_interfaces.h"
|
2021-10-21 19:34:22 +08:00
|
|
|
#include "zend_weakrefs.h"
|
2021-01-31 18:51:13 +08:00
|
|
|
#include "Zend/Optimizer/zend_optimizer.h"
|
2023-11-25 07:54:02 +08:00
|
|
|
#include "Zend/zend_alloc.h"
|
2021-08-31 17:36:50 +08:00
|
|
|
#include "test_arginfo.h"
|
2022-12-17 00:44:26 +08:00
|
|
|
#include "zend_call_stack.h"
|
2023-03-22 03:41:18 +08:00
|
|
|
#include "zend_exceptions.h"
|
2020-09-01 23:57:49 +08:00
|
|
|
|
2023-11-25 07:54:02 +08:00
|
|
|
// `php.h` sets `NDEBUG` when not `PHP_DEBUG` which will make `assert()` from
|
|
|
|
// assert.h a no-op. In order to have `assert()` working on NDEBUG builds, we
|
|
|
|
// undefine `NDEBUG` and re-include assert.h
|
|
|
|
#undef NDEBUG
|
|
|
|
#include "assert.h"
|
|
|
|
|
2023-08-01 04:23:15 +08:00
|
|
|
#if defined(HAVE_LIBXML) && !defined(PHP_WIN32)
|
2023-07-15 23:33:52 +08:00
|
|
|
# include <libxml/globals.h>
|
|
|
|
# include <libxml/parser.h>
|
2023-12-07 06:49:07 +08:00
|
|
|
# include "ext/dom/php_dom.h"
|
2023-07-15 23:33:52 +08:00
|
|
|
#endif
|
|
|
|
|
2020-09-01 23:57:49 +08:00
|
|
|
ZEND_DECLARE_MODULE_GLOBALS(zend_test)
|
|
|
|
|
2017-03-11 07:33:32 +08:00
|
|
|
static zend_class_entry *zend_test_interface;
|
|
|
|
static zend_class_entry *zend_test_class;
|
2018-06-27 16:49:05 +08:00
|
|
|
static zend_class_entry *zend_test_child_class;
|
2022-12-27 05:47:36 +08:00
|
|
|
static zend_class_entry *zend_attribute_test_class;
|
2017-03-11 07:33:32 +08:00
|
|
|
static zend_class_entry *zend_test_trait;
|
2020-05-25 02:57:00 +08:00
|
|
|
static zend_class_entry *zend_test_attribute;
|
2022-12-27 05:47:36 +08:00
|
|
|
static zend_class_entry *zend_test_repeatable_attribute;
|
2022-02-10 02:16:57 +08:00
|
|
|
static zend_class_entry *zend_test_parameter_attribute;
|
2022-10-03 18:05:31 +08:00
|
|
|
static zend_class_entry *zend_test_property_attribute;
|
2022-02-10 02:16:57 +08:00
|
|
|
static zend_class_entry *zend_test_class_with_method_with_parameter_attribute;
|
|
|
|
static zend_class_entry *zend_test_child_class_with_method_with_parameter_attribute;
|
2023-08-24 22:07:00 +08:00
|
|
|
static zend_class_entry *zend_test_class_with_property_attribute;
|
2022-06-16 19:02:53 +08:00
|
|
|
static zend_class_entry *zend_test_forbid_dynamic_call;
|
2021-02-16 05:14:36 +08:00
|
|
|
static zend_class_entry *zend_test_ns_foo_class;
|
2022-07-28 15:28:04 +08:00
|
|
|
static zend_class_entry *zend_test_ns_unlikely_compile_error_class;
|
2023-10-31 17:06:56 +08:00
|
|
|
static zend_class_entry *zend_test_ns_not_unlikely_compile_error_class;
|
2021-02-16 05:14:36 +08:00
|
|
|
static zend_class_entry *zend_test_ns2_foo_class;
|
|
|
|
static zend_class_entry *zend_test_ns2_ns_foo_class;
|
2021-07-22 21:13:38 +08:00
|
|
|
static zend_class_entry *zend_test_unit_enum;
|
|
|
|
static zend_class_entry *zend_test_string_enum;
|
2022-05-09 06:10:12 +08:00
|
|
|
static zend_class_entry *zend_test_int_enum;
|
2023-11-30 20:41:07 +08:00
|
|
|
static zend_class_entry *zend_test_magic_call;
|
2017-03-11 07:33:32 +08:00
|
|
|
static zend_object_handlers zend_test_class_handlers;
|
|
|
|
|
2023-03-22 03:41:18 +08:00
|
|
|
static int le_throwing_resource;
|
|
|
|
|
2020-10-02 23:21:16 +08:00
|
|
|
static ZEND_FUNCTION(zend_test_func)
|
2017-03-11 07:33:32 +08:00
|
|
|
{
|
2019-02-08 02:05:46 +08:00
|
|
|
RETVAL_STR_COPY(EX(func)->common.function_name);
|
|
|
|
|
|
|
|
/* Cleanup trampoline */
|
|
|
|
ZEND_ASSERT(EX(func)->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE);
|
|
|
|
zend_string_release(EX(func)->common.function_name);
|
|
|
|
zend_free_trampoline(EX(func));
|
|
|
|
EX(func) = NULL;
|
2017-03-11 07:33:32 +08:00
|
|
|
}
|
|
|
|
|
2020-10-02 23:21:16 +08:00
|
|
|
static ZEND_FUNCTION(zend_test_array_return)
|
2017-03-11 07:33:32 +08:00
|
|
|
{
|
2020-07-21 21:30:59 +08:00
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
2017-03-11 07:33:32 +08:00
|
|
|
}
|
|
|
|
|
2020-10-02 23:21:16 +08:00
|
|
|
static ZEND_FUNCTION(zend_test_nullable_array_return)
|
2017-03-11 07:33:32 +08:00
|
|
|
{
|
2020-07-21 21:30:59 +08:00
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
2017-03-11 07:33:32 +08:00
|
|
|
}
|
|
|
|
|
2020-10-02 23:21:16 +08:00
|
|
|
static ZEND_FUNCTION(zend_test_void_return)
|
2018-07-01 02:14:15 +08:00
|
|
|
{
|
|
|
|
/* dummy */
|
2020-07-17 21:42:56 +08:00
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
2018-07-01 02:14:15 +08:00
|
|
|
}
|
|
|
|
|
2021-01-31 18:51:13 +08:00
|
|
|
static void pass1(zend_script *script, void *context)
|
|
|
|
{
|
|
|
|
php_printf("pass1\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
static void pass2(zend_script *script, void *context)
|
|
|
|
{
|
|
|
|
php_printf("pass2\n");
|
|
|
|
}
|
|
|
|
|
2020-10-02 23:21:16 +08:00
|
|
|
static ZEND_FUNCTION(zend_test_deprecated)
|
2019-11-18 04:28:17 +08:00
|
|
|
{
|
|
|
|
zval *arg1;
|
|
|
|
|
|
|
|
zend_parse_parameters(ZEND_NUM_ARGS(), "|z", &arg1);
|
|
|
|
}
|
|
|
|
|
2020-01-16 16:46:47 +08:00
|
|
|
/* Create a string without terminating null byte. Must be terminated with
|
2017-03-11 07:33:32 +08:00
|
|
|
* zend_terminate_string() before destruction, otherwise a warning is issued
|
|
|
|
* in debug builds. */
|
2020-10-02 23:21:16 +08:00
|
|
|
static ZEND_FUNCTION(zend_create_unterminated_string)
|
2017-03-11 07:33:32 +08:00
|
|
|
{
|
|
|
|
zend_string *str, *res;
|
|
|
|
|
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &str) == FAILURE) {
|
2019-12-31 18:27:02 +08:00
|
|
|
RETURN_THROWS();
|
2017-03-11 07:33:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
res = zend_string_alloc(ZSTR_LEN(str), 0);
|
|
|
|
memcpy(ZSTR_VAL(res), ZSTR_VAL(str), ZSTR_LEN(str));
|
|
|
|
/* No trailing null byte */
|
|
|
|
|
|
|
|
RETURN_STR(res);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Enforce terminate null byte on string. This avoids a warning in debug builds. */
|
2020-10-02 23:21:16 +08:00
|
|
|
static ZEND_FUNCTION(zend_terminate_string)
|
2017-03-11 07:33:32 +08:00
|
|
|
{
|
|
|
|
zend_string *str;
|
|
|
|
|
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &str) == FAILURE) {
|
2019-12-31 18:27:02 +08:00
|
|
|
RETURN_THROWS();
|
2017-03-11 07:33:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ZSTR_VAL(str)[ZSTR_LEN(str)] = '\0';
|
|
|
|
}
|
|
|
|
|
2021-06-12 01:25:47 +08:00
|
|
|
/* Cause an intentional memory leak, for testing/debugging purposes */
|
2020-10-02 23:21:16 +08:00
|
|
|
static ZEND_FUNCTION(zend_leak_bytes)
|
2017-03-11 07:33:32 +08:00
|
|
|
{
|
|
|
|
zend_long leakbytes = 3;
|
|
|
|
|
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &leakbytes) == FAILURE) {
|
2019-12-31 18:27:02 +08:00
|
|
|
RETURN_THROWS();
|
2017-03-11 07:33:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
emalloc(leakbytes);
|
|
|
|
}
|
|
|
|
|
2021-06-12 01:25:47 +08:00
|
|
|
/* Leak a refcounted variable */
|
2020-10-02 23:21:16 +08:00
|
|
|
static ZEND_FUNCTION(zend_leak_variable)
|
2017-03-11 07:33:32 +08:00
|
|
|
{
|
|
|
|
zval *zv;
|
|
|
|
|
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &zv) == FAILURE) {
|
2019-12-31 18:27:02 +08:00
|
|
|
RETURN_THROWS();
|
2017-03-11 07:33:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!Z_REFCOUNTED_P(zv)) {
|
|
|
|
zend_error(E_WARNING, "Cannot leak variable that is not refcounted");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Z_ADDREF_P(zv);
|
|
|
|
}
|
|
|
|
|
2020-09-11 06:23:54 +08:00
|
|
|
/* Tests Z_PARAM_OBJ_OR_STR */
|
2020-10-02 23:21:16 +08:00
|
|
|
static ZEND_FUNCTION(zend_string_or_object)
|
2020-06-30 21:04:54 +08:00
|
|
|
{
|
|
|
|
zend_string *str;
|
|
|
|
zend_object *object;
|
|
|
|
|
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
2020-09-11 06:23:54 +08:00
|
|
|
Z_PARAM_OBJ_OR_STR(object, str)
|
2020-06-30 21:04:54 +08:00
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
|
|
|
|
|
|
|
if (str) {
|
|
|
|
RETURN_STR_COPY(str);
|
|
|
|
} else {
|
|
|
|
RETURN_OBJ_COPY(object);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-11 06:23:54 +08:00
|
|
|
/* Tests Z_PARAM_OBJ_OR_STR_OR_NULL */
|
2020-10-02 23:21:16 +08:00
|
|
|
static ZEND_FUNCTION(zend_string_or_object_or_null)
|
2020-06-30 21:04:54 +08:00
|
|
|
{
|
|
|
|
zend_string *str;
|
|
|
|
zend_object *object;
|
|
|
|
|
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
2020-09-11 06:23:54 +08:00
|
|
|
Z_PARAM_OBJ_OR_STR_OR_NULL(object, str)
|
2020-06-30 21:04:54 +08:00
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
|
|
|
|
|
|
|
if (str) {
|
|
|
|
RETURN_STR_COPY(str);
|
|
|
|
} else if (object) {
|
|
|
|
RETURN_OBJ_COPY(object);
|
|
|
|
} else {
|
|
|
|
RETURN_NULL();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-11 06:23:54 +08:00
|
|
|
/* Tests Z_PARAM_OBJ_OF_CLASS_OR_STR */
|
2020-10-02 23:21:16 +08:00
|
|
|
static ZEND_FUNCTION(zend_string_or_stdclass)
|
2020-06-30 21:04:54 +08:00
|
|
|
{
|
|
|
|
zend_string *str;
|
|
|
|
zend_object *object;
|
|
|
|
|
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
2020-09-11 06:23:54 +08:00
|
|
|
Z_PARAM_OBJ_OF_CLASS_OR_STR(object, zend_standard_class_def, str)
|
2020-06-30 21:04:54 +08:00
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
|
|
|
|
|
|
|
if (str) {
|
|
|
|
RETURN_STR_COPY(str);
|
|
|
|
} else {
|
|
|
|
RETURN_OBJ_COPY(object);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-05 00:53:51 +08:00
|
|
|
static ZEND_FUNCTION(zend_test_compile_string)
|
|
|
|
{
|
|
|
|
zend_string *source_string = NULL;
|
|
|
|
zend_string *filename = NULL;
|
|
|
|
zend_long position = ZEND_COMPILE_POSITION_AT_OPEN_TAG;
|
|
|
|
|
|
|
|
ZEND_PARSE_PARAMETERS_START(3, 3)
|
|
|
|
Z_PARAM_STR(source_string)
|
|
|
|
Z_PARAM_STR(filename)
|
|
|
|
Z_PARAM_LONG(position)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
|
|
|
|
|
|
|
zend_op_array *op_array = NULL;
|
|
|
|
|
|
|
|
op_array = compile_string(source_string, ZSTR_VAL(filename), position);
|
|
|
|
|
|
|
|
if (op_array) {
|
|
|
|
zval retval;
|
|
|
|
|
|
|
|
zend_try {
|
|
|
|
ZVAL_UNDEF(&retval);
|
|
|
|
zend_execute(op_array, &retval);
|
|
|
|
} zend_catch {
|
|
|
|
destroy_op_array(op_array);
|
|
|
|
efree_size(op_array, sizeof(zend_op_array));
|
|
|
|
zend_bailout();
|
|
|
|
} zend_end_try();
|
|
|
|
|
|
|
|
destroy_op_array(op_array);
|
|
|
|
efree_size(op_array, sizeof(zend_op_array));
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-09-11 06:23:54 +08:00
|
|
|
/* Tests Z_PARAM_OBJ_OF_CLASS_OR_STR_OR_NULL */
|
2020-10-02 23:21:16 +08:00
|
|
|
static ZEND_FUNCTION(zend_string_or_stdclass_or_null)
|
2020-06-30 21:04:54 +08:00
|
|
|
{
|
|
|
|
zend_string *str;
|
|
|
|
zend_object *object;
|
|
|
|
|
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
2020-09-11 06:23:54 +08:00
|
|
|
Z_PARAM_OBJ_OF_CLASS_OR_STR_OR_NULL(object, zend_standard_class_def, str)
|
2020-06-30 21:04:54 +08:00
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
|
|
|
|
|
|
|
if (str) {
|
|
|
|
RETURN_STR_COPY(str);
|
|
|
|
} else if (object) {
|
|
|
|
RETURN_OBJ_COPY(object);
|
|
|
|
} else {
|
|
|
|
RETURN_NULL();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-08 01:15:53 +08:00
|
|
|
/* Tests Z_PARAM_NUMBER_OR_STR */
|
|
|
|
static ZEND_FUNCTION(zend_number_or_string)
|
|
|
|
{
|
|
|
|
zval *input;
|
|
|
|
|
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
|
|
|
Z_PARAM_NUMBER_OR_STR(input)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
|
|
|
|
|
|
|
switch (Z_TYPE_P(input)) {
|
|
|
|
case IS_LONG:
|
|
|
|
RETURN_LONG(Z_LVAL_P(input));
|
|
|
|
case IS_DOUBLE:
|
|
|
|
RETURN_DOUBLE(Z_DVAL_P(input));
|
|
|
|
case IS_STRING:
|
|
|
|
RETURN_STR_COPY(Z_STR_P(input));
|
|
|
|
EMPTY_SWITCH_DEFAULT_CASE();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Tests Z_PARAM_NUMBER_OR_STR_OR_NULL */
|
|
|
|
static ZEND_FUNCTION(zend_number_or_string_or_null)
|
|
|
|
{
|
|
|
|
zval *input;
|
|
|
|
|
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
|
|
|
Z_PARAM_NUMBER_OR_STR_OR_NULL(input)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
|
|
|
|
|
|
|
if (!input) {
|
|
|
|
RETURN_NULL();
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (Z_TYPE_P(input)) {
|
|
|
|
case IS_LONG:
|
|
|
|
RETURN_LONG(Z_LVAL_P(input));
|
|
|
|
case IS_DOUBLE:
|
|
|
|
RETURN_DOUBLE(Z_DVAL_P(input));
|
|
|
|
case IS_STRING:
|
|
|
|
RETURN_STR_COPY(Z_STR_P(input));
|
|
|
|
EMPTY_SWITCH_DEFAULT_CASE();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-21 19:34:22 +08:00
|
|
|
static ZEND_FUNCTION(zend_weakmap_attach)
|
|
|
|
{
|
|
|
|
zval *value;
|
|
|
|
zend_object *obj;
|
|
|
|
|
|
|
|
ZEND_PARSE_PARAMETERS_START(2, 2)
|
|
|
|
Z_PARAM_OBJ(obj)
|
|
|
|
Z_PARAM_ZVAL(value)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
|
|
|
|
|
|
|
if (zend_weakrefs_hash_add(&ZT_G(global_weakmap), obj, value)) {
|
|
|
|
Z_TRY_ADDREF_P(value);
|
|
|
|
RETURN_TRUE;
|
|
|
|
}
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ZEND_FUNCTION(zend_weakmap_remove)
|
|
|
|
{
|
|
|
|
zend_object *obj;
|
|
|
|
|
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
|
|
|
Z_PARAM_OBJ(obj)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
|
|
|
|
|
|
|
RETURN_BOOL(zend_weakrefs_hash_del(&ZT_G(global_weakmap), obj) == SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
static ZEND_FUNCTION(zend_weakmap_dump)
|
|
|
|
{
|
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
|
|
|
RETURN_ARR(zend_array_dup(&ZT_G(global_weakmap)));
|
|
|
|
}
|
|
|
|
|
2022-05-04 03:34:01 +08:00
|
|
|
static ZEND_FUNCTION(zend_get_current_func_name)
|
|
|
|
{
|
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
|
|
|
|
|
|
|
zend_string *function_name = get_function_or_method_name(EG(current_execute_data)->prev_execute_data->func);
|
|
|
|
|
|
|
|
RETURN_STR(function_name);
|
|
|
|
}
|
|
|
|
|
2023-08-01 04:23:15 +08:00
|
|
|
#if defined(HAVE_LIBXML) && !defined(PHP_WIN32)
|
2023-07-15 23:33:52 +08:00
|
|
|
static ZEND_FUNCTION(zend_test_override_libxml_global_state)
|
|
|
|
{
|
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
|
|
|
|
2023-12-07 06:49:07 +08:00
|
|
|
PHP_LIBXML_IGNORE_DEPRECATIONS_START
|
2023-07-15 23:33:52 +08:00
|
|
|
xmlLoadExtDtdDefaultValue = 1;
|
|
|
|
xmlDoValidityCheckingDefaultValue = 1;
|
|
|
|
(void) xmlPedanticParserDefault(1);
|
|
|
|
(void) xmlSubstituteEntitiesDefault(1);
|
|
|
|
(void) xmlLineNumbersDefault(1);
|
|
|
|
(void) xmlKeepBlanksDefault(0);
|
2023-12-07 06:49:07 +08:00
|
|
|
PHP_LIBXML_IGNORE_DEPRECATIONS_END
|
2023-07-15 23:33:52 +08:00
|
|
|
}
|
2023-08-01 04:23:15 +08:00
|
|
|
#endif
|
2023-07-15 23:33:52 +08:00
|
|
|
|
2020-09-03 21:03:12 +08:00
|
|
|
/* TESTS Z_PARAM_ITERABLE and Z_PARAM_ITERABLE_OR_NULL */
|
2020-10-02 23:21:16 +08:00
|
|
|
static ZEND_FUNCTION(zend_iterable)
|
2020-09-03 21:03:12 +08:00
|
|
|
{
|
|
|
|
zval *arg1, *arg2;
|
|
|
|
|
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 2)
|
|
|
|
Z_PARAM_ITERABLE(arg1)
|
|
|
|
Z_PARAM_OPTIONAL
|
|
|
|
Z_PARAM_ITERABLE_OR_NULL(arg2)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
|
|
|
}
|
|
|
|
|
2022-06-07 20:35:34 +08:00
|
|
|
static ZEND_FUNCTION(zend_iterable_legacy)
|
|
|
|
{
|
|
|
|
zval *arg1, *arg2;
|
|
|
|
|
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 2)
|
|
|
|
Z_PARAM_ITERABLE(arg1)
|
|
|
|
Z_PARAM_OPTIONAL
|
|
|
|
Z_PARAM_ITERABLE_OR_NULL(arg2)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
|
|
|
|
|
|
|
RETURN_COPY(arg1);
|
|
|
|
}
|
|
|
|
|
|
|
|
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_iterable_legacy, 0, 1, IS_ITERABLE, 0)
|
|
|
|
ZEND_ARG_TYPE_INFO(0, arg1, IS_ITERABLE, 0)
|
|
|
|
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, arg2, IS_ITERABLE, 1, "null")
|
|
|
|
ZEND_END_ARG_INFO()
|
|
|
|
|
|
|
|
static const zend_function_entry ext_function_legacy[] = {
|
|
|
|
ZEND_FE(zend_iterable_legacy, arginfo_zend_iterable_legacy)
|
|
|
|
ZEND_FE_END
|
|
|
|
};
|
|
|
|
|
2022-06-01 00:02:22 +08:00
|
|
|
/* Call a method on a class or object using zend_call_method() */
|
|
|
|
static ZEND_FUNCTION(zend_call_method)
|
|
|
|
{
|
2022-06-02 00:09:47 +08:00
|
|
|
zend_string *method_name;
|
|
|
|
zval *class_or_object, *arg1 = NULL, *arg2 = NULL;
|
|
|
|
zend_object *obj = NULL;
|
2022-06-01 00:02:22 +08:00
|
|
|
zend_class_entry *ce = NULL;
|
|
|
|
int argc = ZEND_NUM_ARGS();
|
|
|
|
|
|
|
|
ZEND_PARSE_PARAMETERS_START(2, 4)
|
2022-06-02 00:09:47 +08:00
|
|
|
Z_PARAM_ZVAL(class_or_object)
|
2022-06-01 00:02:22 +08:00
|
|
|
Z_PARAM_STR(method_name)
|
|
|
|
Z_PARAM_OPTIONAL
|
|
|
|
Z_PARAM_ZVAL(arg1)
|
|
|
|
Z_PARAM_ZVAL(arg2)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
|
|
|
|
2022-06-02 00:09:47 +08:00
|
|
|
if (Z_TYPE_P(class_or_object) == IS_OBJECT) {
|
|
|
|
obj = Z_OBJ_P(class_or_object);
|
|
|
|
ce = obj->ce;
|
2022-06-02 00:27:47 +08:00
|
|
|
} else if (Z_TYPE_P(class_or_object) == IS_STRING) {
|
2022-06-02 00:09:47 +08:00
|
|
|
ce = zend_lookup_class(Z_STR_P(class_or_object));
|
|
|
|
if (!ce) {
|
|
|
|
zend_error(E_ERROR, "Unknown class '%s'", Z_STRVAL_P(class_or_object));
|
|
|
|
return;
|
|
|
|
}
|
2022-06-02 00:27:47 +08:00
|
|
|
} else {
|
2023-01-23 17:52:14 +08:00
|
|
|
zend_argument_type_error(1, "must be of type object|string, %s given", zend_zval_value_name(class_or_object));
|
2022-06-02 00:27:47 +08:00
|
|
|
return;
|
2022-06-02 00:09:47 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ZEND_ASSERT((argc >= 2) && (argc <= 4));
|
|
|
|
zend_call_method(obj, ce, NULL, ZSTR_VAL(method_name), ZSTR_LEN(method_name), return_value, argc - 2, arg1, arg2);
|
2022-06-01 00:02:22 +08:00
|
|
|
}
|
|
|
|
|
2021-07-22 21:13:38 +08:00
|
|
|
static ZEND_FUNCTION(zend_get_unit_enum)
|
|
|
|
{
|
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
|
|
|
|
|
|
|
RETURN_OBJ_COPY(zend_enum_get_case_cstr(zend_test_unit_enum, "Foo"));
|
|
|
|
}
|
|
|
|
|
2022-06-17 20:12:53 +08:00
|
|
|
static ZEND_FUNCTION(zend_test_zend_ini_parse_quantity)
|
|
|
|
{
|
|
|
|
zend_string *str;
|
|
|
|
zend_string *errstr;
|
|
|
|
|
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
|
|
|
Z_PARAM_STR(str)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
|
|
|
|
|
|
|
RETVAL_LONG(zend_ini_parse_quantity(str, &errstr));
|
|
|
|
|
|
|
|
if (errstr) {
|
|
|
|
zend_error(E_WARNING, "%s", ZSTR_VAL(errstr));
|
|
|
|
zend_string_release(errstr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static ZEND_FUNCTION(zend_test_zend_ini_parse_uquantity)
|
|
|
|
{
|
|
|
|
zend_string *str;
|
|
|
|
zend_string *errstr;
|
|
|
|
|
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
|
|
|
Z_PARAM_STR(str)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
|
|
|
|
|
|
|
RETVAL_LONG((zend_long)zend_ini_parse_uquantity(str, &errstr));
|
|
|
|
|
|
|
|
if (errstr) {
|
|
|
|
zend_error(E_WARNING, "%s", ZSTR_VAL(errstr));
|
|
|
|
zend_string_release(errstr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-08-13 22:32:25 +08:00
|
|
|
static ZEND_FUNCTION(zend_test_zend_ini_str)
|
|
|
|
{
|
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
|
|
|
|
|
|
|
RETURN_STR(ZT_G(str_test));
|
|
|
|
}
|
|
|
|
|
2023-01-30 00:35:37 +08:00
|
|
|
static ZEND_FUNCTION(zend_test_is_string_marked_as_valid_utf8)
|
|
|
|
{
|
|
|
|
zend_string *str;
|
|
|
|
|
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
|
|
|
Z_PARAM_STR(str)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
|
|
|
|
|
|
|
RETURN_BOOL(ZSTR_IS_VALID_UTF8(str));
|
|
|
|
}
|
|
|
|
|
2022-08-23 19:46:44 +08:00
|
|
|
static ZEND_FUNCTION(ZendTestNS2_namespaced_func)
|
2021-02-03 22:57:27 +08:00
|
|
|
{
|
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
|
|
|
RETURN_TRUE;
|
|
|
|
}
|
|
|
|
|
2022-08-23 19:46:44 +08:00
|
|
|
static ZEND_FUNCTION(ZendTestNS2_namespaced_deprecated_func)
|
|
|
|
{
|
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
|
|
|
}
|
|
|
|
|
|
|
|
static ZEND_FUNCTION(ZendTestNS2_ZendSubNS_namespaced_func)
|
|
|
|
{
|
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
|
|
|
RETURN_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ZEND_FUNCTION(ZendTestNS2_ZendSubNS_namespaced_deprecated_func)
|
|
|
|
{
|
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
|
|
|
}
|
|
|
|
|
2022-02-10 02:16:57 +08:00
|
|
|
static ZEND_FUNCTION(zend_test_parameter_with_attribute)
|
|
|
|
{
|
|
|
|
zend_string *parameter;
|
|
|
|
|
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
|
|
|
Z_PARAM_STR(parameter)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
|
|
|
|
|
|
|
RETURN_LONG(1);
|
|
|
|
}
|
|
|
|
|
2022-12-17 00:44:26 +08:00
|
|
|
#ifdef ZEND_CHECK_STACK_LIMIT
|
|
|
|
static ZEND_FUNCTION(zend_test_zend_call_stack_get)
|
|
|
|
{
|
|
|
|
zend_call_stack stack;
|
|
|
|
|
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
|
|
|
|
|
|
|
if (zend_call_stack_get(&stack)) {
|
|
|
|
zend_string *str;
|
|
|
|
|
|
|
|
array_init(return_value);
|
|
|
|
|
|
|
|
str = strpprintf(0, "%p", stack.base);
|
|
|
|
add_assoc_str(return_value, "base", str);
|
|
|
|
|
|
|
|
str = strpprintf(0, "0x%zx", stack.max_size);
|
|
|
|
add_assoc_str(return_value, "max_size", str);
|
|
|
|
|
|
|
|
str = strpprintf(0, "%p", zend_call_stack_position());
|
|
|
|
add_assoc_str(return_value, "position", str);
|
|
|
|
|
|
|
|
str = strpprintf(0, "%p", EG(stack_limit));
|
|
|
|
add_assoc_str(return_value, "EG(stack_limit)", str);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
RETURN_NULL();
|
|
|
|
}
|
|
|
|
|
|
|
|
zend_long (*volatile zend_call_stack_use_all_fun)(void *limit);
|
|
|
|
|
|
|
|
static zend_long zend_call_stack_use_all(void *limit)
|
|
|
|
{
|
|
|
|
if (zend_call_stack_overflowed(limit)) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1 + zend_call_stack_use_all_fun(limit);
|
|
|
|
}
|
|
|
|
|
|
|
|
static ZEND_FUNCTION(zend_test_zend_call_stack_use_all)
|
|
|
|
{
|
|
|
|
zend_call_stack stack;
|
|
|
|
|
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
|
|
|
|
|
|
|
if (!zend_call_stack_get(&stack)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
zend_call_stack_use_all_fun = zend_call_stack_use_all;
|
|
|
|
|
|
|
|
void *limit = zend_call_stack_limit(stack.base, stack.max_size, 4096);
|
|
|
|
|
|
|
|
RETURN_LONG(zend_call_stack_use_all(limit));
|
|
|
|
}
|
|
|
|
#endif /* ZEND_CHECK_STACK_LIMIT */
|
|
|
|
|
2023-03-05 06:22:05 +08:00
|
|
|
static ZEND_FUNCTION(zend_get_map_ptr_last)
|
|
|
|
{
|
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
|
|
|
RETURN_LONG(CG(map_ptr_last));
|
|
|
|
}
|
|
|
|
|
2023-04-15 22:08:24 +08:00
|
|
|
static ZEND_FUNCTION(zend_test_crash)
|
|
|
|
{
|
2023-04-16 05:21:48 +08:00
|
|
|
zend_string *message = NULL;
|
2023-04-15 22:08:24 +08:00
|
|
|
|
|
|
|
ZEND_PARSE_PARAMETERS_START(0, 1)
|
|
|
|
Z_PARAM_OPTIONAL
|
|
|
|
Z_PARAM_STR_OR_NULL(message)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
|
|
|
|
|
|
|
if (message) {
|
|
|
|
php_printf("%s", ZSTR_VAL(message));
|
|
|
|
}
|
|
|
|
|
|
|
|
char *invalid = (char *) 1;
|
|
|
|
php_printf("%s", invalid);
|
|
|
|
}
|
|
|
|
|
2023-11-25 07:54:02 +08:00
|
|
|
static bool has_opline(zend_execute_data *execute_data)
|
|
|
|
{
|
|
|
|
return execute_data
|
|
|
|
&& execute_data->func
|
|
|
|
&& ZEND_USER_CODE(execute_data->func->type)
|
|
|
|
&& execute_data->opline
|
|
|
|
;
|
|
|
|
}
|
|
|
|
|
|
|
|
void * zend_test_custom_malloc(size_t len)
|
|
|
|
{
|
|
|
|
if (has_opline(EG(current_execute_data))) {
|
|
|
|
assert(EG(current_execute_data)->opline->lineno != (uint32_t)-1);
|
|
|
|
}
|
|
|
|
return _zend_mm_alloc(ZT_G(zend_orig_heap), len ZEND_FILE_LINE_EMPTY_CC ZEND_FILE_LINE_EMPTY_CC);
|
|
|
|
}
|
|
|
|
|
|
|
|
void zend_test_custom_free(void *ptr)
|
|
|
|
{
|
|
|
|
if (has_opline(EG(current_execute_data))) {
|
|
|
|
assert(EG(current_execute_data)->opline->lineno != (uint32_t)-1);
|
|
|
|
}
|
|
|
|
_zend_mm_free(ZT_G(zend_orig_heap), ptr ZEND_FILE_LINE_EMPTY_CC ZEND_FILE_LINE_EMPTY_CC);
|
|
|
|
}
|
|
|
|
|
|
|
|
void * zend_test_custom_realloc(void * ptr, size_t len)
|
|
|
|
{
|
|
|
|
if (has_opline(EG(current_execute_data))) {
|
|
|
|
assert(EG(current_execute_data)->opline->lineno != (uint32_t)-1);
|
|
|
|
}
|
|
|
|
return _zend_mm_realloc(ZT_G(zend_orig_heap), ptr, len ZEND_FILE_LINE_EMPTY_CC ZEND_FILE_LINE_EMPTY_CC);
|
|
|
|
}
|
|
|
|
|
|
|
|
static PHP_INI_MH(OnUpdateZendTestObserveOplineInZendMM)
|
|
|
|
{
|
|
|
|
if (new_value == NULL) {
|
|
|
|
return FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
int int_value = zend_ini_parse_bool(new_value);
|
|
|
|
|
|
|
|
if (int_value == 1) {
|
|
|
|
// `zend_mm_heap` is a private struct, so we have not way to find the
|
|
|
|
// actual size, but 4096 bytes should be enough
|
|
|
|
ZT_G(zend_test_heap) = malloc(4096);
|
|
|
|
memset(ZT_G(zend_test_heap), 0, 4096);
|
|
|
|
zend_mm_set_custom_handlers(
|
|
|
|
ZT_G(zend_test_heap),
|
|
|
|
zend_test_custom_malloc,
|
|
|
|
zend_test_custom_free,
|
|
|
|
zend_test_custom_realloc
|
|
|
|
);
|
|
|
|
ZT_G(zend_orig_heap) = zend_mm_get_heap();
|
|
|
|
zend_mm_set_heap(ZT_G(zend_test_heap));
|
|
|
|
} else if (ZT_G(zend_test_heap)) {
|
|
|
|
free(ZT_G(zend_test_heap));
|
|
|
|
ZT_G(zend_test_heap) = NULL;
|
|
|
|
zend_mm_set_heap(ZT_G(zend_orig_heap));
|
|
|
|
}
|
|
|
|
return OnUpdateBool(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
|
|
|
|
}
|
|
|
|
|
2023-04-07 03:54:59 +08:00
|
|
|
static ZEND_FUNCTION(zend_test_fill_packed_array)
|
|
|
|
{
|
|
|
|
HashTable *parameter;
|
|
|
|
|
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
|
|
|
Z_PARAM_ARRAY_HT_EX(parameter, 0, 1)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
|
|
|
|
|
|
|
if (!HT_IS_PACKED(parameter)) {
|
|
|
|
zend_argument_value_error(1, "must be a packed array");
|
|
|
|
RETURN_THROWS();
|
|
|
|
}
|
|
|
|
|
|
|
|
zend_hash_extend(parameter, parameter->nNumUsed + 10, true);
|
|
|
|
ZEND_HASH_FILL_PACKED(parameter) {
|
|
|
|
for (int i = 0; i < 10; i++) {
|
|
|
|
zval value;
|
|
|
|
ZVAL_LONG(&value, i);
|
|
|
|
ZEND_HASH_FILL_ADD(&value);
|
|
|
|
}
|
|
|
|
} ZEND_HASH_FILL_END();
|
|
|
|
}
|
|
|
|
|
2023-04-01 03:37:45 +08:00
|
|
|
static ZEND_FUNCTION(get_open_basedir)
|
|
|
|
{
|
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
2023-10-23 15:23:36 +08:00
|
|
|
if (PG(open_basedir)) {
|
|
|
|
RETURN_STRING(PG(open_basedir));
|
|
|
|
} else {
|
|
|
|
RETURN_NULL();
|
|
|
|
}
|
2023-04-01 03:37:45 +08:00
|
|
|
}
|
|
|
|
|
2023-11-08 15:39:05 +08:00
|
|
|
static ZEND_FUNCTION(zend_test_is_pcre_bundled)
|
|
|
|
{
|
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
|
|
|
#if HAVE_BUNDLED_PCRE
|
|
|
|
RETURN_TRUE;
|
|
|
|
#else
|
|
|
|
RETURN_FALSE;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2024-05-14 02:28:59 +08:00
|
|
|
#ifdef PHP_WIN32
|
|
|
|
static ZEND_FUNCTION(zend_test_set_fmode)
|
|
|
|
{
|
|
|
|
bool binary;
|
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
|
|
|
Z_PARAM_BOOL(binary)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
|
|
|
|
|
|
|
_fmode = binary ? _O_BINARY : _O_TEXT;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
Fix GH-11078: PHP Fatal error triggers pointer being freed was not allocated and malloc: double free for ptr errors
Although the issue was demonstrated using Curl, the issue is purely in
the streams layer of PHP.
Full analysis is written in GH-11078 [1], but here is the brief version:
Here's what actually happens:
1) We're creating a FILE handle from a stream using the casting mechanism.
This will create a cookie-based FILE handle using funopen.
2) We're reading stream data using fread from the userspace stream. This will
temporarily set a buffer into a field _bf.base [2]. This buffer is now equal
to the upload buffer that Curl allocated and note that that buffer is owned
by Curl.
3) The fatal error occurs and we bail out from the fread function, notice how
the reset code is never executed and so the buffer will still point to
Curl's upload buffer instead of FILE's own buffer [3].
4) The resources are destroyed, this includes our opened stream and because the
FILE handle is cached, it gets destroyed as well.
In fact, the stream code calls through fclose on purpose in this case.
5) The fclose code frees the _bs.base buffer [4].
However, this is not the buffer that FILE owns but the one that Curl owns
because it isn't reset properly due to the bailout!
6) The objects are getting destroyed, and so the curl free logic is invoked.
When Curl tries to gracefully clean up, it tries to free the buffer.
But that buffer is actually already freed mistakingly by the C library!
This also explains why we can't reproduce it on Linux: this bizarre buffer
swapping only happens on macOS and BSD, not on Linux.
To solve this, we switch to an unbuffered mode for cookie-based FILEs.
This avoids any stateful problems related to buffers especially when the
bailout mechanism triggers. As streams have their own buffering
mechanism, I don't expect this to impact performance.
[1] https://github.com/php/php-src/issues/11078#issuecomment-2155616843
[2] https://github.com/apple-open-source-mirror/Libc/blob/5e566be7a7047360adfb35ffc44c6a019a854bea/stdio/FreeBSD/fread.c#L102-L103
[3] https://github.com/apple-open-source-mirror/Libc/blob/5e566be7a7047360adfb35ffc44c6a019a854bea/stdio/FreeBSD/fread.c#L117
[4] https://github.com/apple-open-source-mirror/Libc/blob/5e566be7a7047360adfb35ffc44c6a019a854bea/stdio/FreeBSD/fclose.c#L66-L67
Closes GH-14524.
2024-06-09 22:18:11 +08:00
|
|
|
static ZEND_FUNCTION(zend_test_cast_fread)
|
|
|
|
{
|
|
|
|
zval *stream_zv;
|
|
|
|
php_stream *stream;
|
|
|
|
FILE *fp;
|
|
|
|
|
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
|
|
|
Z_PARAM_RESOURCE(stream_zv);
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
|
|
|
|
|
|
|
php_stream_from_zval(stream, stream_zv);
|
|
|
|
|
|
|
|
if (php_stream_cast(stream, PHP_STREAM_AS_STDIO, (void *) &fp, REPORT_ERRORS) == FAILURE) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t size = 10240; /* Must be large enough to trigger the issue */
|
|
|
|
char *buf = malloc(size);
|
|
|
|
bool bail = false;
|
|
|
|
zend_try {
|
|
|
|
(void) !fread(buf, 1, size, fp);
|
|
|
|
} zend_catch {
|
|
|
|
bail = true;
|
|
|
|
} zend_end_try();
|
|
|
|
|
|
|
|
free(buf);
|
|
|
|
|
|
|
|
if (bail) {
|
|
|
|
zend_bailout();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-06-25 21:14:00 +08:00
|
|
|
static ZEND_FUNCTION(zend_test_is_zend_ptr)
|
|
|
|
{
|
|
|
|
zend_long addr;
|
|
|
|
|
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
|
|
|
Z_PARAM_LONG(addr);
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
|
|
|
|
|
|
|
RETURN_BOOL(is_zend_ptr((void*)addr));
|
|
|
|
}
|
|
|
|
|
2021-06-12 01:25:47 +08:00
|
|
|
static zend_object *zend_test_class_new(zend_class_entry *class_type)
|
|
|
|
{
|
2017-03-11 07:33:32 +08:00
|
|
|
zend_object *obj = zend_objects_new(class_type);
|
2019-01-07 19:28:51 +08:00
|
|
|
object_properties_init(obj, class_type);
|
2017-03-11 07:33:32 +08:00
|
|
|
obj->handlers = &zend_test_class_handlers;
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
2021-06-12 01:25:47 +08:00
|
|
|
static zend_function *zend_test_class_method_get(zend_object **object, zend_string *name, const zval *key)
|
|
|
|
{
|
2021-06-29 16:04:10 +08:00
|
|
|
if (zend_string_equals_literal_ci(name, "test")) {
|
2021-05-10 18:52:59 +08:00
|
|
|
zend_internal_function *fptr;
|
|
|
|
|
|
|
|
if (EXPECTED(EG(trampoline).common.function_name == NULL)) {
|
|
|
|
fptr = (zend_internal_function *) &EG(trampoline);
|
|
|
|
} else {
|
|
|
|
fptr = emalloc(sizeof(zend_internal_function));
|
|
|
|
}
|
|
|
|
memset(fptr, 0, sizeof(zend_internal_function));
|
|
|
|
fptr->type = ZEND_INTERNAL_FUNCTION;
|
|
|
|
fptr->num_args = 1;
|
|
|
|
fptr->scope = (*object)->ce;
|
|
|
|
fptr->fn_flags = ZEND_ACC_CALL_VIA_HANDLER;
|
|
|
|
fptr->function_name = zend_string_copy(name);
|
|
|
|
fptr->handler = ZEND_FN(zend_test_func);
|
|
|
|
|
|
|
|
return (zend_function*)fptr;
|
2021-06-29 16:04:10 +08:00
|
|
|
}
|
2021-05-10 18:52:59 +08:00
|
|
|
return zend_std_get_method(object, name, key);
|
2017-03-11 07:33:32 +08:00
|
|
|
}
|
|
|
|
|
2021-06-12 01:25:47 +08:00
|
|
|
static zend_function *zend_test_class_static_method_get(zend_class_entry *ce, zend_string *name)
|
|
|
|
{
|
2019-10-25 18:47:18 +08:00
|
|
|
if (zend_string_equals_literal_ci(name, "test")) {
|
2019-10-25 18:53:24 +08:00
|
|
|
zend_internal_function *fptr;
|
|
|
|
|
|
|
|
if (EXPECTED(EG(trampoline).common.function_name == NULL)) {
|
|
|
|
fptr = (zend_internal_function *) &EG(trampoline);
|
|
|
|
} else {
|
|
|
|
fptr = emalloc(sizeof(zend_internal_function));
|
|
|
|
}
|
|
|
|
memset(fptr, 0, sizeof(zend_internal_function));
|
|
|
|
fptr->type = ZEND_INTERNAL_FUNCTION;
|
2019-10-25 18:47:18 +08:00
|
|
|
fptr->num_args = 1;
|
|
|
|
fptr->scope = ce;
|
|
|
|
fptr->fn_flags = ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_STATIC;
|
2019-10-25 18:53:24 +08:00
|
|
|
fptr->function_name = zend_string_copy(name);
|
2019-10-25 18:47:18 +08:00
|
|
|
fptr->handler = ZEND_FN(zend_test_func);
|
|
|
|
|
|
|
|
return (zend_function*)fptr;
|
2019-02-08 02:05:46 +08:00
|
|
|
}
|
2019-10-25 18:47:18 +08:00
|
|
|
return zend_std_get_static_method(ce, name, NULL);
|
2017-03-11 07:33:32 +08:00
|
|
|
}
|
|
|
|
|
2020-06-29 01:16:33 +08:00
|
|
|
void zend_attribute_validate_zendtestattribute(zend_attribute *attr, uint32_t target, zend_class_entry *scope)
|
2020-05-25 02:57:00 +08:00
|
|
|
{
|
|
|
|
if (target != ZEND_ATTRIBUTE_TARGET_CLASS) {
|
2020-08-15 16:39:00 +08:00
|
|
|
zend_error(E_COMPILE_ERROR, "Only classes can be marked with #[ZendTestAttribute]");
|
2020-05-25 02:57:00 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-12 01:25:47 +08:00
|
|
|
static ZEND_METHOD(_ZendTestClass, __toString)
|
|
|
|
{
|
2020-10-07 17:34:14 +08:00
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
2019-10-21 22:13:09 +08:00
|
|
|
RETURN_EMPTY_STRING();
|
|
|
|
}
|
|
|
|
|
2019-10-25 18:47:18 +08:00
|
|
|
/* Internal function returns bool, we return int. */
|
2021-06-12 01:25:47 +08:00
|
|
|
static ZEND_METHOD(_ZendTestClass, is_object)
|
|
|
|
{
|
2020-10-07 17:34:14 +08:00
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
2019-10-25 18:47:18 +08:00
|
|
|
RETURN_LONG(42);
|
|
|
|
}
|
|
|
|
|
2020-10-07 17:34:14 +08:00
|
|
|
static ZEND_METHOD(_ZendTestClass, returnsStatic) {
|
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
|
|
|
object_init_ex(return_value, zend_get_called_scope(execute_data));
|
|
|
|
}
|
|
|
|
|
2021-06-12 01:25:47 +08:00
|
|
|
static ZEND_METHOD(_ZendTestClass, returnsThrowable)
|
|
|
|
{
|
2021-05-10 18:52:59 +08:00
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
|
|
|
zend_throw_error(NULL, "Dummy");
|
|
|
|
}
|
|
|
|
|
2023-03-08 00:34:49 +08:00
|
|
|
static ZEND_METHOD(_ZendTestClass, variadicTest) {
|
2023-03-09 19:32:58 +08:00
|
|
|
int argc, i;
|
2023-03-08 00:34:49 +08:00
|
|
|
zval *args = NULL;
|
|
|
|
|
|
|
|
ZEND_PARSE_PARAMETERS_START(0, -1)
|
|
|
|
Z_PARAM_VARIADIC('*', args, argc)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
|
|
|
|
2023-03-09 19:32:58 +08:00
|
|
|
for (i = 0; i < argc; i++) {
|
|
|
|
zval *arg = args + i;
|
|
|
|
|
|
|
|
if (Z_TYPE_P(arg) == IS_STRING) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (Z_TYPE_P(arg) == IS_OBJECT && instanceof_function(Z_OBJ_P(arg)->ce, zend_ce_iterator)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
zend_argument_type_error(i + 1, "must be of class Iterator or a string, %s given", zend_zval_type_name(arg));
|
2023-03-09 20:20:56 +08:00
|
|
|
RETURN_THROWS();
|
2023-03-09 19:32:58 +08:00
|
|
|
}
|
2023-03-08 00:34:49 +08:00
|
|
|
|
|
|
|
object_init_ex(return_value, zend_get_called_scope(execute_data));
|
|
|
|
}
|
|
|
|
|
2021-06-12 01:25:47 +08:00
|
|
|
static ZEND_METHOD(_ZendTestChildClass, returnsThrowable)
|
|
|
|
{
|
2021-05-10 18:52:59 +08:00
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
|
|
|
zend_throw_error(NULL, "Dummy");
|
|
|
|
}
|
|
|
|
|
2022-12-27 05:47:36 +08:00
|
|
|
static ZEND_METHOD(ZendAttributeTest, testMethod)
|
|
|
|
{
|
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
|
|
|
RETURN_TRUE;
|
|
|
|
}
|
|
|
|
|
2021-06-12 01:25:47 +08:00
|
|
|
static ZEND_METHOD(_ZendTestTrait, testMethod)
|
|
|
|
{
|
2020-10-07 17:34:14 +08:00
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
2017-03-11 07:33:32 +08:00
|
|
|
RETURN_TRUE;
|
|
|
|
}
|
|
|
|
|
2021-06-12 01:25:47 +08:00
|
|
|
static ZEND_METHOD(ZendTestNS_Foo, method)
|
|
|
|
{
|
2020-10-07 18:13:52 +08:00
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
2022-07-12 21:22:49 +08:00
|
|
|
|
|
|
|
RETURN_LONG(0);
|
2020-10-07 18:13:52 +08:00
|
|
|
}
|
|
|
|
|
2022-07-28 15:28:04 +08:00
|
|
|
static ZEND_METHOD(ZendTestNS_UnlikelyCompileError, method)
|
|
|
|
{
|
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
|
|
|
|
|
|
|
RETURN_NULL();
|
|
|
|
}
|
|
|
|
|
2023-10-31 17:06:56 +08:00
|
|
|
static ZEND_METHOD(ZendTestNS_NotUnlikelyCompileError, method)
|
|
|
|
{
|
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
|
|
|
|
|
|
|
RETURN_NULL();
|
|
|
|
}
|
|
|
|
|
2021-06-12 01:25:47 +08:00
|
|
|
static ZEND_METHOD(ZendTestNS2_Foo, method)
|
|
|
|
{
|
2020-10-07 18:13:52 +08:00
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
|
|
|
}
|
|
|
|
|
2021-06-12 01:25:47 +08:00
|
|
|
static ZEND_METHOD(ZendTestNS2_ZendSubNS_Foo, method)
|
|
|
|
{
|
2021-02-03 22:57:27 +08:00
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
|
|
|
}
|
|
|
|
|
2022-02-10 02:16:57 +08:00
|
|
|
static ZEND_METHOD(ZendTestParameterAttribute, __construct)
|
|
|
|
{
|
|
|
|
zend_string *parameter;
|
|
|
|
|
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
|
|
|
Z_PARAM_STR(parameter)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
|
|
|
|
|
|
|
ZVAL_STR_COPY(OBJ_PROP_NUM(Z_OBJ_P(ZEND_THIS), 0), parameter);
|
|
|
|
}
|
|
|
|
|
2022-10-03 18:05:31 +08:00
|
|
|
static ZEND_METHOD(ZendTestPropertyAttribute, __construct)
|
|
|
|
{
|
|
|
|
zend_string *parameter;
|
|
|
|
|
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
|
|
|
Z_PARAM_STR(parameter)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
|
|
|
|
|
|
|
ZVAL_STR_COPY(OBJ_PROP_NUM(Z_OBJ_P(ZEND_THIS), 0), parameter);
|
|
|
|
}
|
|
|
|
|
2022-02-10 02:16:57 +08:00
|
|
|
static ZEND_METHOD(ZendTestClassWithMethodWithParameterAttribute, no_override)
|
|
|
|
{
|
|
|
|
zend_string *parameter;
|
|
|
|
|
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
|
|
|
Z_PARAM_STR(parameter)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
|
|
|
|
|
|
|
RETURN_LONG(2);
|
|
|
|
}
|
|
|
|
|
|
|
|
static ZEND_METHOD(ZendTestClassWithMethodWithParameterAttribute, override)
|
|
|
|
{
|
|
|
|
zend_string *parameter;
|
|
|
|
|
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
|
|
|
Z_PARAM_STR(parameter)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
|
|
|
|
|
|
|
RETURN_LONG(3);
|
|
|
|
}
|
|
|
|
|
|
|
|
static ZEND_METHOD(ZendTestChildClassWithMethodWithParameterAttribute, override)
|
|
|
|
{
|
|
|
|
zend_string *parameter;
|
|
|
|
|
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
|
|
|
Z_PARAM_STR(parameter)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
|
|
|
|
|
|
|
RETURN_LONG(4);
|
|
|
|
}
|
|
|
|
|
2022-06-16 19:02:53 +08:00
|
|
|
static ZEND_METHOD(ZendTestForbidDynamicCall, call)
|
|
|
|
{
|
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
|
|
|
|
|
|
|
zend_forbid_dynamic_call();
|
|
|
|
}
|
|
|
|
|
|
|
|
static ZEND_METHOD(ZendTestForbidDynamicCall, callStatic)
|
|
|
|
{
|
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
|
|
|
|
|
|
|
zend_forbid_dynamic_call();
|
|
|
|
}
|
|
|
|
|
2023-11-30 20:41:07 +08:00
|
|
|
static ZEND_METHOD(_ZendTestMagicCall, __call)
|
|
|
|
{
|
|
|
|
zend_string *name;
|
|
|
|
zval *arguments;
|
|
|
|
|
|
|
|
ZEND_PARSE_PARAMETERS_START(2, 2)
|
|
|
|
Z_PARAM_STR(name)
|
|
|
|
Z_PARAM_ARRAY(arguments)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
|
|
|
|
|
|
|
zval name_zv;
|
|
|
|
ZVAL_STR(&name_zv, name);
|
|
|
|
|
|
|
|
zend_string_addref(name);
|
|
|
|
Z_TRY_ADDREF_P(arguments);
|
|
|
|
RETURN_ARR(zend_new_pair(&name_zv, arguments));
|
|
|
|
}
|
|
|
|
|
2020-09-01 23:57:49 +08:00
|
|
|
PHP_INI_BEGIN()
|
2020-11-30 18:58:34 +08:00
|
|
|
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)
|
2021-01-31 18:51:13 +08:00
|
|
|
STD_PHP_INI_BOOLEAN("zend_test.register_passes", "0", PHP_INI_SYSTEM, OnUpdateBool, register_passes, zend_zend_test_globals, zend_test_globals)
|
2022-05-17 06:53:13 +08:00
|
|
|
STD_PHP_INI_BOOLEAN("zend_test.print_stderr_mshutdown", "0", PHP_INI_SYSTEM, OnUpdateBool, print_stderr_mshutdown, zend_zend_test_globals, zend_test_globals)
|
2023-02-10 20:08:44 +08:00
|
|
|
#ifdef HAVE_COPY_FILE_RANGE
|
|
|
|
STD_PHP_INI_ENTRY("zend_test.limit_copy_file_range", "-1", PHP_INI_ALL, OnUpdateLong, limit_copy_file_range, zend_zend_test_globals, zend_test_globals)
|
|
|
|
#endif
|
2022-06-17 20:12:53 +08:00
|
|
|
STD_PHP_INI_ENTRY("zend_test.quantity_value", "0", PHP_INI_ALL, OnUpdateLong, quantity_value, zend_zend_test_globals, zend_test_globals)
|
2022-08-13 22:32:25 +08:00
|
|
|
STD_PHP_INI_ENTRY("zend_test.str_test", "", PHP_INI_ALL, OnUpdateStr, str_test, zend_zend_test_globals, zend_test_globals)
|
|
|
|
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)
|
2023-11-25 07:54:02 +08:00
|
|
|
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)
|
2020-09-01 23:57:49 +08:00
|
|
|
PHP_INI_END()
|
|
|
|
|
2020-11-30 18:58:34 +08:00
|
|
|
void (*old_zend_execute_ex)(zend_execute_data *execute_data);
|
|
|
|
static void custom_zend_execute_ex(zend_execute_data *execute_data)
|
|
|
|
{
|
|
|
|
old_zend_execute_ex(execute_data);
|
|
|
|
}
|
|
|
|
|
2023-03-22 03:41:18 +08:00
|
|
|
static void le_throwing_resource_dtor(zend_resource *rsrc)
|
|
|
|
{
|
|
|
|
zend_throw_exception(NULL, "Throwing resource destructor called", 0);
|
|
|
|
}
|
|
|
|
|
2023-08-19 07:11:06 +08:00
|
|
|
static ZEND_METHOD(_ZendTestClass, takesUnionType)
|
|
|
|
{
|
|
|
|
zend_object *obj;
|
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 1);
|
|
|
|
Z_PARAM_OBJ(obj)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
|
|
|
// we have to perform type-checking to avoid arginfo/zpp mismatch error
|
|
|
|
bool type_matches = (
|
|
|
|
instanceof_function(obj->ce, zend_standard_class_def)
|
|
|
|
||
|
|
|
|
instanceof_function(obj->ce, zend_ce_iterator)
|
|
|
|
);
|
|
|
|
if (!type_matches) {
|
|
|
|
zend_string *ty = zend_type_to_string(execute_data->func->internal_function.arg_info->type);
|
|
|
|
zend_argument_type_error(1, "must be of type %s, %s given", ty->val, obj->ce->name->val);
|
|
|
|
zend_string_release(ty);
|
|
|
|
RETURN_THROWS();
|
|
|
|
}
|
|
|
|
|
|
|
|
RETURN_NULL();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Returns a newly allocated DNF type `Iterator|(Traversable&Countable)`.
|
|
|
|
//
|
|
|
|
// We need to generate it "manually" because gen_stubs.php does not support codegen for DNF types ATM.
|
|
|
|
static zend_type create_test_dnf_type(void) {
|
|
|
|
zend_string *class_Iterator = zend_string_init_interned("Iterator", sizeof("Iterator") - 1, true);
|
|
|
|
zend_alloc_ce_cache(class_Iterator);
|
|
|
|
zend_string *class_Traversable = ZSTR_KNOWN(ZEND_STR_TRAVERSABLE);
|
|
|
|
zend_string *class_Countable = zend_string_init_interned("Countable", sizeof("Countable") - 1, true);
|
|
|
|
zend_alloc_ce_cache(class_Countable);
|
|
|
|
//
|
|
|
|
zend_type_list *intersection_list = malloc(ZEND_TYPE_LIST_SIZE(2));
|
|
|
|
intersection_list->num_types = 2;
|
|
|
|
intersection_list->types[0] = (zend_type) ZEND_TYPE_INIT_CLASS(class_Traversable, 0, 0);
|
|
|
|
intersection_list->types[1] = (zend_type) ZEND_TYPE_INIT_CLASS(class_Countable, 0, 0);
|
|
|
|
zend_type_list *union_list = malloc(ZEND_TYPE_LIST_SIZE(2));
|
|
|
|
union_list->num_types = 2;
|
|
|
|
union_list->types[0] = (zend_type) ZEND_TYPE_INIT_CLASS(class_Iterator, 0, 0);
|
|
|
|
union_list->types[1] = (zend_type) ZEND_TYPE_INIT_INTERSECTION(intersection_list, 0);
|
|
|
|
return (zend_type) ZEND_TYPE_INIT_UNION(union_list, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void register_ZendTestClass_dnf_property(zend_class_entry *ce) {
|
|
|
|
zend_string *prop_name = zend_string_init_interned("dnfProperty", sizeof("dnfProperty") - 1, true);
|
|
|
|
zval default_value;
|
|
|
|
ZVAL_UNDEF(&default_value);
|
|
|
|
zend_type type = create_test_dnf_type();
|
|
|
|
zend_declare_typed_property(ce, prop_name, &default_value, ZEND_ACC_PUBLIC, NULL, type);
|
|
|
|
}
|
|
|
|
|
|
|
|
// arg_info for `zend_test_internal_dnf_arguments`
|
|
|
|
// The types are upgraded to DNF types in `register_dynamic_function_entries()`
|
|
|
|
static zend_internal_arg_info arginfo_zend_test_internal_dnf_arguments[] = {
|
|
|
|
// first entry is a zend_internal_function_info (see zend_compile.h): {argument_count, return_type, unused}
|
|
|
|
{(const char*)(uintptr_t)(1), {0}, NULL},
|
|
|
|
{"arg", {0}, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static ZEND_NAMED_FUNCTION(zend_test_internal_dnf_arguments)
|
|
|
|
{
|
|
|
|
zend_object *obj;
|
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 1);
|
|
|
|
Z_PARAM_OBJ(obj)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
|
|
|
// we have to perform type-checking to avoid arginfo/zpp mismatch error
|
|
|
|
bool type_matches = (
|
|
|
|
instanceof_function(obj->ce, zend_ce_iterator)
|
|
|
|
|| (
|
|
|
|
instanceof_function(obj->ce, zend_ce_traversable)
|
|
|
|
&& instanceof_function(obj->ce, zend_ce_countable)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
if (!type_matches) {
|
|
|
|
zend_string *ty = zend_type_to_string(arginfo_zend_test_internal_dnf_arguments[1].type);
|
|
|
|
zend_argument_type_error(1, "must be of type %s, %s given", ty->val, obj->ce->name->val);
|
|
|
|
zend_string_release(ty);
|
|
|
|
RETURN_THROWS();
|
|
|
|
}
|
|
|
|
|
|
|
|
RETURN_OBJ_COPY(obj);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const zend_function_entry dynamic_function_entries[] = {
|
|
|
|
{
|
|
|
|
.fname = "zend_test_internal_dnf_arguments",
|
|
|
|
.handler = zend_test_internal_dnf_arguments,
|
|
|
|
.arg_info = arginfo_zend_test_internal_dnf_arguments,
|
|
|
|
.num_args = 1,
|
|
|
|
.flags = 0,
|
|
|
|
},
|
|
|
|
ZEND_FE_END,
|
|
|
|
};
|
|
|
|
|
|
|
|
static void register_dynamic_function_entries(int module_type) {
|
|
|
|
// return-type is at index 0
|
|
|
|
arginfo_zend_test_internal_dnf_arguments[0].type = create_test_dnf_type();
|
|
|
|
arginfo_zend_test_internal_dnf_arguments[1].type = create_test_dnf_type();
|
|
|
|
//
|
|
|
|
zend_register_functions(NULL, dynamic_function_entries, NULL, module_type);
|
|
|
|
}
|
|
|
|
|
2017-03-11 07:33:32 +08:00
|
|
|
PHP_MINIT_FUNCTION(zend_test)
|
|
|
|
{
|
2023-08-19 07:11:06 +08:00
|
|
|
register_dynamic_function_entries(type);
|
|
|
|
|
2021-01-26 18:50:36 +08:00
|
|
|
zend_test_interface = register_class__ZendTestInterface();
|
|
|
|
|
|
|
|
zend_test_class = register_class__ZendTestClass(zend_test_interface);
|
2023-08-19 07:11:06 +08:00
|
|
|
register_ZendTestClass_dnf_property(zend_test_class);
|
2017-03-11 07:33:32 +08:00
|
|
|
zend_test_class->create_object = zend_test_class_new;
|
|
|
|
zend_test_class->get_static_method = zend_test_class_static_method_get;
|
|
|
|
|
2021-01-26 18:50:36 +08:00
|
|
|
zend_test_child_class = register_class__ZendTestChildClass(zend_test_class);
|
2018-06-27 16:49:05 +08:00
|
|
|
|
2018-05-31 16:57:22 +08:00
|
|
|
memcpy(&zend_test_class_handlers, &std_object_handlers, sizeof(zend_object_handlers));
|
2017-03-11 07:33:32 +08:00
|
|
|
zend_test_class_handlers.get_method = zend_test_class_method_get;
|
|
|
|
|
2022-12-27 05:47:36 +08:00
|
|
|
zend_attribute_test_class = register_class_ZendAttributeTest();
|
|
|
|
|
2021-01-26 18:50:36 +08:00
|
|
|
zend_test_trait = register_class__ZendTestTrait();
|
2020-01-10 18:34:05 +08:00
|
|
|
|
2022-07-26 02:55:58 +08:00
|
|
|
register_test_symbols(module_number);
|
2020-05-25 02:57:00 +08:00
|
|
|
|
2021-01-26 18:50:36 +08:00
|
|
|
zend_test_attribute = register_class_ZendTestAttribute();
|
2020-06-29 01:16:33 +08:00
|
|
|
{
|
2022-07-06 00:22:33 +08:00
|
|
|
zend_internal_attribute *attr = zend_mark_internal_attribute(zend_test_attribute);
|
2020-06-29 01:16:33 +08:00
|
|
|
attr->validator = zend_attribute_validate_zendtestattribute;
|
|
|
|
}
|
|
|
|
|
2022-12-27 05:47:36 +08:00
|
|
|
zend_test_repeatable_attribute = register_class_ZendTestRepeatableAttribute();
|
|
|
|
zend_mark_internal_attribute(zend_test_repeatable_attribute);
|
|
|
|
|
2022-02-10 02:16:57 +08:00
|
|
|
zend_test_parameter_attribute = register_class_ZendTestParameterAttribute();
|
2022-07-06 00:22:33 +08:00
|
|
|
zend_mark_internal_attribute(zend_test_parameter_attribute);
|
2022-02-10 02:16:57 +08:00
|
|
|
|
2022-10-03 18:05:31 +08:00
|
|
|
zend_test_property_attribute = register_class_ZendTestPropertyAttribute();
|
|
|
|
zend_mark_internal_attribute(zend_test_property_attribute);
|
|
|
|
|
2022-02-10 02:16:57 +08:00
|
|
|
zend_test_class_with_method_with_parameter_attribute = register_class_ZendTestClassWithMethodWithParameterAttribute();
|
|
|
|
zend_test_child_class_with_method_with_parameter_attribute = register_class_ZendTestChildClassWithMethodWithParameterAttribute(zend_test_class_with_method_with_parameter_attribute);
|
|
|
|
|
2023-08-24 22:07:00 +08:00
|
|
|
zend_test_class_with_property_attribute = register_class_ZendTestClassWithPropertyAttribute();
|
|
|
|
{
|
|
|
|
zend_property_info *prop_info = zend_hash_str_find_ptr(&zend_test_class_with_property_attribute->properties_info, "attributed", sizeof("attributed") - 1);
|
|
|
|
zend_add_property_attribute(zend_test_class_with_property_attribute, prop_info, zend_test_attribute->name, 0);
|
|
|
|
}
|
|
|
|
|
2022-06-16 19:02:53 +08:00
|
|
|
zend_test_forbid_dynamic_call = register_class_ZendTestForbidDynamicCall();
|
|
|
|
|
2021-02-16 05:14:36 +08:00
|
|
|
zend_test_ns_foo_class = register_class_ZendTestNS_Foo();
|
2022-07-28 15:28:04 +08:00
|
|
|
zend_test_ns_unlikely_compile_error_class = register_class_ZendTestNS_UnlikelyCompileError();
|
2023-10-31 17:06:56 +08:00
|
|
|
zend_test_ns_not_unlikely_compile_error_class = register_class_ZendTestNS_NotUnlikelyCompileError();
|
2021-02-16 05:14:36 +08:00
|
|
|
zend_test_ns2_foo_class = register_class_ZendTestNS2_Foo();
|
|
|
|
zend_test_ns2_ns_foo_class = register_class_ZendTestNS2_ZendSubNS_Foo();
|
|
|
|
|
2021-08-31 17:36:50 +08:00
|
|
|
zend_test_unit_enum = register_class_ZendTestUnitEnum();
|
|
|
|
zend_test_string_enum = register_class_ZendTestStringEnum();
|
2022-05-09 06:10:12 +08:00
|
|
|
zend_test_int_enum = register_class_ZendTestIntEnum();
|
2021-07-22 21:13:38 +08:00
|
|
|
|
2023-11-30 20:41:07 +08:00
|
|
|
zend_test_magic_call = register_class__ZendTestMagicCall();
|
2021-07-22 21:13:38 +08:00
|
|
|
|
2022-06-07 20:35:34 +08:00
|
|
|
zend_register_functions(NULL, ext_function_legacy, NULL, EG(current_module)->type);
|
|
|
|
|
2020-09-01 23:57:49 +08:00
|
|
|
// Loading via dl() not supported with the observer API
|
|
|
|
if (type != MODULE_TEMPORARY) {
|
|
|
|
REGISTER_INI_ENTRIES();
|
|
|
|
} else {
|
|
|
|
(void)ini_entries;
|
|
|
|
}
|
|
|
|
|
2020-11-30 18:58:34 +08:00
|
|
|
if (ZT_G(replace_zend_execute_ex)) {
|
|
|
|
old_zend_execute_ex = zend_execute_ex;
|
|
|
|
zend_execute_ex = custom_zend_execute_ex;
|
|
|
|
}
|
|
|
|
|
2021-01-31 18:51:13 +08:00
|
|
|
if (ZT_G(register_passes)) {
|
|
|
|
zend_optimizer_register_pass(pass1);
|
|
|
|
zend_optimizer_register_pass(pass2);
|
|
|
|
}
|
|
|
|
|
2021-06-12 01:25:47 +08:00
|
|
|
zend_test_observer_init(INIT_FUNC_ARGS_PASSTHRU);
|
|
|
|
zend_test_fiber_init();
|
2023-08-28 00:06:10 +08:00
|
|
|
zend_test_iterators_init();
|
2023-08-03 01:52:55 +08:00
|
|
|
zend_test_object_handlers_init();
|
2021-06-12 01:25:47 +08:00
|
|
|
|
2023-03-22 03:41:18 +08:00
|
|
|
le_throwing_resource = zend_register_list_destructors_ex(le_throwing_resource_dtor, NULL, "throwing resource", module_number);
|
|
|
|
|
2017-03-11 07:33:32 +08:00
|
|
|
return SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
PHP_MSHUTDOWN_FUNCTION(zend_test)
|
|
|
|
{
|
2020-09-01 23:57:49 +08:00
|
|
|
if (type != MODULE_TEMPORARY) {
|
|
|
|
UNREGISTER_INI_ENTRIES();
|
|
|
|
}
|
|
|
|
|
2021-06-12 01:25:47 +08:00
|
|
|
zend_test_observer_shutdown(SHUTDOWN_FUNC_ARGS_PASSTHRU);
|
2017-03-11 07:33:32 +08:00
|
|
|
|
2022-05-17 06:53:13 +08:00
|
|
|
if (ZT_G(print_stderr_mshutdown)) {
|
|
|
|
fprintf(stderr, "[zend-test] MSHUTDOWN\n");
|
|
|
|
}
|
|
|
|
|
2021-06-12 01:25:47 +08:00
|
|
|
return SUCCESS;
|
2020-09-01 23:57:49 +08:00
|
|
|
}
|
|
|
|
|
2017-03-11 07:33:32 +08:00
|
|
|
PHP_RINIT_FUNCTION(zend_test)
|
|
|
|
{
|
2021-10-21 19:34:22 +08:00
|
|
|
zend_hash_init(&ZT_G(global_weakmap), 8, NULL, ZVAL_PTR_DTOR, 0);
|
2022-07-29 19:32:48 +08:00
|
|
|
ZT_G(observer_nesting_depth) = 0;
|
2017-03-11 07:33:32 +08:00
|
|
|
return SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
PHP_RSHUTDOWN_FUNCTION(zend_test)
|
|
|
|
{
|
2021-11-28 08:52:30 +08:00
|
|
|
zend_ulong obj_key;
|
|
|
|
ZEND_HASH_FOREACH_NUM_KEY(&ZT_G(global_weakmap), obj_key) {
|
|
|
|
zend_weakrefs_hash_del(&ZT_G(global_weakmap), zend_weakref_key_to_object(obj_key));
|
2021-10-21 19:34:22 +08:00
|
|
|
} ZEND_HASH_FOREACH_END();
|
|
|
|
zend_hash_destroy(&ZT_G(global_weakmap));
|
2023-11-25 07:54:02 +08:00
|
|
|
|
|
|
|
if (ZT_G(zend_test_heap)) {
|
|
|
|
free(ZT_G(zend_test_heap));
|
|
|
|
ZT_G(zend_test_heap) = NULL;
|
|
|
|
zend_mm_set_heap(ZT_G(zend_orig_heap));
|
|
|
|
}
|
|
|
|
|
2017-03-11 07:33:32 +08:00
|
|
|
return SUCCESS;
|
|
|
|
}
|
|
|
|
|
2020-09-01 23:57:49 +08:00
|
|
|
static PHP_GINIT_FUNCTION(zend_test)
|
|
|
|
{
|
|
|
|
#if defined(COMPILE_DL_ZEND_TEST) && defined(ZTS)
|
|
|
|
ZEND_TSRMLS_CACHE_UPDATE();
|
|
|
|
#endif
|
|
|
|
memset(zend_test_globals, 0, sizeof(*zend_test_globals));
|
2022-07-30 23:57:00 +08:00
|
|
|
|
|
|
|
zend_test_observer_ginit(zend_test_globals);
|
|
|
|
}
|
|
|
|
|
|
|
|
static PHP_GSHUTDOWN_FUNCTION(zend_test)
|
|
|
|
{
|
|
|
|
zend_test_observer_gshutdown(zend_test_globals);
|
2020-09-01 23:57:49 +08:00
|
|
|
}
|
|
|
|
|
2017-03-11 07:33:32 +08:00
|
|
|
PHP_MINFO_FUNCTION(zend_test)
|
|
|
|
{
|
|
|
|
php_info_print_table_start();
|
2022-09-06 14:48:22 +08:00
|
|
|
php_info_print_table_row(2, "zend_test extension", "enabled");
|
2017-03-11 07:33:32 +08:00
|
|
|
php_info_print_table_end();
|
2020-09-01 23:57:49 +08:00
|
|
|
|
|
|
|
DISPLAY_INI_ENTRIES();
|
2017-03-11 07:33:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
zend_module_entry zend_test_module_entry = {
|
|
|
|
STANDARD_MODULE_HEADER,
|
2021-01-18 17:55:29 +08:00
|
|
|
"zend_test",
|
2020-04-05 03:26:46 +08:00
|
|
|
ext_functions,
|
2017-03-11 07:33:32 +08:00
|
|
|
PHP_MINIT(zend_test),
|
|
|
|
PHP_MSHUTDOWN(zend_test),
|
|
|
|
PHP_RINIT(zend_test),
|
|
|
|
PHP_RSHUTDOWN(zend_test),
|
|
|
|
PHP_MINFO(zend_test),
|
|
|
|
PHP_ZEND_TEST_VERSION,
|
2020-09-01 23:57:49 +08:00
|
|
|
PHP_MODULE_GLOBALS(zend_test),
|
|
|
|
PHP_GINIT(zend_test),
|
2022-07-30 23:57:00 +08:00
|
|
|
PHP_GSHUTDOWN(zend_test),
|
2020-09-01 23:57:49 +08:00
|
|
|
NULL,
|
|
|
|
STANDARD_MODULE_PROPERTIES_EX
|
2017-03-11 07:33:32 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
#ifdef COMPILE_DL_ZEND_TEST
|
2021-06-12 01:25:47 +08:00
|
|
|
# ifdef ZTS
|
2017-03-11 07:33:32 +08:00
|
|
|
ZEND_TSRMLS_CACHE_DEFINE()
|
2021-06-12 01:25:47 +08:00
|
|
|
# endif
|
2017-03-15 18:43:20 +08:00
|
|
|
ZEND_GET_MODULE(zend_test)
|
2017-03-11 07:33:32 +08:00
|
|
|
#endif
|
2020-01-12 21:01:42 +08:00
|
|
|
|
2021-07-13 15:22:31 +08:00
|
|
|
/* The important part here is the ZEND_FASTCALL. */
|
|
|
|
PHP_ZEND_TEST_API int ZEND_FASTCALL bug78270(const char *str, size_t str_len)
|
|
|
|
{
|
2022-06-17 20:12:53 +08:00
|
|
|
char * copy = zend_strndup(str, str_len);
|
|
|
|
int r = (int) ZEND_ATOL(copy);
|
|
|
|
free(copy);
|
|
|
|
return r;
|
2021-07-13 15:22:31 +08:00
|
|
|
}
|
|
|
|
|
2020-05-27 15:58:10 +08:00
|
|
|
PHP_ZEND_TEST_API struct bug79096 bug79096(void)
|
2020-01-12 21:01:42 +08:00
|
|
|
{
|
2021-06-29 16:04:10 +08:00
|
|
|
struct bug79096 b;
|
2020-01-12 21:01:42 +08:00
|
|
|
|
2021-06-29 16:04:10 +08:00
|
|
|
b.a = 1;
|
|
|
|
b.b = 1;
|
|
|
|
return b;
|
2020-01-12 21:01:42 +08:00
|
|
|
}
|
2020-04-29 00:33:19 +08:00
|
|
|
|
2020-05-27 15:58:10 +08:00
|
|
|
PHP_ZEND_TEST_API void bug79532(off_t *array, size_t elems)
|
2020-04-29 00:33:19 +08:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < elems; i++) {
|
|
|
|
array[i] = i;
|
|
|
|
}
|
|
|
|
}
|
2020-10-30 19:44:37 +08:00
|
|
|
|
|
|
|
PHP_ZEND_TEST_API int *(*bug79177_cb)(void);
|
|
|
|
void bug79177(void)
|
|
|
|
{
|
|
|
|
bug79177_cb();
|
|
|
|
}
|
2021-03-17 14:55:20 +08:00
|
|
|
|
|
|
|
typedef struct bug80847_01 {
|
|
|
|
uint64_t b;
|
|
|
|
double c;
|
|
|
|
} bug80847_01;
|
|
|
|
typedef struct bug80847_02 {
|
|
|
|
bug80847_01 a;
|
|
|
|
} bug80847_02;
|
|
|
|
|
|
|
|
PHP_ZEND_TEST_API bug80847_02 ffi_bug80847(bug80847_02 s) {
|
|
|
|
s.a.b += 10;
|
|
|
|
s.a.c -= 10.0;
|
2021-06-29 16:04:10 +08:00
|
|
|
return s;
|
2021-03-17 14:55:20 +08:00
|
|
|
}
|
2022-07-23 07:09:25 +08:00
|
|
|
|
|
|
|
PHP_ZEND_TEST_API void (*bug_gh9090_void_none_ptr)(void) = NULL;
|
|
|
|
PHP_ZEND_TEST_API void (*bug_gh9090_void_int_char_ptr)(int, char *) = NULL;
|
|
|
|
PHP_ZEND_TEST_API void (*bug_gh9090_void_int_char_var_ptr)(int, char *, ...) = NULL;
|
|
|
|
PHP_ZEND_TEST_API void (*bug_gh9090_void_char_int_ptr)(char *, int) = NULL;
|
|
|
|
PHP_ZEND_TEST_API int (*bug_gh9090_int_int_char_ptr)(int, char *) = NULL;
|
|
|
|
|
|
|
|
PHP_ZEND_TEST_API void bug_gh9090_void_none(void) {
|
|
|
|
php_printf("bug_gh9090_none\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
PHP_ZEND_TEST_API void bug_gh9090_void_int_char(int i, char *s) {
|
|
|
|
php_printf("bug_gh9090_int_char %d %s\n", i, s);
|
|
|
|
}
|
|
|
|
|
|
|
|
PHP_ZEND_TEST_API void bug_gh9090_void_int_char_var(int i, char *fmt, ...) {
|
|
|
|
va_list args;
|
|
|
|
char *buffer;
|
|
|
|
|
|
|
|
va_start(args, fmt);
|
|
|
|
|
|
|
|
zend_vspprintf(&buffer, 0, fmt, args);
|
|
|
|
php_printf("bug_gh9090_void_int_char_var %s\n", buffer);
|
|
|
|
efree(buffer);
|
|
|
|
|
|
|
|
va_end(args);
|
|
|
|
}
|
2023-02-10 20:08:44 +08:00
|
|
|
|
2023-08-11 06:51:48 +08:00
|
|
|
PHP_ZEND_TEST_API int gh11934b_ffi_var_test_cdata;
|
|
|
|
|
2023-02-10 20:08:44 +08:00
|
|
|
#ifdef HAVE_COPY_FILE_RANGE
|
|
|
|
/**
|
|
|
|
* This function allows us to simulate early return of copy_file_range by setting the limit_copy_file_range ini setting.
|
|
|
|
*/
|
2024-03-14 16:02:29 +08:00
|
|
|
#ifdef __MUSL__
|
|
|
|
typedef off_t off64_t;
|
|
|
|
#endif
|
|
|
|
PHP_ZEND_TEST_API ssize_t copy_file_range(int fd_in, off64_t *off_in, int fd_out, off64_t *off_out, size_t len, unsigned int flags)
|
2023-02-10 20:08:44 +08:00
|
|
|
{
|
2024-03-14 16:02:29 +08:00
|
|
|
ssize_t (*original_copy_file_range)(int, off64_t *, int, off64_t *, size_t, unsigned int) = dlsym(RTLD_NEXT, "copy_file_range");
|
2023-02-10 20:08:44 +08:00
|
|
|
if (ZT_G(limit_copy_file_range) >= Z_L(0)) {
|
|
|
|
len = ZT_G(limit_copy_file_range);
|
|
|
|
}
|
|
|
|
return original_copy_file_range(fd_in, off_in, fd_out, off_out, len, flags);
|
|
|
|
}
|
|
|
|
#endif
|
2023-03-22 03:41:18 +08:00
|
|
|
|
|
|
|
|
|
|
|
static PHP_FUNCTION(zend_test_create_throwing_resource)
|
|
|
|
{
|
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
|
|
|
zend_resource *res = zend_register_resource(NULL, le_throwing_resource);
|
|
|
|
ZVAL_RES(return_value, res);
|
|
|
|
}
|