xref: /PHP-7.4/ext/zend_test/test.c (revision 0427dcb9)
1 /*
2   +----------------------------------------------------------------------+
3   | PHP Version 7                                                        |
4   +----------------------------------------------------------------------+
5   | Copyright (c) The PHP Group                                          |
6   +----------------------------------------------------------------------+
7   | This source file is subject to version 3.01 of the PHP license,      |
8   | that is bundled with this package in the file LICENSE, and is        |
9   | available through the world-wide-web at the following url:           |
10   | http://www.php.net/license/3_01.txt                                  |
11   | If you did not receive a copy of the PHP license and are unable to   |
12   | obtain it through the world-wide-web, please send a note to          |
13   | license@php.net so we can mail you a copy immediately.               |
14   +----------------------------------------------------------------------+
15   | Author:                                                              |
16   +----------------------------------------------------------------------+
17 */
18 
19 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif
22 
23 #include "php.h"
24 #include "php_ini.h"
25 #include "ext/standard/info.h"
26 #include "php_test.h"
27 
28 static zend_class_entry *zend_test_interface;
29 static zend_class_entry *zend_test_class;
30 static zend_class_entry *zend_test_child_class;
31 static zend_class_entry *zend_test_trait;
32 static zend_object_handlers zend_test_class_handlers;
33 
34 ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO(arginfo_zend_test_array_return, IS_ARRAY, 0)
ZEND_END_ARG_INFO()35 ZEND_END_ARG_INFO()
36 
37 ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO(arginfo_zend_test_nullable_array_return, IS_ARRAY, 1)
38 ZEND_END_ARG_INFO()
39 
40 ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO(arginfo_zend_test_void_return, IS_VOID, 0)
41 ZEND_END_ARG_INFO()
42 
43 ZEND_BEGIN_ARG_INFO_EX(arginfo_zend_terminate_string, 0, 0, 1)
44 	ZEND_ARG_INFO(1, str)
45 ZEND_END_ARG_INFO()
46 
47 ZEND_BEGIN_ARG_INFO_EX(arginfo_zend_leak_variable, 0, 0, 1)
48 	ZEND_ARG_INFO(0, variable)
49 ZEND_END_ARG_INFO()
50 
51 ZEND_FUNCTION(zend_test_func)
52 {
53 	/* dummy */
54 }
55 
ZEND_FUNCTION(zend_test_array_return)56 ZEND_FUNCTION(zend_test_array_return)
57 {
58 	zval *arg1, *arg2;
59 
60 	zend_parse_parameters(ZEND_NUM_ARGS(), "|zz", &arg1, &arg2);
61 }
62 
ZEND_FUNCTION(zend_test_nullable_array_return)63 ZEND_FUNCTION(zend_test_nullable_array_return)
64 {
65 	zval *arg1, *arg2;
66 
67 	zend_parse_parameters(ZEND_NUM_ARGS(), "|zz", &arg1, &arg2);
68 }
69 
ZEND_FUNCTION(zend_test_void_return)70 ZEND_FUNCTION(zend_test_void_return)
71 {
72 	/* dummy */
73 }
74 
75 /* Create a string without terminating null byte. Must be termined with
76  * zend_terminate_string() before destruction, otherwise a warning is issued
77  * in debug builds. */
ZEND_FUNCTION(zend_create_unterminated_string)78 ZEND_FUNCTION(zend_create_unterminated_string)
79 {
80 	zend_string *str, *res;
81 
82 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &str) == FAILURE) {
83 		return;
84 	}
85 
86 	res = zend_string_alloc(ZSTR_LEN(str), 0);
87 	memcpy(ZSTR_VAL(res), ZSTR_VAL(str), ZSTR_LEN(str));
88 	/* No trailing null byte */
89 
90 	RETURN_STR(res);
91 }
92 
93 /* Enforce terminate null byte on string. This avoids a warning in debug builds. */
ZEND_FUNCTION(zend_terminate_string)94 ZEND_FUNCTION(zend_terminate_string)
95 {
96 	zend_string *str;
97 
98 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &str) == FAILURE) {
99 		return;
100 	}
101 
102 	ZSTR_VAL(str)[ZSTR_LEN(str)] = '\0';
103 }
104 
105 /* {{{ proto void zend_leak_bytes([int num_bytes])
106    Cause an intentional memory leak, for testing/debugging purposes */
ZEND_FUNCTION(zend_leak_bytes)107 ZEND_FUNCTION(zend_leak_bytes)
108 {
109 	zend_long leakbytes = 3;
110 
111 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &leakbytes) == FAILURE) {
112 		return;
113 	}
114 
115 	emalloc(leakbytes);
116 }
117 /* }}} */
118 
119 /* {{{ proto void zend_leak_variable(mixed variable)
120    Leak a refcounted variable */
ZEND_FUNCTION(zend_leak_variable)121 ZEND_FUNCTION(zend_leak_variable)
122 {
123 	zval *zv;
124 
125 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &zv) == FAILURE) {
126 		return;
127 	}
128 
129 	if (!Z_REFCOUNTED_P(zv)) {
130 		zend_error(E_WARNING, "Cannot leak variable that is not refcounted");
131 		return;
132 	}
133 
134 	Z_ADDREF_P(zv);
135 }
136 /* }}} */
137 
zend_test_class_new(zend_class_entry * class_type)138 static zend_object *zend_test_class_new(zend_class_entry *class_type) /* {{{ */ {
139 	zend_object *obj = zend_objects_new(class_type);
140 	object_properties_init(obj, class_type);
141 	obj->handlers = &zend_test_class_handlers;
142 	return obj;
143 }
144 /* }}} */
145 
zend_test_class_method_get(zend_object ** object,zend_string * name,const zval * key)146 static zend_function *zend_test_class_method_get(zend_object **object, zend_string *name, const zval *key) /* {{{ */ {
147 	zend_internal_function *fptr = emalloc(sizeof(zend_internal_function));
148 	fptr->type = ZEND_OVERLOADED_FUNCTION_TEMPORARY;
149 	fptr->num_args = 1;
150 	fptr->arg_info = NULL;
151 	fptr->scope = (*object)->ce;
152 	fptr->fn_flags = ZEND_ACC_CALL_VIA_HANDLER;
153 	fptr->function_name = zend_string_copy(name);
154 	fptr->handler = ZEND_FN(zend_test_func);
155 	zend_set_function_arg_flags((zend_function*)fptr);
156 
157 	return (zend_function*)fptr;
158 }
159 /* }}} */
160 
zend_test_class_static_method_get(zend_class_entry * ce,zend_string * name)161 static zend_function *zend_test_class_static_method_get(zend_class_entry *ce, zend_string *name) /* {{{ */ {
162 	if (zend_string_equals_literal_ci(name, "test")) {
163 		zend_internal_function *fptr = emalloc(sizeof(zend_internal_function));
164 		fptr->type = ZEND_OVERLOADED_FUNCTION;
165 		fptr->num_args = 1;
166 		fptr->arg_info = NULL;
167 		fptr->scope = ce;
168 		fptr->fn_flags = ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_STATIC;
169 		fptr->function_name = name;
170 		fptr->handler = ZEND_FN(zend_test_func);
171 		zend_set_function_arg_flags((zend_function*)fptr);
172 
173 		return (zend_function*)fptr;
174 	}
175 	return zend_std_get_static_method(ce, name, NULL);
176 }
177 /* }}} */
178 
zend_test_class_call_method(zend_string * method,zend_object * object,INTERNAL_FUNCTION_PARAMETERS)179 static int zend_test_class_call_method(zend_string *method, zend_object *object, INTERNAL_FUNCTION_PARAMETERS) /* {{{ */ {
180 	RETVAL_STR(zend_string_copy(method));
181 	return 0;
182 }
183 /* }}} */
184 
185 /* Internal function returns bool, we return int. */
ZEND_METHOD(_ZendTestClass,is_object)186 static ZEND_METHOD(_ZendTestClass, is_object) /* {{{ */ {
187 	RETURN_LONG(42);
188 }
189 /* }}} */
190 
ZEND_METHOD(_ZendTestTrait,testMethod)191 static ZEND_METHOD(_ZendTestTrait, testMethod) /* {{{ */ {
192 	RETURN_TRUE;
193 }
194 /* }}} */
195 
196 static const zend_function_entry zend_test_class_methods[] = {
197 	ZEND_ME(_ZendTestClass, is_object, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
198 	ZEND_FE_END
199 };
200 
201 static const zend_function_entry zend_test_trait_methods[] = {
202     ZEND_ME(_ZendTestTrait, testMethod, NULL, ZEND_ACC_PUBLIC)
203     ZEND_FE_END
204 };
205 
PHP_MINIT_FUNCTION(zend_test)206 PHP_MINIT_FUNCTION(zend_test)
207 {
208 	zend_class_entry class_entry;
209 
210 	INIT_CLASS_ENTRY(class_entry, "_ZendTestInterface", NULL);
211 	zend_test_interface = zend_register_internal_interface(&class_entry);
212 	zend_declare_class_constant_long(zend_test_interface, ZEND_STRL("DUMMY"), 0);
213 	INIT_CLASS_ENTRY(class_entry, "_ZendTestClass", zend_test_class_methods);
214 	zend_test_class = zend_register_internal_class_ex(&class_entry, NULL);
215 	zend_class_implements(zend_test_class, 1, zend_test_interface);
216 	zend_test_class->create_object = zend_test_class_new;
217 	zend_test_class->get_static_method = zend_test_class_static_method_get;
218 
219 	zend_declare_property_null(zend_test_class, "_StaticProp", sizeof("_StaticProp") - 1, ZEND_ACC_STATIC);
220 
221 	{
222 		zend_string *name = zend_string_init("intProp", sizeof("intProp") - 1, 1);
223 		zval val;
224 		ZVAL_LONG(&val, 123);
225 		zend_declare_typed_property(
226 			zend_test_class, name, &val, ZEND_ACC_PUBLIC, NULL, ZEND_TYPE_ENCODE(IS_LONG, 0));
227 		zend_string_release(name);
228 	}
229 
230 	{
231 		zend_string *name = zend_string_init("classProp", sizeof("classProp") - 1, 1);
232 		zend_string *class_name = zend_string_init("stdClass", sizeof("stdClass") - 1, 1);
233 		zval val;
234 		ZVAL_NULL(&val);
235 		zend_declare_typed_property(
236 			zend_test_class, name, &val, ZEND_ACC_PUBLIC, NULL,
237 			ZEND_TYPE_ENCODE_CLASS(class_name, 1));
238 		zend_string_release(name);
239 	}
240 
241 	{
242 		zend_string *name = zend_string_init("staticIntProp", sizeof("staticIntProp") - 1, 1);
243 		zval val;
244 		ZVAL_LONG(&val, 123);
245 		zend_declare_typed_property(
246 			zend_test_class, name, &val, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC, NULL,
247 			ZEND_TYPE_ENCODE(IS_LONG, 0));
248 		zend_string_release(name);
249 	}
250 
251 	INIT_CLASS_ENTRY(class_entry, "_ZendTestChildClass", NULL);
252 	zend_test_child_class = zend_register_internal_class_ex(&class_entry, zend_test_class);
253 
254 	memcpy(&zend_test_class_handlers, &std_object_handlers, sizeof(zend_object_handlers));
255 	zend_test_class_handlers.get_method = zend_test_class_method_get;
256 	zend_test_class_handlers.call_method = zend_test_class_call_method;
257 
258 	INIT_CLASS_ENTRY(class_entry, "_ZendTestTrait", zend_test_trait_methods);
259 	zend_test_trait = zend_register_internal_class(&class_entry);
260 	zend_test_trait->ce_flags |= ZEND_ACC_TRAIT;
261 	zend_declare_property_null(zend_test_trait, "testProp", sizeof("testProp")-1, ZEND_ACC_PUBLIC);
262 
263 	zend_register_class_alias("_ZendTestClassAlias", zend_test_class);
264 	return SUCCESS;
265 }
266 
PHP_MSHUTDOWN_FUNCTION(zend_test)267 PHP_MSHUTDOWN_FUNCTION(zend_test)
268 {
269 	return SUCCESS;
270 }
271 
PHP_RINIT_FUNCTION(zend_test)272 PHP_RINIT_FUNCTION(zend_test)
273 {
274 #if defined(COMPILE_DL_ZEND_TEST) && defined(ZTS)
275 	ZEND_TSRMLS_CACHE_UPDATE();
276 #endif
277 	return SUCCESS;
278 }
279 
PHP_RSHUTDOWN_FUNCTION(zend_test)280 PHP_RSHUTDOWN_FUNCTION(zend_test)
281 {
282 	return SUCCESS;
283 }
284 
PHP_MINFO_FUNCTION(zend_test)285 PHP_MINFO_FUNCTION(zend_test)
286 {
287 	php_info_print_table_start();
288 	php_info_print_table_header(2, "zend-test extension", "enabled");
289 	php_info_print_table_end();
290 }
291 
292 static const zend_function_entry zend_test_functions[] = {
293 	ZEND_FE(zend_test_array_return, arginfo_zend_test_array_return)
294 	ZEND_FE(zend_test_nullable_array_return, arginfo_zend_test_nullable_array_return)
295 	ZEND_FE(zend_test_void_return, arginfo_zend_test_void_return)
296 	ZEND_FE(zend_create_unterminated_string, NULL)
297 	ZEND_FE(zend_terminate_string, arginfo_zend_terminate_string)
298 	ZEND_FE(zend_leak_bytes, NULL)
299 	ZEND_FE(zend_leak_variable, arginfo_zend_leak_variable)
300 	ZEND_FE_END
301 };
302 
303 zend_module_entry zend_test_module_entry = {
304 	STANDARD_MODULE_HEADER,
305 	"zend-test",
306 	zend_test_functions,
307 	PHP_MINIT(zend_test),
308 	PHP_MSHUTDOWN(zend_test),
309 	PHP_RINIT(zend_test),
310 	PHP_RSHUTDOWN(zend_test),
311 	PHP_MINFO(zend_test),
312 	PHP_ZEND_TEST_VERSION,
313 	STANDARD_MODULE_PROPERTIES
314 };
315 
316 #ifdef COMPILE_DL_ZEND_TEST
317 #ifdef ZTS
318 ZEND_TSRMLS_CACHE_DEFINE()
319 #endif
ZEND_GET_MODULE(zend_test)320 ZEND_GET_MODULE(zend_test)
321 #endif
322 
323 struct bug79096 bug79096(void)
324 {
325   struct bug79096 b;
326 
327   b.a = 1;
328   b.b = 1;
329   return b;
330 }
331 
bug79532(off_t * array,size_t elems)332 void bug79532(off_t *array, size_t elems)
333 {
334 	int i;
335 	for (i = 0; i < elems; i++) {
336 		array[i] = i;
337 	}
338 }
339 
340 PHP_ZEND_TEST_API int *(*bug79177_cb)(void);
bug79177(void)341 void bug79177(void)
342 {
343 	bug79177_cb();
344 }
345