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: |
|
|
|
|
| http://www.php.net/license/3_01.txt |
|
|
|
|
| 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
|
|
|
|
#include "config.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "php.h"
|
|
|
|
#include "php_ini.h"
|
|
|
|
#include "ext/standard/info.h"
|
2020-09-01 23:57:49 +08:00
|
|
|
#include "ext/standard/php_var.h"
|
2017-03-11 07:33:32 +08:00
|
|
|
#include "php_test.h"
|
2020-02-13 23:37:49 +08:00
|
|
|
#include "test_arginfo.h"
|
2020-05-25 02:57:00 +08:00
|
|
|
#include "zend_attributes.h"
|
2020-09-01 23:57:49 +08:00
|
|
|
#include "zend_observer.h"
|
|
|
|
#include "zend_smart_str.h"
|
|
|
|
|
|
|
|
ZEND_BEGIN_MODULE_GLOBALS(zend_test)
|
|
|
|
int observer_enabled;
|
|
|
|
int observer_show_output;
|
|
|
|
int observer_observe_all;
|
|
|
|
int observer_observe_includes;
|
|
|
|
int observer_observe_functions;
|
|
|
|
int observer_show_return_type;
|
|
|
|
int observer_show_return_value;
|
2020-09-25 03:57:43 +08:00
|
|
|
int observer_show_init_backtrace;
|
2020-11-11 18:06:55 +08:00
|
|
|
int observer_show_opcode;
|
2020-09-01 23:57:49 +08:00
|
|
|
int observer_nesting_depth;
|
2020-11-30 18:58:34 +08:00
|
|
|
int replace_zend_execute_ex;
|
2020-09-01 23:57:49 +08:00
|
|
|
ZEND_END_MODULE_GLOBALS(zend_test)
|
|
|
|
|
|
|
|
ZEND_DECLARE_MODULE_GLOBALS(zend_test)
|
|
|
|
|
|
|
|
#define ZT_G(v) ZEND_MODULE_GLOBALS_ACCESSOR(zend_test, v)
|
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;
|
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;
|
2017-03-11 07:33:32 +08:00
|
|
|
static zend_object_handlers zend_test_class_handlers;
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
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';
|
|
|
|
}
|
|
|
|
|
2020-07-01 21:32:55 +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);
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 21:32:55 +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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
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();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
2021-02-07 03:13:22 +08:00
|
|
|
static ZEND_FUNCTION(namespaced_func)
|
|
|
|
{
|
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
|
|
|
RETURN_TRUE;
|
|
|
|
}
|
|
|
|
|
2017-03-11 07:33:32 +08:00
|
|
|
static zend_object *zend_test_class_new(zend_class_entry *class_type) /* {{{ */ {
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
|
|
|
static zend_function *zend_test_class_method_get(zend_object **object, zend_string *name, const zval *key) /* {{{ */ {
|
2019-02-08 02:05:46 +08:00
|
|
|
zend_internal_function *fptr;
|
|
|
|
|
|
|
|
if (EXPECTED(EG(trampoline).common.function_name == NULL)) {
|
2019-04-11 17:20:52 +08:00
|
|
|
fptr = (zend_internal_function *) &EG(trampoline);
|
2019-02-08 02:05:46 +08:00
|
|
|
} else {
|
|
|
|
fptr = emalloc(sizeof(zend_internal_function));
|
|
|
|
}
|
|
|
|
memset(fptr, 0, sizeof(zend_internal_function));
|
|
|
|
fptr->type = ZEND_INTERNAL_FUNCTION;
|
2017-03-11 07:33:32 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
|
|
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-07 17:34:14 +08:00
|
|
|
static ZEND_METHOD(_ZendTestClass, __toString) {
|
|
|
|
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. */
|
2020-10-07 17:34:14 +08:00
|
|
|
static ZEND_METHOD(_ZendTestClass, is_object) {
|
|
|
|
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));
|
|
|
|
}
|
|
|
|
|
|
|
|
static ZEND_METHOD(_ZendTestTrait, testMethod) {
|
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
2017-03-11 07:33:32 +08:00
|
|
|
RETURN_TRUE;
|
|
|
|
}
|
|
|
|
|
2020-10-07 18:13:52 +08:00
|
|
|
static ZEND_METHOD(ZendTestNS_Foo, method) {
|
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
|
|
|
}
|
|
|
|
|
|
|
|
static ZEND_METHOD(ZendTestNS2_Foo, method) {
|
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
|
|
|
}
|
|
|
|
|
2020-09-01 23:57:49 +08:00
|
|
|
PHP_INI_BEGIN()
|
|
|
|
STD_PHP_INI_BOOLEAN("zend_test.observer.enabled", "0", PHP_INI_SYSTEM, OnUpdateBool, observer_enabled, zend_zend_test_globals, zend_test_globals)
|
|
|
|
STD_PHP_INI_BOOLEAN("zend_test.observer.show_output", "1", PHP_INI_SYSTEM, OnUpdateBool, observer_show_output, zend_zend_test_globals, zend_test_globals)
|
|
|
|
STD_PHP_INI_BOOLEAN("zend_test.observer.observe_all", "0", PHP_INI_SYSTEM, OnUpdateBool, observer_observe_all, zend_zend_test_globals, zend_test_globals)
|
|
|
|
STD_PHP_INI_BOOLEAN("zend_test.observer.observe_includes", "0", PHP_INI_SYSTEM, OnUpdateBool, observer_observe_includes, zend_zend_test_globals, zend_test_globals)
|
|
|
|
STD_PHP_INI_BOOLEAN("zend_test.observer.observe_functions", "0", PHP_INI_SYSTEM, OnUpdateBool, observer_observe_functions, zend_zend_test_globals, zend_test_globals)
|
|
|
|
STD_PHP_INI_BOOLEAN("zend_test.observer.show_return_type", "0", PHP_INI_SYSTEM, OnUpdateBool, observer_show_return_type, zend_zend_test_globals, zend_test_globals)
|
|
|
|
STD_PHP_INI_BOOLEAN("zend_test.observer.show_return_value", "0", PHP_INI_SYSTEM, OnUpdateBool, observer_show_return_value, zend_zend_test_globals, zend_test_globals)
|
2020-09-25 03:57:43 +08:00
|
|
|
STD_PHP_INI_BOOLEAN("zend_test.observer.show_init_backtrace", "0", PHP_INI_SYSTEM, OnUpdateBool, observer_show_init_backtrace, zend_zend_test_globals, zend_test_globals)
|
2020-11-11 18:06:55 +08:00
|
|
|
STD_PHP_INI_BOOLEAN("zend_test.observer.show_opcode", "0", PHP_INI_SYSTEM, OnUpdateBool, observer_show_opcode, zend_zend_test_globals, zend_test_globals)
|
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)
|
2020-09-01 23:57:49 +08:00
|
|
|
PHP_INI_END()
|
|
|
|
|
2020-09-25 03:57:43 +08:00
|
|
|
static zend_observer_fcall_handlers observer_fcall_init(zend_execute_data *execute_data);
|
2020-09-01 23:57:49 +08:00
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2017-03-11 07:33:32 +08:00
|
|
|
PHP_MINIT_FUNCTION(zend_test)
|
|
|
|
{
|
|
|
|
zend_class_entry class_entry;
|
|
|
|
|
|
|
|
INIT_CLASS_ENTRY(class_entry, "_ZendTestInterface", NULL);
|
|
|
|
zend_test_interface = zend_register_internal_interface(&class_entry);
|
|
|
|
zend_declare_class_constant_long(zend_test_interface, ZEND_STRL("DUMMY"), 0);
|
2020-04-11 19:27:04 +08:00
|
|
|
INIT_CLASS_ENTRY(class_entry, "_ZendTestClass", class__ZendTestClass_methods);
|
2019-10-21 22:13:09 +08:00
|
|
|
zend_test_class = zend_register_internal_class(&class_entry);
|
2017-03-11 07:33:32 +08:00
|
|
|
zend_class_implements(zend_test_class, 1, zend_test_interface);
|
|
|
|
zend_test_class->create_object = zend_test_class_new;
|
|
|
|
zend_test_class->get_static_method = zend_test_class_static_method_get;
|
|
|
|
|
2018-06-27 16:49:05 +08:00
|
|
|
zend_declare_property_null(zend_test_class, "_StaticProp", sizeof("_StaticProp") - 1, ZEND_ACC_STATIC);
|
|
|
|
|
2019-01-07 19:28:51 +08:00
|
|
|
{
|
2019-04-18 19:48:38 +08:00
|
|
|
zend_string *name = zend_string_init("intProp", sizeof("intProp") - 1, 1);
|
2019-01-07 19:28:51 +08:00
|
|
|
zval val;
|
|
|
|
ZVAL_LONG(&val, 123);
|
|
|
|
zend_declare_typed_property(
|
2019-09-20 23:01:19 +08:00
|
|
|
zend_test_class, name, &val, ZEND_ACC_PUBLIC, NULL,
|
|
|
|
(zend_type) ZEND_TYPE_INIT_CODE(IS_LONG, 0, 0));
|
2019-01-07 19:28:51 +08:00
|
|
|
zend_string_release(name);
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
2019-04-18 19:48:38 +08:00
|
|
|
zend_string *name = zend_string_init("classProp", sizeof("classProp") - 1, 1);
|
2019-01-07 19:28:51 +08:00
|
|
|
zend_string *class_name = zend_string_init("stdClass", sizeof("stdClass") - 1, 1);
|
|
|
|
zval val;
|
|
|
|
ZVAL_NULL(&val);
|
|
|
|
zend_declare_typed_property(
|
|
|
|
zend_test_class, name, &val, ZEND_ACC_PUBLIC, NULL,
|
2019-09-20 23:01:19 +08:00
|
|
|
(zend_type) ZEND_TYPE_INIT_CLASS(class_name, 1, 0));
|
2019-01-07 19:28:51 +08:00
|
|
|
zend_string_release(name);
|
|
|
|
}
|
|
|
|
|
2019-09-25 19:21:13 +08:00
|
|
|
{
|
|
|
|
zend_string *name = zend_string_init("classUnionProp", sizeof("classUnionProp") - 1, 1);
|
|
|
|
zend_string *class_name1 = zend_string_init("stdClass", sizeof("stdClass") - 1, 1);
|
|
|
|
zend_string *class_name2 = zend_string_init("Iterator", sizeof("Iterator") - 1, 1);
|
|
|
|
zend_type_list *type_list = malloc(ZEND_TYPE_LIST_SIZE(2));
|
|
|
|
type_list->num_types = 2;
|
2020-01-17 00:04:11 +08:00
|
|
|
type_list->types[0] = (zend_type) ZEND_TYPE_INIT_CLASS(class_name1, 0, 0);
|
|
|
|
type_list->types[1] = (zend_type) ZEND_TYPE_INIT_CLASS(class_name2, 0, 0);
|
2019-09-25 19:21:13 +08:00
|
|
|
zend_type type = ZEND_TYPE_INIT_PTR(type_list, _ZEND_TYPE_LIST_BIT, 1, 0);
|
|
|
|
zval val;
|
|
|
|
ZVAL_NULL(&val);
|
|
|
|
zend_declare_typed_property(zend_test_class, name, &val, ZEND_ACC_PUBLIC, NULL, type);
|
|
|
|
zend_string_release(name);
|
|
|
|
}
|
|
|
|
|
2019-01-07 19:28:51 +08:00
|
|
|
{
|
2019-04-18 19:48:38 +08:00
|
|
|
zend_string *name = zend_string_init("staticIntProp", sizeof("staticIntProp") - 1, 1);
|
2019-01-07 19:28:51 +08:00
|
|
|
zval val;
|
|
|
|
ZVAL_LONG(&val, 123);
|
|
|
|
zend_declare_typed_property(
|
|
|
|
zend_test_class, name, &val, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC, NULL,
|
2019-09-20 23:01:19 +08:00
|
|
|
(zend_type) ZEND_TYPE_INIT_CODE(IS_LONG, 0, 0));
|
2019-01-07 19:28:51 +08:00
|
|
|
zend_string_release(name);
|
|
|
|
}
|
|
|
|
|
2018-06-27 16:49:05 +08:00
|
|
|
INIT_CLASS_ENTRY(class_entry, "_ZendTestChildClass", NULL);
|
|
|
|
zend_test_child_class = zend_register_internal_class_ex(&class_entry, zend_test_class);
|
|
|
|
|
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;
|
|
|
|
|
2020-04-11 19:27:04 +08:00
|
|
|
INIT_CLASS_ENTRY(class_entry, "_ZendTestTrait", class__ZendTestTrait_methods);
|
2017-03-11 07:33:32 +08:00
|
|
|
zend_test_trait = zend_register_internal_class(&class_entry);
|
|
|
|
zend_test_trait->ce_flags |= ZEND_ACC_TRAIT;
|
|
|
|
zend_declare_property_null(zend_test_trait, "testProp", sizeof("testProp")-1, ZEND_ACC_PUBLIC);
|
2018-05-15 06:36:14 +08:00
|
|
|
|
|
|
|
zend_register_class_alias("_ZendTestClassAlias", zend_test_class);
|
2020-01-10 18:34:05 +08:00
|
|
|
|
|
|
|
REGISTER_LONG_CONSTANT("ZEND_TEST_DEPRECATED", 42, CONST_PERSISTENT | CONST_DEPRECATED);
|
2020-05-25 02:57:00 +08:00
|
|
|
|
|
|
|
INIT_CLASS_ENTRY(class_entry, "ZendTestAttribute", NULL);
|
|
|
|
zend_test_attribute = zend_register_internal_class(&class_entry);
|
|
|
|
zend_test_attribute->ce_flags |= ZEND_ACC_FINAL;
|
|
|
|
|
2020-06-29 01:16:33 +08:00
|
|
|
{
|
|
|
|
zend_internal_attribute *attr = zend_internal_attribute_register(zend_test_attribute, ZEND_ATTRIBUTE_TARGET_ALL);
|
|
|
|
attr->validator = zend_attribute_validate_zendtestattribute;
|
|
|
|
}
|
|
|
|
|
2020-09-01 23:57:49 +08:00
|
|
|
// Loading via dl() not supported with the observer API
|
|
|
|
if (type != MODULE_TEMPORARY) {
|
|
|
|
REGISTER_INI_ENTRIES();
|
|
|
|
if (ZT_G(observer_enabled)) {
|
|
|
|
zend_observer_fcall_register(observer_fcall_init);
|
|
|
|
}
|
|
|
|
} 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;
|
|
|
|
}
|
|
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
2017-03-11 07:33:32 +08:00
|
|
|
return SUCCESS;
|
|
|
|
}
|
|
|
|
|
2020-11-11 18:06:55 +08:00
|
|
|
static void observer_show_opcode(zend_execute_data *execute_data)
|
|
|
|
{
|
|
|
|
if (!ZT_G(observer_show_opcode)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
php_printf("%*s<!-- opcode: '%s' -->\n", 2 * ZT_G(observer_nesting_depth), "", zend_get_opcode_name(EX(opline)->opcode));
|
|
|
|
}
|
|
|
|
|
2020-09-01 23:57:49 +08:00
|
|
|
static void observer_begin(zend_execute_data *execute_data)
|
|
|
|
{
|
|
|
|
if (!ZT_G(observer_show_output)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (execute_data->func && execute_data->func->common.function_name) {
|
|
|
|
if (execute_data->func->common.scope) {
|
|
|
|
php_printf("%*s<%s::%s>\n", 2 * ZT_G(observer_nesting_depth), "", ZSTR_VAL(execute_data->func->common.scope->name), ZSTR_VAL(execute_data->func->common.function_name));
|
|
|
|
} else {
|
|
|
|
php_printf("%*s<%s>\n", 2 * ZT_G(observer_nesting_depth), "", ZSTR_VAL(execute_data->func->common.function_name));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
php_printf("%*s<file '%s'>\n", 2 * ZT_G(observer_nesting_depth), "", ZSTR_VAL(execute_data->func->op_array.filename));
|
|
|
|
}
|
|
|
|
ZT_G(observer_nesting_depth)++;
|
2020-11-11 18:06:55 +08:00
|
|
|
observer_show_opcode(execute_data);
|
2020-09-01 23:57:49 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void get_retval_info(zval *retval, smart_str *buf)
|
|
|
|
{
|
|
|
|
if (!ZT_G(observer_show_return_type) && !ZT_G(observer_show_return_value)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
smart_str_appendc(buf, ':');
|
|
|
|
if (retval == NULL) {
|
|
|
|
smart_str_appendl(buf, "NULL", 4);
|
|
|
|
} else if (ZT_G(observer_show_return_value)) {
|
2020-11-12 06:25:39 +08:00
|
|
|
if (Z_TYPE_P(retval) == IS_OBJECT) {
|
|
|
|
smart_str_appendl(buf, "object(", 7);
|
|
|
|
smart_str_append(buf, Z_OBJCE_P(retval)->name);
|
|
|
|
smart_str_appendl(buf, ")#", 2);
|
|
|
|
smart_str_append_long(buf, Z_OBJ_HANDLE_P(retval));
|
|
|
|
} else {
|
|
|
|
php_var_export_ex(retval, 2 * ZT_G(observer_nesting_depth) + 3, buf);
|
|
|
|
}
|
2020-09-01 23:57:49 +08:00
|
|
|
} else if (ZT_G(observer_show_return_type)) {
|
|
|
|
smart_str_appends(buf, zend_zval_type_name(retval));
|
|
|
|
}
|
|
|
|
smart_str_0(buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void observer_end(zend_execute_data *execute_data, zval *retval)
|
|
|
|
{
|
|
|
|
if (!ZT_G(observer_show_output)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (EG(exception)) {
|
|
|
|
php_printf("%*s<!-- Exception: %s -->\n", 2 * ZT_G(observer_nesting_depth), "", ZSTR_VAL(EG(exception)->ce->name));
|
|
|
|
}
|
2020-11-11 18:06:55 +08:00
|
|
|
observer_show_opcode(execute_data);
|
2020-09-01 23:57:49 +08:00
|
|
|
ZT_G(observer_nesting_depth)--;
|
|
|
|
if (execute_data->func && execute_data->func->common.function_name) {
|
|
|
|
smart_str retval_info = {0};
|
|
|
|
get_retval_info(retval, &retval_info);
|
|
|
|
if (execute_data->func->common.scope) {
|
|
|
|
php_printf("%*s</%s::%s%s>\n", 2 * ZT_G(observer_nesting_depth), "", ZSTR_VAL(execute_data->func->common.scope->name), ZSTR_VAL(execute_data->func->common.function_name), retval_info.s ? ZSTR_VAL(retval_info.s) : "");
|
|
|
|
} else {
|
|
|
|
php_printf("%*s</%s%s>\n", 2 * ZT_G(observer_nesting_depth), "", ZSTR_VAL(execute_data->func->common.function_name), retval_info.s ? ZSTR_VAL(retval_info.s) : "");
|
|
|
|
}
|
|
|
|
smart_str_free(&retval_info);
|
|
|
|
} else {
|
|
|
|
php_printf("%*s</file '%s'>\n", 2 * ZT_G(observer_nesting_depth), "", ZSTR_VAL(execute_data->func->op_array.filename));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void observer_show_init(zend_function *fbc)
|
|
|
|
{
|
|
|
|
if (fbc->common.function_name) {
|
|
|
|
if (fbc->common.scope) {
|
|
|
|
php_printf("%*s<!-- init %s::%s() -->\n", 2 * ZT_G(observer_nesting_depth), "", ZSTR_VAL(fbc->common.scope->name), ZSTR_VAL(fbc->common.function_name));
|
|
|
|
} else {
|
|
|
|
php_printf("%*s<!-- init %s() -->\n", 2 * ZT_G(observer_nesting_depth), "", ZSTR_VAL(fbc->common.function_name));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
php_printf("%*s<!-- init '%s' -->\n", 2 * ZT_G(observer_nesting_depth), "", ZSTR_VAL(fbc->op_array.filename));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-25 03:57:43 +08:00
|
|
|
static void observer_show_init_backtrace(zend_execute_data *execute_data)
|
2020-09-01 23:57:49 +08:00
|
|
|
{
|
2020-09-25 03:57:43 +08:00
|
|
|
zend_execute_data *ex = execute_data;
|
|
|
|
php_printf("%*s<!--\n", 2 * ZT_G(observer_nesting_depth), "");
|
|
|
|
do {
|
|
|
|
zend_function *fbc = ex->func;
|
|
|
|
int indent = 2 * ZT_G(observer_nesting_depth) + 4;
|
|
|
|
if (fbc->common.function_name) {
|
|
|
|
if (fbc->common.scope) {
|
|
|
|
php_printf("%*s%s::%s()\n", indent, "", ZSTR_VAL(fbc->common.scope->name), ZSTR_VAL(fbc->common.function_name));
|
|
|
|
} else {
|
|
|
|
php_printf("%*s%s()\n", indent, "", ZSTR_VAL(fbc->common.function_name));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
php_printf("%*s{main} %s\n", indent, "", ZSTR_VAL(fbc->op_array.filename));
|
|
|
|
}
|
|
|
|
} while ((ex = ex->prev_execute_data) != NULL);
|
|
|
|
php_printf("%*s-->\n", 2 * ZT_G(observer_nesting_depth), "");
|
|
|
|
}
|
|
|
|
|
|
|
|
static zend_observer_fcall_handlers observer_fcall_init(zend_execute_data *execute_data)
|
|
|
|
{
|
|
|
|
zend_function *fbc = execute_data->func;
|
2020-09-01 23:57:49 +08:00
|
|
|
if (ZT_G(observer_show_output)) {
|
|
|
|
observer_show_init(fbc);
|
2020-09-25 03:57:43 +08:00
|
|
|
if (ZT_G(observer_show_init_backtrace)) {
|
|
|
|
observer_show_init_backtrace(execute_data);
|
|
|
|
}
|
2020-11-11 18:06:55 +08:00
|
|
|
observer_show_opcode(execute_data);
|
2020-09-01 23:57:49 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (ZT_G(observer_observe_all)) {
|
2020-09-18 17:55:58 +08:00
|
|
|
return (zend_observer_fcall_handlers){observer_begin, observer_end};
|
2020-09-01 23:57:49 +08:00
|
|
|
} else if (ZT_G(observer_observe_includes) && !fbc->common.function_name) {
|
2020-09-18 17:55:58 +08:00
|
|
|
return (zend_observer_fcall_handlers){observer_begin, observer_end};
|
2020-09-01 23:57:49 +08:00
|
|
|
} else if (ZT_G(observer_observe_functions) && fbc->common.function_name) {
|
2020-09-18 17:55:58 +08:00
|
|
|
return (zend_observer_fcall_handlers){observer_begin, observer_end};
|
2020-09-01 23:57:49 +08:00
|
|
|
}
|
2020-09-18 17:55:58 +08:00
|
|
|
return (zend_observer_fcall_handlers){NULL, NULL};
|
2020-09-01 23:57:49 +08:00
|
|
|
}
|
|
|
|
|
2017-03-11 07:33:32 +08:00
|
|
|
PHP_RINIT_FUNCTION(zend_test)
|
|
|
|
{
|
|
|
|
return SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
PHP_RSHUTDOWN_FUNCTION(zend_test)
|
|
|
|
{
|
|
|
|
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));
|
|
|
|
}
|
|
|
|
|
2017-03-11 07:33:32 +08:00
|
|
|
PHP_MINFO_FUNCTION(zend_test)
|
|
|
|
{
|
|
|
|
php_info_print_table_start();
|
|
|
|
php_info_print_table_header(2, "zend-test extension", "enabled");
|
|
|
|
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,
|
2017-08-18 04:15:09 +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),
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
STANDARD_MODULE_PROPERTIES_EX
|
2017-03-11 07:33:32 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
#ifdef COMPILE_DL_ZEND_TEST
|
|
|
|
#ifdef ZTS
|
|
|
|
ZEND_TSRMLS_CACHE_DEFINE()
|
|
|
|
#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
|
|
|
|
2020-05-27 15:58:10 +08:00
|
|
|
PHP_ZEND_TEST_API struct bug79096 bug79096(void)
|
2020-01-12 21:01:42 +08:00
|
|
|
{
|
|
|
|
struct bug79096 b;
|
|
|
|
|
|
|
|
b.a = 1;
|
|
|
|
b.b = 1;
|
|
|
|
return b;
|
|
|
|
}
|
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;
|
|
|
|
return s;
|
|
|
|
}
|