xref: /php-src/ext/zend_test/test.c (revision e643129b)
1 /*
2   +----------------------------------------------------------------------+
3   | Copyright (c) The PHP Group                                          |
4   +----------------------------------------------------------------------+
5   | This source file is subject to version 3.01 of the PHP license,      |
6   | that is bundled with this package in the file LICENSE, and is        |
7   | available through the world-wide-web at the following url:           |
8   | https://www.php.net/license/3_01.txt                                 |
9   | If you did not receive a copy of the PHP license and are unable to   |
10   | obtain it through the world-wide-web, please send a note to          |
11   | license@php.net so we can mail you a copy immediately.               |
12   +----------------------------------------------------------------------+
13   | Author:                                                              |
14   +----------------------------------------------------------------------+
15 */
16 
17 #include "zend_modules.h"
18 #ifdef HAVE_CONFIG_H
19 # include "config.h"
20 #endif
21 
22 #include "php.h"
23 #include "php_ini.h"
24 #include "ext/standard/info.h"
25 #include "php_test.h"
26 #include "observer.h"
27 #include "fiber.h"
28 #include "iterators.h"
29 #include "object_handlers.h"
30 #include "zend_attributes.h"
31 #include "zend_enum.h"
32 #include "zend_interfaces.h"
33 #include "zend_weakrefs.h"
34 #include "Zend/Optimizer/zend_optimizer.h"
35 #include "Zend/zend_alloc.h"
36 #include "test_arginfo.h"
37 #include "zend_call_stack.h"
38 #include "zend_exceptions.h"
39 #include "zend_mm_custom_handlers.h"
40 
41 #if defined(HAVE_LIBXML) && !defined(PHP_WIN32)
42 # include <libxml/globals.h>
43 # include <libxml/parser.h>
44 #endif
45 
46 ZEND_DECLARE_MODULE_GLOBALS(zend_test)
47 
48 static zend_class_entry *zend_test_interface;
49 static zend_class_entry *zend_test_class;
50 static zend_class_entry *zend_test_child_class;
51 static zend_class_entry *zend_attribute_test_class;
52 static zend_class_entry *zend_test_trait;
53 static zend_class_entry *zend_test_attribute;
54 static zend_class_entry *zend_test_repeatable_attribute;
55 static zend_class_entry *zend_test_parameter_attribute;
56 static zend_class_entry *zend_test_property_attribute;
57 static zend_class_entry *zend_test_attribute_with_arguments;
58 static zend_class_entry *zend_test_class_with_method_with_parameter_attribute;
59 static zend_class_entry *zend_test_child_class_with_method_with_parameter_attribute;
60 static zend_class_entry *zend_test_class_with_property_attribute;
61 static zend_class_entry *zend_test_forbid_dynamic_call;
62 static zend_class_entry *zend_test_ns_foo_class;
63 static zend_class_entry *zend_test_ns_unlikely_compile_error_class;
64 static zend_class_entry *zend_test_ns_not_unlikely_compile_error_class;
65 static zend_class_entry *zend_test_ns2_foo_class;
66 static zend_class_entry *zend_test_ns2_ns_foo_class;
67 static zend_class_entry *zend_test_unit_enum;
68 static zend_class_entry *zend_test_string_enum;
69 static zend_class_entry *zend_test_int_enum;
70 static zend_class_entry *zend_test_magic_call;
71 static zend_object_handlers zend_test_class_handlers;
72 
73 static int le_throwing_resource;
74 
ZEND_FUNCTION(zend_test_func)75 static ZEND_FUNCTION(zend_test_func)
76 {
77 	RETVAL_STR_COPY(EX(func)->common.function_name);
78 
79 	/* Cleanup trampoline */
80 	ZEND_ASSERT(EX(func)->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE);
81 	zend_string_release(EX(func)->common.function_name);
82 	zend_free_trampoline(EX(func));
83 	EX(func) = NULL;
84 }
85 
ZEND_FUNCTION(zend_test_array_return)86 static ZEND_FUNCTION(zend_test_array_return)
87 {
88 	ZEND_PARSE_PARAMETERS_NONE();
89 }
90 
ZEND_FUNCTION(zend_test_nullable_array_return)91 static ZEND_FUNCTION(zend_test_nullable_array_return)
92 {
93 	ZEND_PARSE_PARAMETERS_NONE();
94 
95 	RETURN_NULL();
96 }
97 
ZEND_FUNCTION(zend_test_void_return)98 static ZEND_FUNCTION(zend_test_void_return)
99 {
100 	/* dummy */
101 	ZEND_PARSE_PARAMETERS_NONE();
102 }
103 
pass1(zend_script * script,void * context)104 static void pass1(zend_script *script, void *context)
105 {
106 	php_printf("pass1\n");
107 }
108 
pass2(zend_script * script,void * context)109 static void pass2(zend_script *script, void *context)
110 {
111 	php_printf("pass2\n");
112 }
113 
ZEND_FUNCTION(zend_test_deprecated)114 static ZEND_FUNCTION(zend_test_deprecated)
115 {
116 	zval *arg1;
117 
118 	zend_parse_parameters(ZEND_NUM_ARGS(), "|z", &arg1);
119 }
120 
ZEND_FUNCTION(zend_test_deprecated_attr)121 static ZEND_FUNCTION(zend_test_deprecated_attr)
122 {
123 	ZEND_PARSE_PARAMETERS_NONE();
124 }
125 
126 /* Create a string without terminating null byte. Must be terminated with
127  * zend_terminate_string() before destruction, otherwise a warning is issued
128  * in debug builds. */
ZEND_FUNCTION(zend_create_unterminated_string)129 static ZEND_FUNCTION(zend_create_unterminated_string)
130 {
131 	zend_string *str, *res;
132 
133 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &str) == FAILURE) {
134 		RETURN_THROWS();
135 	}
136 
137 	res = zend_string_alloc(ZSTR_LEN(str), 0);
138 	memcpy(ZSTR_VAL(res), ZSTR_VAL(str), ZSTR_LEN(str));
139 	/* No trailing null byte */
140 
141 	RETURN_STR(res);
142 }
143 
144 /* Enforce terminate null byte on string. This avoids a warning in debug builds. */
ZEND_FUNCTION(zend_terminate_string)145 static ZEND_FUNCTION(zend_terminate_string)
146 {
147 	zend_string *str;
148 
149 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &str) == FAILURE) {
150 		RETURN_THROWS();
151 	}
152 
153 	ZSTR_VAL(str)[ZSTR_LEN(str)] = '\0';
154 }
155 
156 /* Cause an intentional memory leak, for testing/debugging purposes */
ZEND_FUNCTION(zend_leak_bytes)157 static ZEND_FUNCTION(zend_leak_bytes)
158 {
159 	zend_long leakbytes = 3;
160 
161 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &leakbytes) == FAILURE) {
162 		RETURN_THROWS();
163 	}
164 
165 	emalloc(leakbytes);
166 }
167 
168 /* Leak a refcounted variable */
ZEND_FUNCTION(zend_leak_variable)169 static ZEND_FUNCTION(zend_leak_variable)
170 {
171 	zval *zv;
172 
173 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &zv) == FAILURE) {
174 		RETURN_THROWS();
175 	}
176 
177 	if (!Z_REFCOUNTED_P(zv)) {
178 		zend_error(E_WARNING, "Cannot leak variable that is not refcounted");
179 		return;
180 	}
181 
182 	Z_ADDREF_P(zv);
183 }
184 
185 /* Tests Z_PARAM_OBJ_OR_STR */
ZEND_FUNCTION(zend_string_or_object)186 static ZEND_FUNCTION(zend_string_or_object)
187 {
188 	zend_string *str;
189 	zend_object *object;
190 
191 	ZEND_PARSE_PARAMETERS_START(1, 1)
192 		Z_PARAM_OBJ_OR_STR(object, str)
193 	ZEND_PARSE_PARAMETERS_END();
194 
195 	if (str) {
196 		RETURN_STR_COPY(str);
197 	} else {
198 		RETURN_OBJ_COPY(object);
199 	}
200 }
201 
202 /* Tests Z_PARAM_OBJ_OR_STR_OR_NULL */
ZEND_FUNCTION(zend_string_or_object_or_null)203 static ZEND_FUNCTION(zend_string_or_object_or_null)
204 {
205 	zend_string *str;
206 	zend_object *object;
207 
208 	ZEND_PARSE_PARAMETERS_START(1, 1)
209 		Z_PARAM_OBJ_OR_STR_OR_NULL(object, str)
210 	ZEND_PARSE_PARAMETERS_END();
211 
212 	if (str) {
213 		RETURN_STR_COPY(str);
214 	} else if (object) {
215 		RETURN_OBJ_COPY(object);
216 	} else {
217 		RETURN_NULL();
218 	}
219 }
220 
221 /* Tests Z_PARAM_OBJ_OF_CLASS_OR_STR */
ZEND_FUNCTION(zend_string_or_stdclass)222 static ZEND_FUNCTION(zend_string_or_stdclass)
223 {
224 	zend_string *str;
225 	zend_object *object;
226 
227 	ZEND_PARSE_PARAMETERS_START(1, 1)
228 		Z_PARAM_OBJ_OF_CLASS_OR_STR(object, zend_standard_class_def, str)
229 	ZEND_PARSE_PARAMETERS_END();
230 
231 	if (str) {
232 		RETURN_STR_COPY(str);
233 	} else {
234 		RETURN_OBJ_COPY(object);
235 	}
236 }
237 
ZEND_FUNCTION(zend_test_compile_string)238 static ZEND_FUNCTION(zend_test_compile_string)
239 {
240 	zend_string *source_string = NULL;
241 	zend_string *filename = NULL;
242 	zend_long position = ZEND_COMPILE_POSITION_AT_OPEN_TAG;
243 
244 	ZEND_PARSE_PARAMETERS_START(3, 3)
245 		Z_PARAM_STR(source_string)
246 		Z_PARAM_STR(filename)
247 		Z_PARAM_LONG(position)
248 	ZEND_PARSE_PARAMETERS_END();
249 
250 	zend_op_array *op_array = NULL;
251 
252 	op_array = compile_string(source_string, ZSTR_VAL(filename), position);
253 
254 	if (op_array) {
255 		zval retval;
256 
257 		zend_try {
258 			ZVAL_UNDEF(&retval);
259 			zend_execute(op_array, &retval);
260 		} zend_catch {
261 			destroy_op_array(op_array);
262 			efree_size(op_array, sizeof(zend_op_array));
263 			zend_bailout();
264 		} zend_end_try();
265 
266 		destroy_op_array(op_array);
267 		efree_size(op_array, sizeof(zend_op_array));
268 	}
269 
270 	return;
271 }
272 
273 /* Tests Z_PARAM_OBJ_OF_CLASS_OR_STR_OR_NULL */
ZEND_FUNCTION(zend_string_or_stdclass_or_null)274 static ZEND_FUNCTION(zend_string_or_stdclass_or_null)
275 {
276 	zend_string *str;
277 	zend_object *object;
278 
279 	ZEND_PARSE_PARAMETERS_START(1, 1)
280 		Z_PARAM_OBJ_OF_CLASS_OR_STR_OR_NULL(object, zend_standard_class_def, str)
281 	ZEND_PARSE_PARAMETERS_END();
282 
283 	if (str) {
284 		RETURN_STR_COPY(str);
285 	} else if (object) {
286 		RETURN_OBJ_COPY(object);
287 	} else {
288 		RETURN_NULL();
289 	}
290 }
291 
292 /* Tests Z_PARAM_NUMBER_OR_STR */
ZEND_FUNCTION(zend_number_or_string)293 static ZEND_FUNCTION(zend_number_or_string)
294 {
295 	zval *input;
296 
297 	ZEND_PARSE_PARAMETERS_START(1, 1)
298 		Z_PARAM_NUMBER_OR_STR(input)
299 	ZEND_PARSE_PARAMETERS_END();
300 
301 	switch (Z_TYPE_P(input)) {
302 		case IS_LONG:
303 			RETURN_LONG(Z_LVAL_P(input));
304 		case IS_DOUBLE:
305 			RETURN_DOUBLE(Z_DVAL_P(input));
306 		case IS_STRING:
307 			RETURN_STR_COPY(Z_STR_P(input));
308 		EMPTY_SWITCH_DEFAULT_CASE();
309 	}
310 }
311 
312 /* Tests Z_PARAM_NUMBER_OR_STR_OR_NULL */
ZEND_FUNCTION(zend_number_or_string_or_null)313 static ZEND_FUNCTION(zend_number_or_string_or_null)
314 {
315 	zval *input;
316 
317 	ZEND_PARSE_PARAMETERS_START(1, 1)
318 		Z_PARAM_NUMBER_OR_STR_OR_NULL(input)
319 	ZEND_PARSE_PARAMETERS_END();
320 
321 	if (!input) {
322 		RETURN_NULL();
323 	}
324 
325 	switch (Z_TYPE_P(input)) {
326 		case IS_LONG:
327 			RETURN_LONG(Z_LVAL_P(input));
328 		case IS_DOUBLE:
329 			RETURN_DOUBLE(Z_DVAL_P(input));
330 		case IS_STRING:
331 			RETURN_STR_COPY(Z_STR_P(input));
332 		EMPTY_SWITCH_DEFAULT_CASE();
333 	}
334 }
335 
ZEND_FUNCTION(zend_weakmap_attach)336 static ZEND_FUNCTION(zend_weakmap_attach)
337 {
338 	zval *value;
339 	zend_object *obj;
340 
341 	ZEND_PARSE_PARAMETERS_START(2, 2)
342 			Z_PARAM_OBJ(obj)
343 			Z_PARAM_ZVAL(value)
344 	ZEND_PARSE_PARAMETERS_END();
345 
346 	if (zend_weakrefs_hash_add(&ZT_G(global_weakmap), obj, value)) {
347 		Z_TRY_ADDREF_P(value);
348 		RETURN_TRUE;
349 	}
350 	RETURN_FALSE;
351 }
352 
ZEND_FUNCTION(zend_weakmap_remove)353 static ZEND_FUNCTION(zend_weakmap_remove)
354 {
355 	zend_object *obj;
356 
357 	ZEND_PARSE_PARAMETERS_START(1, 1)
358 			Z_PARAM_OBJ(obj)
359 	ZEND_PARSE_PARAMETERS_END();
360 
361 	RETURN_BOOL(zend_weakrefs_hash_del(&ZT_G(global_weakmap), obj) == SUCCESS);
362 }
363 
ZEND_FUNCTION(zend_weakmap_dump)364 static ZEND_FUNCTION(zend_weakmap_dump)
365 {
366 	ZEND_PARSE_PARAMETERS_NONE();
367 	RETURN_ARR(zend_array_dup(&ZT_G(global_weakmap)));
368 }
369 
ZEND_FUNCTION(zend_get_current_func_name)370 static ZEND_FUNCTION(zend_get_current_func_name)
371 {
372     ZEND_PARSE_PARAMETERS_NONE();
373 
374     zend_string *function_name = get_function_or_method_name(EG(current_execute_data)->prev_execute_data->func);
375 
376     RETURN_STR(function_name);
377 }
378 
379 #if defined(HAVE_LIBXML) && !defined(PHP_WIN32)
ZEND_FUNCTION(zend_test_override_libxml_global_state)380 static ZEND_FUNCTION(zend_test_override_libxml_global_state)
381 {
382 	ZEND_PARSE_PARAMETERS_NONE();
383 
384 	ZEND_DIAGNOSTIC_IGNORED_START("-Wdeprecated-declarations")
385 	xmlLoadExtDtdDefaultValue = 1;
386 	xmlDoValidityCheckingDefaultValue = 1;
387 	(void) xmlPedanticParserDefault(1);
388 	(void) xmlSubstituteEntitiesDefault(1);
389 	(void) xmlLineNumbersDefault(1);
390 	(void) xmlKeepBlanksDefault(0);
391 	ZEND_DIAGNOSTIC_IGNORED_END
392 }
393 #endif
394 
395 /* TESTS Z_PARAM_ITERABLE and Z_PARAM_ITERABLE_OR_NULL */
ZEND_FUNCTION(zend_iterable)396 static ZEND_FUNCTION(zend_iterable)
397 {
398 	zval *arg1, *arg2;
399 
400 	ZEND_PARSE_PARAMETERS_START(1, 2)
401 		Z_PARAM_ITERABLE(arg1)
402 		Z_PARAM_OPTIONAL
403 		Z_PARAM_ITERABLE_OR_NULL(arg2)
404 	ZEND_PARSE_PARAMETERS_END();
405 }
406 
ZEND_FUNCTION(zend_iterable_legacy)407 static ZEND_FUNCTION(zend_iterable_legacy)
408 {
409 	zval *arg1, *arg2;
410 
411 	ZEND_PARSE_PARAMETERS_START(1, 2)
412 		Z_PARAM_ITERABLE(arg1)
413 		Z_PARAM_OPTIONAL
414 		Z_PARAM_ITERABLE_OR_NULL(arg2)
415 	ZEND_PARSE_PARAMETERS_END();
416 
417 	RETURN_COPY(arg1);
418 }
419 
420 ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_iterable_legacy, 0, 1, IS_ITERABLE, 0)
421 	ZEND_ARG_TYPE_INFO(0, arg1, IS_ITERABLE, 0)
422 	ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, arg2, IS_ITERABLE, 1, "null")
423 ZEND_END_ARG_INFO()
424 
425 static const zend_function_entry ext_function_legacy[] = {
426 	ZEND_FE(zend_iterable_legacy, arginfo_zend_iterable_legacy)
427 	ZEND_FE_END
428 };
429 
430 /* Call a method on a class or object using zend_call_method() */
ZEND_FUNCTION(zend_call_method)431 static ZEND_FUNCTION(zend_call_method)
432 {
433 	zend_string *method_name;
434 	zval *class_or_object, *arg1 = NULL, *arg2 = NULL;
435 	zend_object *obj = NULL;
436 	zend_class_entry *ce = NULL;
437 	int argc = ZEND_NUM_ARGS();
438 
439 	ZEND_PARSE_PARAMETERS_START(2, 4)
440 		Z_PARAM_ZVAL(class_or_object)
441 		Z_PARAM_STR(method_name)
442 		Z_PARAM_OPTIONAL
443 		Z_PARAM_ZVAL(arg1)
444 		Z_PARAM_ZVAL(arg2)
445 	ZEND_PARSE_PARAMETERS_END();
446 
447 	if (Z_TYPE_P(class_or_object) == IS_OBJECT) {
448 		obj = Z_OBJ_P(class_or_object);
449 		ce = obj->ce;
450 	} else if (Z_TYPE_P(class_or_object) == IS_STRING) {
451 		ce = zend_lookup_class(Z_STR_P(class_or_object));
452 		if (!ce) {
453 			zend_error_noreturn(E_ERROR, "Unknown class '%s'", Z_STRVAL_P(class_or_object));
454 			return;
455 		}
456 	} else {
457 		zend_argument_type_error(1, "must be of type object|string, %s given", zend_zval_value_name(class_or_object));
458 		return;
459 	}
460 
461 	ZEND_ASSERT((argc >= 2) && (argc <= 4));
462 	zend_call_method(obj, ce, NULL, ZSTR_VAL(method_name), ZSTR_LEN(method_name), return_value, argc - 2, arg1, arg2);
463 }
464 
465 /* Instantiate a class and run the constructor via object_init_with_constructor */
ZEND_FUNCTION(zend_object_init_with_constructor)466 static ZEND_FUNCTION(zend_object_init_with_constructor)
467 {
468 	zend_class_entry *ce = NULL;
469 	zval *args;
470 	uint32_t num_args;
471 	HashTable *named_args;
472 
473 	ZEND_PARSE_PARAMETERS_START(1, -1)
474 		Z_PARAM_CLASS(ce)
475 		Z_PARAM_VARIADIC_WITH_NAMED(args, num_args, named_args)
476 	ZEND_PARSE_PARAMETERS_END();
477 
478 	zval obj;
479 	/* We don't use return_value directly to check for memory leaks of the API on failure */
480 	zend_result status = object_init_with_constructor(&obj, ce, num_args, args, named_args);
481 	if (status == FAILURE) {
482 		RETURN_THROWS();
483 	}
484 	ZEND_ASSERT(!EG(exception));
485 	ZVAL_COPY_VALUE(return_value, &obj);
486 }
487 
ZEND_FUNCTION(zend_get_unit_enum)488 static ZEND_FUNCTION(zend_get_unit_enum)
489 {
490 	ZEND_PARSE_PARAMETERS_NONE();
491 
492 	RETURN_OBJ_COPY(zend_enum_get_case_cstr(zend_test_unit_enum, "Foo"));
493 }
494 
ZEND_FUNCTION(zend_test_zend_ini_parse_quantity)495 static ZEND_FUNCTION(zend_test_zend_ini_parse_quantity)
496 {
497 	zend_string *str;
498 	zend_string *errstr;
499 
500 	ZEND_PARSE_PARAMETERS_START(1, 1)
501 		Z_PARAM_STR(str)
502 	ZEND_PARSE_PARAMETERS_END();
503 
504 	RETVAL_LONG(zend_ini_parse_quantity(str, &errstr));
505 
506 	if (errstr) {
507 		zend_error(E_WARNING, "%s", ZSTR_VAL(errstr));
508 		zend_string_release(errstr);
509 	}
510 }
511 
ZEND_FUNCTION(zend_test_zend_ini_parse_uquantity)512 static ZEND_FUNCTION(zend_test_zend_ini_parse_uquantity)
513 {
514 	zend_string *str;
515 	zend_string *errstr;
516 
517 	ZEND_PARSE_PARAMETERS_START(1, 1)
518 		Z_PARAM_STR(str)
519 	ZEND_PARSE_PARAMETERS_END();
520 
521 	RETVAL_LONG((zend_long)zend_ini_parse_uquantity(str, &errstr));
522 
523 	if (errstr) {
524 		zend_error(E_WARNING, "%s", ZSTR_VAL(errstr));
525 		zend_string_release(errstr);
526 	}
527 }
528 
ZEND_FUNCTION(zend_test_zend_ini_str)529 static ZEND_FUNCTION(zend_test_zend_ini_str)
530 {
531 	ZEND_PARSE_PARAMETERS_NONE();
532 
533 	RETURN_STR(ZT_G(str_test));
534 }
535 
ZEND_FUNCTION(zend_test_is_string_marked_as_valid_utf8)536 static ZEND_FUNCTION(zend_test_is_string_marked_as_valid_utf8)
537 {
538 	zend_string *str;
539 
540 	ZEND_PARSE_PARAMETERS_START(1, 1)
541 		Z_PARAM_STR(str)
542 	ZEND_PARSE_PARAMETERS_END();
543 
544 	RETURN_BOOL(ZSTR_IS_VALID_UTF8(str));
545 }
546 
ZEND_FUNCTION(ZendTestNS2_namespaced_func)547 static ZEND_FUNCTION(ZendTestNS2_namespaced_func)
548 {
549 	ZEND_PARSE_PARAMETERS_NONE();
550 	RETURN_TRUE;
551 }
552 
ZEND_FUNCTION(ZendTestNS2_namespaced_deprecated_func)553 static ZEND_FUNCTION(ZendTestNS2_namespaced_deprecated_func)
554 {
555 	ZEND_PARSE_PARAMETERS_NONE();
556 }
557 
ZEND_FUNCTION(ZendTestNS2_ZendSubNS_namespaced_func)558 static ZEND_FUNCTION(ZendTestNS2_ZendSubNS_namespaced_func)
559 {
560 	ZEND_PARSE_PARAMETERS_NONE();
561 	RETURN_TRUE;
562 }
563 
ZEND_FUNCTION(ZendTestNS2_ZendSubNS_namespaced_deprecated_func)564 static ZEND_FUNCTION(ZendTestNS2_ZendSubNS_namespaced_deprecated_func)
565 {
566 	ZEND_PARSE_PARAMETERS_NONE();
567 }
568 
ZEND_FUNCTION(zend_test_parameter_with_attribute)569 static ZEND_FUNCTION(zend_test_parameter_with_attribute)
570 {
571 	zend_string *parameter;
572 
573 	ZEND_PARSE_PARAMETERS_START(1, 1)
574 		Z_PARAM_STR(parameter)
575 	ZEND_PARSE_PARAMETERS_END();
576 
577 	RETURN_LONG(1);
578 }
579 
ZEND_FUNCTION(zend_test_attribute_with_named_argument)580 static ZEND_FUNCTION(zend_test_attribute_with_named_argument)
581 {
582 	ZEND_PARSE_PARAMETERS_NONE();
583 }
584 
585 #ifdef ZEND_CHECK_STACK_LIMIT
ZEND_FUNCTION(zend_test_zend_call_stack_get)586 static ZEND_FUNCTION(zend_test_zend_call_stack_get)
587 {
588 	zend_call_stack stack;
589 
590 	ZEND_PARSE_PARAMETERS_NONE();
591 
592 	if (zend_call_stack_get(&stack)) {
593 		zend_string *str;
594 
595 		array_init(return_value);
596 
597 		str = strpprintf(0, "%p", stack.base);
598 		add_assoc_str(return_value, "base", str);
599 
600 		str = strpprintf(0, "0x%zx", stack.max_size);
601 		add_assoc_str(return_value, "max_size", str);
602 
603 		str = strpprintf(0, "%p", zend_call_stack_position());
604 		add_assoc_str(return_value, "position", str);
605 
606 		str = strpprintf(0, "%p", EG(stack_limit));
607 		add_assoc_str(return_value, "EG(stack_limit)", str);
608 
609 		return;
610 	}
611 
612 	RETURN_NULL();
613 }
614 
615 zend_long (*volatile zend_call_stack_use_all_fun)(void *limit);
616 
zend_call_stack_use_all(void * limit)617 static zend_long zend_call_stack_use_all(void *limit)
618 {
619 	if (zend_call_stack_overflowed(limit)) {
620 		return 1;
621 	}
622 
623 	return 1 + zend_call_stack_use_all_fun(limit);
624 }
625 
ZEND_FUNCTION(zend_test_zend_call_stack_use_all)626 static ZEND_FUNCTION(zend_test_zend_call_stack_use_all)
627 {
628 	zend_call_stack stack;
629 
630 	ZEND_PARSE_PARAMETERS_NONE();
631 
632 	if (!zend_call_stack_get(&stack)) {
633 		return;
634 	}
635 
636 	zend_call_stack_use_all_fun = zend_call_stack_use_all;
637 
638 	void *limit = zend_call_stack_limit(stack.base, stack.max_size, 4096);
639 
640 	RETURN_LONG(zend_call_stack_use_all(limit));
641 }
642 #endif /* ZEND_CHECK_STACK_LIMIT */
643 
ZEND_FUNCTION(zend_get_map_ptr_last)644 static ZEND_FUNCTION(zend_get_map_ptr_last)
645 {
646 	ZEND_PARSE_PARAMETERS_NONE();
647 	RETURN_LONG(CG(map_ptr_last));
648 }
649 
ZEND_FUNCTION(zend_test_crash)650 static ZEND_FUNCTION(zend_test_crash)
651 {
652 	zend_string *message = NULL;
653 
654 	ZEND_PARSE_PARAMETERS_START(0, 1)
655 		Z_PARAM_OPTIONAL
656 		Z_PARAM_STR_OR_NULL(message)
657 	ZEND_PARSE_PARAMETERS_END();
658 
659 	if (message) {
660 		php_printf("%s", ZSTR_VAL(message));
661 	}
662 
663 	char *invalid = (char *) 1;
664 	php_printf("%s", invalid);
665 }
666 
has_opline(zend_execute_data * execute_data)667 static bool has_opline(zend_execute_data *execute_data)
668 {
669 	return execute_data
670 		&& execute_data->func
671 		&& ZEND_USER_CODE(execute_data->func->type)
672 		&& execute_data->opline
673 	;
674 }
675 
zend_test_custom_malloc(size_t len ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)676 void * zend_test_custom_malloc(size_t len ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
677 {
678 	if (has_opline(EG(current_execute_data))) {
679 		assert(EG(current_execute_data)->opline->lineno != (uint32_t)-1);
680 	}
681 	return _zend_mm_alloc(ZT_G(zend_orig_heap), len ZEND_FILE_LINE_EMPTY_CC ZEND_FILE_LINE_EMPTY_CC);
682 }
683 
zend_test_custom_free(void * ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)684 void zend_test_custom_free(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
685 {
686 	if (has_opline(EG(current_execute_data))) {
687 		assert(EG(current_execute_data)->opline->lineno != (uint32_t)-1);
688 	}
689 	_zend_mm_free(ZT_G(zend_orig_heap), ptr ZEND_FILE_LINE_EMPTY_CC ZEND_FILE_LINE_EMPTY_CC);
690 }
691 
zend_test_custom_realloc(void * ptr,size_t len ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)692 void * zend_test_custom_realloc(void * ptr, size_t len ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
693 {
694 	if (has_opline(EG(current_execute_data))) {
695 		assert(EG(current_execute_data)->opline->lineno != (uint32_t)-1);
696 	}
697 	return _zend_mm_realloc(ZT_G(zend_orig_heap), ptr, len ZEND_FILE_LINE_EMPTY_CC ZEND_FILE_LINE_EMPTY_CC);
698 }
699 
PHP_INI_MH(OnUpdateZendTestObserveOplineInZendMM)700 static PHP_INI_MH(OnUpdateZendTestObserveOplineInZendMM)
701 {
702 	if (new_value == NULL) {
703 		return FAILURE;
704 	}
705 
706 	int int_value = zend_ini_parse_bool(new_value);
707 
708 	if (int_value == 1) {
709 		// `zend_mm_heap` is a private struct, so we have not way to find the
710 		// actual size, but 4096 bytes should be enough
711 		ZT_G(zend_test_heap) = malloc(4096);
712 		memset(ZT_G(zend_test_heap), 0, 4096);
713 		zend_mm_set_custom_handlers(
714 			ZT_G(zend_test_heap),
715 			zend_test_custom_malloc,
716 			zend_test_custom_free,
717 			zend_test_custom_realloc
718 		);
719 		ZT_G(zend_orig_heap) = zend_mm_get_heap();
720 		zend_mm_set_heap(ZT_G(zend_test_heap));
721 	} else if (ZT_G(zend_test_heap))  {
722 		free(ZT_G(zend_test_heap));
723 		ZT_G(zend_test_heap) = NULL;
724 		zend_mm_set_heap(ZT_G(zend_orig_heap));
725 	}
726 	return OnUpdateBool(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
727 }
728 
ZEND_FUNCTION(zend_test_fill_packed_array)729 static ZEND_FUNCTION(zend_test_fill_packed_array)
730 {
731 	HashTable *parameter;
732 
733 	ZEND_PARSE_PARAMETERS_START(1, 1)
734 		Z_PARAM_ARRAY_HT_EX(parameter, 0, 1)
735 	ZEND_PARSE_PARAMETERS_END();
736 
737 	if (!HT_IS_PACKED(parameter)) {
738 		zend_argument_value_error(1, "must be a packed array");
739 		RETURN_THROWS();
740 	}
741 
742 	zend_hash_extend(parameter, parameter->nNumUsed + 10, true);
743 	ZEND_HASH_FILL_PACKED(parameter) {
744 		for (int i = 0; i < 10; i++) {
745 			zval value;
746 			ZVAL_LONG(&value, i);
747 			ZEND_HASH_FILL_ADD(&value);
748 		}
749 	} ZEND_HASH_FILL_END();
750 }
751 
ZEND_FUNCTION(get_open_basedir)752 static ZEND_FUNCTION(get_open_basedir)
753 {
754 	ZEND_PARSE_PARAMETERS_NONE();
755 	if (PG(open_basedir)) {
756 		RETURN_STRING(PG(open_basedir));
757 	} else {
758 		RETURN_NULL();
759 	}
760 }
761 
ZEND_FUNCTION(zend_test_is_pcre_bundled)762 static ZEND_FUNCTION(zend_test_is_pcre_bundled)
763 {
764 	ZEND_PARSE_PARAMETERS_NONE();
765 #ifdef HAVE_BUNDLED_PCRE
766 	RETURN_TRUE;
767 #else
768 	RETURN_FALSE;
769 #endif
770 }
771 
772 #ifdef PHP_WIN32
ZEND_FUNCTION(zend_test_set_fmode)773 static ZEND_FUNCTION(zend_test_set_fmode)
774 {
775 	bool binary;
776 	ZEND_PARSE_PARAMETERS_START(1, 1)
777 		Z_PARAM_BOOL(binary)
778 	ZEND_PARSE_PARAMETERS_END();
779 
780 	_fmode = binary ? _O_BINARY : _O_TEXT;
781 }
782 #endif
783 
ZEND_FUNCTION(zend_test_cast_fread)784 static ZEND_FUNCTION(zend_test_cast_fread)
785 {
786 	zval *stream_zv;
787 	php_stream *stream;
788 	FILE *fp;
789 
790 	ZEND_PARSE_PARAMETERS_START(1, 1)
791 		Z_PARAM_RESOURCE(stream_zv);
792 	ZEND_PARSE_PARAMETERS_END();
793 
794 	php_stream_from_zval(stream, stream_zv);
795 
796 	if (php_stream_cast(stream, PHP_STREAM_AS_STDIO, (void *) &fp, REPORT_ERRORS) == FAILURE) {
797 		return;
798 	}
799 
800 	size_t size = 10240; /* Must be large enough to trigger the issue */
801 	char *buf = malloc(size);
802 	bool bail = false;
803 	zend_try {
804 		(void) !fread(buf, 1, size, fp);
805 	} zend_catch {
806 		bail = true;
807 	} zend_end_try();
808 
809 	free(buf);
810 
811 	if (bail) {
812 		zend_bailout();
813 	}
814 }
815 
ZEND_FUNCTION(zend_test_is_zend_ptr)816 static ZEND_FUNCTION(zend_test_is_zend_ptr)
817 {
818 	zend_long addr;
819 
820 	ZEND_PARSE_PARAMETERS_START(1, 1)
821 		Z_PARAM_LONG(addr);
822 	ZEND_PARSE_PARAMETERS_END();
823 
824 	RETURN_BOOL(is_zend_ptr((void*)addr));
825 }
826 
ZEND_FUNCTION(zend_test_log_err_debug)827 static ZEND_FUNCTION(zend_test_log_err_debug)
828 {
829 	zend_string *str;
830 
831 	ZEND_PARSE_PARAMETERS_START(1, 1)
832 		Z_PARAM_STR(str);
833 	ZEND_PARSE_PARAMETERS_END();
834 
835 	php_log_err_with_severity(ZSTR_VAL(str), LOG_DEBUG);
836 }
837 
zend_test_class_new(zend_class_entry * class_type)838 static zend_object *zend_test_class_new(zend_class_entry *class_type)
839 {
840 	zend_object *obj = zend_objects_new(class_type);
841 	object_properties_init(obj, class_type);
842 	obj->handlers = &zend_test_class_handlers;
843 	return obj;
844 }
845 
zend_test_class_method_get(zend_object ** object,zend_string * name,const zval * key)846 static zend_function *zend_test_class_method_get(zend_object **object, zend_string *name, const zval *key)
847 {
848 	if (zend_string_equals_literal_ci(name, "test")) {
849 		zend_internal_function *fptr;
850 
851 		if (EXPECTED(EG(trampoline).common.function_name == NULL)) {
852 			fptr = (zend_internal_function *) &EG(trampoline);
853 		} else {
854 			fptr = emalloc(sizeof(zend_internal_function));
855 	    }
856 		memset(fptr, 0, sizeof(zend_internal_function));
857 		fptr->type = ZEND_INTERNAL_FUNCTION;
858 		fptr->num_args = 0;
859 		fptr->scope = (*object)->ce;
860 		fptr->fn_flags = ZEND_ACC_CALL_VIA_HANDLER;
861 		fptr->function_name = zend_string_copy(name);
862 		fptr->handler = ZEND_FN(zend_test_func);
863 		fptr->doc_comment = NULL;
864 
865 		return (zend_function*)fptr;
866 	}
867 	return zend_std_get_method(object, name, key);
868 }
869 
zend_test_class_static_method_get(zend_class_entry * ce,zend_string * name)870 static zend_function *zend_test_class_static_method_get(zend_class_entry *ce, zend_string *name)
871 {
872 	if (zend_string_equals_literal_ci(name, "test")) {
873 		zend_internal_function *fptr;
874 
875 		if (EXPECTED(EG(trampoline).common.function_name == NULL)) {
876 			fptr = (zend_internal_function *) &EG(trampoline);
877 		} else {
878 			fptr = emalloc(sizeof(zend_internal_function));
879 		}
880 		memset(fptr, 0, sizeof(zend_internal_function));
881 		fptr->type = ZEND_INTERNAL_FUNCTION;
882 		fptr->num_args = 0;
883 		fptr->scope = ce;
884 		fptr->fn_flags = ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_STATIC;
885 		fptr->function_name = zend_string_copy(name);
886 		fptr->handler = ZEND_FN(zend_test_func);
887 		fptr->doc_comment = NULL;
888 
889 		return (zend_function*)fptr;
890 	}
891 	return zend_std_get_static_method(ce, name, NULL);
892 }
893 
zend_attribute_validate_zendtestattribute(zend_attribute * attr,uint32_t target,zend_class_entry * scope)894 void zend_attribute_validate_zendtestattribute(zend_attribute *attr, uint32_t target, zend_class_entry *scope)
895 {
896 	if (target != ZEND_ATTRIBUTE_TARGET_CLASS) {
897 		zend_error(E_COMPILE_ERROR, "Only classes can be marked with #[ZendTestAttribute]");
898 	}
899 }
900 
ZEND_METHOD(_ZendTestClass,__toString)901 static ZEND_METHOD(_ZendTestClass, __toString)
902 {
903 	ZEND_PARSE_PARAMETERS_NONE();
904 	RETURN_EMPTY_STRING();
905 }
906 
907 /* Internal function returns bool, we return int. */
ZEND_METHOD(_ZendTestClass,is_object)908 static ZEND_METHOD(_ZendTestClass, is_object)
909 {
910 	ZEND_PARSE_PARAMETERS_NONE();
911 	RETURN_LONG(42);
912 }
913 
ZEND_METHOD(_ZendTestClass,returnsStatic)914 static ZEND_METHOD(_ZendTestClass, returnsStatic) {
915 	ZEND_PARSE_PARAMETERS_NONE();
916 	object_init_ex(return_value, zend_get_called_scope(execute_data));
917 }
918 
ZEND_METHOD(_ZendTestClass,returnsThrowable)919 static ZEND_METHOD(_ZendTestClass, returnsThrowable)
920 {
921 	ZEND_PARSE_PARAMETERS_NONE();
922 	zend_throw_error(NULL, "Dummy");
923 }
924 
ZEND_METHOD(_ZendTestClass,variadicTest)925 static ZEND_METHOD(_ZendTestClass, variadicTest) {
926 	int      argc, i;
927 	zval    *args = NULL;
928 
929 	ZEND_PARSE_PARAMETERS_START(0, -1)
930 		Z_PARAM_VARIADIC('*', args, argc)
931 	ZEND_PARSE_PARAMETERS_END();
932 
933 	for (i = 0; i < argc; i++) {
934 		zval *arg = args + i;
935 
936 		if (Z_TYPE_P(arg) == IS_STRING) {
937 			continue;
938 		}
939 		if (Z_TYPE_P(arg) == IS_OBJECT && instanceof_function(Z_OBJ_P(arg)->ce, zend_ce_iterator)) {
940 			continue;
941 		}
942 
943 		zend_argument_type_error(i + 1, "must be of class Iterator or a string, %s given", zend_zval_type_name(arg));
944 		RETURN_THROWS();
945 	}
946 
947 	object_init_ex(return_value, zend_get_called_scope(execute_data));
948 }
949 
ZEND_METHOD(_ZendTestChildClass,returnsThrowable)950 static ZEND_METHOD(_ZendTestChildClass, returnsThrowable)
951 {
952 	ZEND_PARSE_PARAMETERS_NONE();
953 	zend_throw_error(NULL, "Dummy");
954 }
955 
ZEND_METHOD(ZendAttributeTest,testMethod)956 static ZEND_METHOD(ZendAttributeTest, testMethod)
957 {
958 	ZEND_PARSE_PARAMETERS_NONE();
959 	RETURN_TRUE;
960 }
961 
ZEND_METHOD(_ZendTestTrait,testMethod)962 static ZEND_METHOD(_ZendTestTrait, testMethod)
963 {
964 	ZEND_PARSE_PARAMETERS_NONE();
965 	RETURN_TRUE;
966 }
967 
ZEND_METHOD(ZendTestNS_Foo,method)968 static ZEND_METHOD(ZendTestNS_Foo, method)
969 {
970 	ZEND_PARSE_PARAMETERS_NONE();
971 
972 	RETURN_LONG(0);
973 }
974 
ZEND_METHOD(ZendTestNS_UnlikelyCompileError,method)975 static ZEND_METHOD(ZendTestNS_UnlikelyCompileError, method)
976 {
977 	ZEND_PARSE_PARAMETERS_NONE();
978 
979 	RETURN_NULL();
980 }
981 
ZEND_METHOD(ZendTestNS_NotUnlikelyCompileError,method)982 static ZEND_METHOD(ZendTestNS_NotUnlikelyCompileError, method)
983 {
984 	ZEND_PARSE_PARAMETERS_NONE();
985 
986 	RETURN_NULL();
987 }
988 
ZEND_METHOD(ZendTestNS2_Foo,method)989 static ZEND_METHOD(ZendTestNS2_Foo, method)
990 {
991 	ZEND_PARSE_PARAMETERS_NONE();
992 }
993 
ZEND_METHOD(ZendTestNS2_ZendSubNS_Foo,method)994 static ZEND_METHOD(ZendTestNS2_ZendSubNS_Foo, method)
995 {
996 	ZEND_PARSE_PARAMETERS_NONE();
997 }
998 
ZEND_METHOD(ZendTestParameterAttribute,__construct)999 static ZEND_METHOD(ZendTestParameterAttribute, __construct)
1000 {
1001 	zend_string *parameter;
1002 
1003 	ZEND_PARSE_PARAMETERS_START(1, 1)
1004 		Z_PARAM_STR(parameter)
1005 	ZEND_PARSE_PARAMETERS_END();
1006 
1007 	ZVAL_STR_COPY(OBJ_PROP_NUM(Z_OBJ_P(ZEND_THIS), 0), parameter);
1008 }
1009 
ZEND_METHOD(ZendTestPropertyAttribute,__construct)1010 static ZEND_METHOD(ZendTestPropertyAttribute, __construct)
1011 {
1012 	zend_string *parameter;
1013 
1014 	ZEND_PARSE_PARAMETERS_START(1, 1)
1015 		Z_PARAM_STR(parameter)
1016 	ZEND_PARSE_PARAMETERS_END();
1017 
1018 	ZVAL_STR_COPY(OBJ_PROP_NUM(Z_OBJ_P(ZEND_THIS), 0), parameter);
1019 }
1020 
ZEND_METHOD(ZendTestAttributeWithArguments,__construct)1021 static ZEND_METHOD(ZendTestAttributeWithArguments, __construct)
1022 {
1023 	zval *arg;
1024 
1025 	ZEND_PARSE_PARAMETERS_START(1, 1)
1026 		Z_PARAM_ZVAL(arg)
1027 	ZEND_PARSE_PARAMETERS_END();
1028 
1029 	zend_string *property_name = zend_string_init("arg", strlen("arg"), 0);
1030 	zend_update_property_ex(zend_test_attribute_with_arguments, Z_OBJ_P(ZEND_THIS), property_name, arg);
1031 	zend_string_release(property_name);
1032 }
1033 
ZEND_METHOD(ZendTestClassWithMethodWithParameterAttribute,no_override)1034 static ZEND_METHOD(ZendTestClassWithMethodWithParameterAttribute, no_override)
1035 {
1036 	zend_string *parameter;
1037 
1038 	ZEND_PARSE_PARAMETERS_START(1, 1)
1039 		Z_PARAM_STR(parameter)
1040 	ZEND_PARSE_PARAMETERS_END();
1041 
1042 	RETURN_LONG(2);
1043 }
1044 
ZEND_METHOD(ZendTestClassWithMethodWithParameterAttribute,override)1045 static ZEND_METHOD(ZendTestClassWithMethodWithParameterAttribute, override)
1046 {
1047 	zend_string *parameter;
1048 
1049 	ZEND_PARSE_PARAMETERS_START(1, 1)
1050 		Z_PARAM_STR(parameter)
1051 	ZEND_PARSE_PARAMETERS_END();
1052 
1053 	RETURN_LONG(3);
1054 }
1055 
ZEND_METHOD(ZendTestChildClassWithMethodWithParameterAttribute,override)1056 static ZEND_METHOD(ZendTestChildClassWithMethodWithParameterAttribute, override)
1057 {
1058 	zend_string *parameter;
1059 
1060 	ZEND_PARSE_PARAMETERS_START(1, 1)
1061 		Z_PARAM_STR(parameter)
1062 	ZEND_PARSE_PARAMETERS_END();
1063 
1064 	RETURN_LONG(4);
1065 }
1066 
ZEND_METHOD(ZendTestForbidDynamicCall,call)1067 static ZEND_METHOD(ZendTestForbidDynamicCall, call)
1068 {
1069 	ZEND_PARSE_PARAMETERS_NONE();
1070 
1071 	zend_forbid_dynamic_call();
1072 }
1073 
ZEND_METHOD(ZendTestForbidDynamicCall,callStatic)1074 static ZEND_METHOD(ZendTestForbidDynamicCall, callStatic)
1075 {
1076 	ZEND_PARSE_PARAMETERS_NONE();
1077 
1078 	zend_forbid_dynamic_call();
1079 }
1080 
ZEND_METHOD(_ZendTestMagicCall,__call)1081 static ZEND_METHOD(_ZendTestMagicCall, __call)
1082 {
1083 	zend_string *name;
1084 	zval *arguments;
1085 
1086 	ZEND_PARSE_PARAMETERS_START(2, 2)
1087 		Z_PARAM_STR(name)
1088 		Z_PARAM_ARRAY(arguments)
1089 	ZEND_PARSE_PARAMETERS_END();
1090 
1091 	zval name_zv;
1092 	ZVAL_STR(&name_zv, name);
1093 
1094 	zend_string_addref(name);
1095 	Z_TRY_ADDREF_P(arguments);
1096 	RETURN_ARR(zend_new_pair(&name_zv, arguments));
1097 }
1098 
ZEND_METHOD(_ZendTestMagicCallForward,__call)1099 static ZEND_METHOD(_ZendTestMagicCallForward, __call)
1100 {
1101 	zend_string *name;
1102 	zval *arguments;
1103 
1104 	ZEND_PARSE_PARAMETERS_START(2, 2)
1105 		Z_PARAM_STR(name)
1106 		Z_PARAM_ARRAY(arguments)
1107 	ZEND_PARSE_PARAMETERS_END();
1108 
1109 	ZEND_IGNORE_VALUE(arguments);
1110 
1111 	zval func;
1112 	ZVAL_STR(&func, name);
1113 	call_user_function(NULL, NULL, &func, return_value, 0, NULL);
1114 }
1115 
1116 PHP_INI_BEGIN()
1117 	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)
1118 	STD_PHP_INI_BOOLEAN("zend_test.register_passes", "0", PHP_INI_SYSTEM, OnUpdateBool, register_passes, zend_zend_test_globals, zend_test_globals)
1119 	STD_PHP_INI_BOOLEAN("zend_test.print_stderr_mshutdown", "0", PHP_INI_SYSTEM, OnUpdateBool, print_stderr_mshutdown, zend_zend_test_globals, zend_test_globals)
1120 #ifdef HAVE_COPY_FILE_RANGE
1121 	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)
1122 #endif
1123 	STD_PHP_INI_ENTRY("zend_test.quantity_value", "0", PHP_INI_ALL, OnUpdateLong, quantity_value, zend_zend_test_globals, zend_test_globals)
1124 	STD_PHP_INI_ENTRY("zend_test.str_test", "", PHP_INI_ALL, OnUpdateStr, str_test, zend_zend_test_globals, zend_test_globals)
1125 	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)
1126 	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)
1127 PHP_INI_END()
1128 
1129 void (*old_zend_execute_ex)(zend_execute_data *execute_data);
custom_zend_execute_ex(zend_execute_data * execute_data)1130 static void custom_zend_execute_ex(zend_execute_data *execute_data)
1131 {
1132 	old_zend_execute_ex(execute_data);
1133 }
1134 
le_throwing_resource_dtor(zend_resource * rsrc)1135 static void le_throwing_resource_dtor(zend_resource *rsrc)
1136 {
1137 	zend_throw_exception(NULL, "Throwing resource destructor called", 0);
1138 }
1139 
ZEND_METHOD(_ZendTestClass,takesUnionType)1140 static ZEND_METHOD(_ZendTestClass, takesUnionType)
1141 {
1142 	zend_object *obj;
1143 	ZEND_PARSE_PARAMETERS_START(1, 1);
1144 		Z_PARAM_OBJ(obj)
1145 	ZEND_PARSE_PARAMETERS_END();
1146 	// we have to perform type-checking to avoid arginfo/zpp mismatch error
1147 	bool type_matches = (
1148 		instanceof_function(obj->ce, zend_standard_class_def)
1149 		||
1150 		instanceof_function(obj->ce, zend_ce_iterator)
1151 	);
1152 	if (!type_matches) {
1153 		zend_string *ty = zend_type_to_string(execute_data->func->internal_function.arg_info->type);
1154 		zend_argument_type_error(1, "must be of type %s, %s given", ty->val, obj->ce->name->val);
1155 		zend_string_release(ty);
1156 		RETURN_THROWS();
1157 	}
1158 
1159 	RETURN_NULL();
1160 }
1161 
1162 // Returns a newly allocated DNF type `Iterator|(Traversable&Countable)`.
1163 //
1164 // We need to generate it "manually" because gen_stubs.php does not support codegen for DNF types ATM.
create_test_dnf_type(void)1165 static zend_type create_test_dnf_type(void) {
1166 	zend_string *class_Iterator = zend_string_init_interned("Iterator", sizeof("Iterator") - 1, true);
1167 	zend_alloc_ce_cache(class_Iterator);
1168 	zend_string *class_Traversable = ZSTR_KNOWN(ZEND_STR_TRAVERSABLE);
1169 	zend_string *class_Countable = zend_string_init_interned("Countable", sizeof("Countable") - 1, true);
1170 	zend_alloc_ce_cache(class_Countable);
1171 	//
1172 	zend_type_list *intersection_list = malloc(ZEND_TYPE_LIST_SIZE(2));
1173 	intersection_list->num_types = 2;
1174 	intersection_list->types[0] = (zend_type) ZEND_TYPE_INIT_CLASS(class_Traversable, 0, 0);
1175 	intersection_list->types[1] = (zend_type) ZEND_TYPE_INIT_CLASS(class_Countable, 0, 0);
1176 	zend_type_list *union_list = malloc(ZEND_TYPE_LIST_SIZE(2));
1177 	union_list->num_types = 2;
1178 	union_list->types[0] = (zend_type) ZEND_TYPE_INIT_CLASS(class_Iterator, 0, 0);
1179 	union_list->types[1] = (zend_type) ZEND_TYPE_INIT_INTERSECTION(intersection_list, 0);
1180 	return (zend_type) ZEND_TYPE_INIT_UNION(union_list, 0);
1181 }
1182 
register_ZendTestClass_dnf_property(zend_class_entry * ce)1183 static void register_ZendTestClass_dnf_property(zend_class_entry *ce) {
1184 	zend_string *prop_name = zend_string_init_interned("dnfProperty", sizeof("dnfProperty") - 1, true);
1185 	zval default_value;
1186 	ZVAL_UNDEF(&default_value);
1187 	zend_type type = create_test_dnf_type();
1188 	zend_declare_typed_property(ce, prop_name, &default_value, ZEND_ACC_PUBLIC, NULL, type);
1189 }
1190 
1191 // arg_info for `zend_test_internal_dnf_arguments`
1192 // The types are upgraded to DNF types in `register_dynamic_function_entries()`
1193 static zend_internal_arg_info arginfo_zend_test_internal_dnf_arguments[] = {
1194 	// first entry is a zend_internal_function_info (see zend_compile.h): {argument_count, return_type, unused}
1195 	{(const char*)(uintptr_t)(1), {0}, NULL},
1196 	{"arg", {0}, NULL}
1197 };
1198 
ZEND_NAMED_FUNCTION(zend_test_internal_dnf_arguments)1199 static ZEND_NAMED_FUNCTION(zend_test_internal_dnf_arguments)
1200 {
1201 	zend_object *obj;
1202 	ZEND_PARSE_PARAMETERS_START(1, 1);
1203 		Z_PARAM_OBJ(obj)
1204 	ZEND_PARSE_PARAMETERS_END();
1205 	// we have to perform type-checking to avoid arginfo/zpp mismatch error
1206 	bool type_matches = (
1207 		instanceof_function(obj->ce, zend_ce_iterator)
1208 		|| (
1209 			instanceof_function(obj->ce, zend_ce_traversable)
1210 			&& instanceof_function(obj->ce, zend_ce_countable)
1211 		)
1212 	);
1213 	if (!type_matches) {
1214 		zend_string *ty = zend_type_to_string(arginfo_zend_test_internal_dnf_arguments[1].type);
1215 		zend_argument_type_error(1, "must be of type %s, %s given", ty->val, obj->ce->name->val);
1216 		zend_string_release(ty);
1217 		RETURN_THROWS();
1218 	}
1219 
1220 	RETURN_OBJ_COPY(obj);
1221 }
1222 
1223 static const zend_function_entry dynamic_function_entries[] = {
1224 	{
1225 		.fname = "zend_test_internal_dnf_arguments",
1226 		.handler = zend_test_internal_dnf_arguments,
1227 		.arg_info = arginfo_zend_test_internal_dnf_arguments,
1228 		.num_args = 1,
1229 		.flags = 0,
1230 	},
1231 	ZEND_FE_END,
1232 };
1233 
register_dynamic_function_entries(int module_type)1234 static void register_dynamic_function_entries(int module_type) {
1235 	// return-type is at index 0
1236 	arginfo_zend_test_internal_dnf_arguments[0].type = create_test_dnf_type();
1237 	arginfo_zend_test_internal_dnf_arguments[1].type = create_test_dnf_type();
1238 	//
1239 	zend_register_functions(NULL, dynamic_function_entries, NULL, module_type);
1240 }
1241 
PHP_MINIT_FUNCTION(zend_test)1242 PHP_MINIT_FUNCTION(zend_test)
1243 {
1244 	register_dynamic_function_entries(type);
1245 
1246 	zend_test_interface = register_class__ZendTestInterface();
1247 
1248 	zend_test_class = register_class__ZendTestClass(zend_test_interface);
1249 	register_ZendTestClass_dnf_property(zend_test_class);
1250 	zend_test_class->create_object = zend_test_class_new;
1251 	zend_test_class->get_static_method = zend_test_class_static_method_get;
1252 
1253 	zend_test_child_class = register_class__ZendTestChildClass(zend_test_class);
1254 
1255 	memcpy(&zend_test_class_handlers, &std_object_handlers, sizeof(zend_object_handlers));
1256 	zend_test_class_handlers.get_method = zend_test_class_method_get;
1257 
1258 	zend_attribute_test_class = register_class_ZendAttributeTest();
1259 
1260 	zend_test_trait = register_class__ZendTestTrait();
1261 
1262 	register_test_symbols(module_number);
1263 
1264 	zend_test_attribute = register_class_ZendTestAttribute();
1265 	{
1266 		zend_internal_attribute *attr = zend_mark_internal_attribute(zend_test_attribute);
1267 		attr->validator = zend_attribute_validate_zendtestattribute;
1268 	}
1269 
1270 	zend_test_repeatable_attribute = register_class_ZendTestRepeatableAttribute();
1271 	zend_mark_internal_attribute(zend_test_repeatable_attribute);
1272 
1273 	zend_test_parameter_attribute = register_class_ZendTestParameterAttribute();
1274 	zend_mark_internal_attribute(zend_test_parameter_attribute);
1275 
1276 	zend_test_property_attribute = register_class_ZendTestPropertyAttribute();
1277 	zend_mark_internal_attribute(zend_test_property_attribute);
1278 
1279 	zend_test_attribute_with_arguments = register_class_ZendTestAttributeWithArguments();
1280 	zend_mark_internal_attribute(zend_test_attribute_with_arguments);
1281 
1282 	zend_test_class_with_method_with_parameter_attribute = register_class_ZendTestClassWithMethodWithParameterAttribute();
1283 	zend_test_child_class_with_method_with_parameter_attribute = register_class_ZendTestChildClassWithMethodWithParameterAttribute(zend_test_class_with_method_with_parameter_attribute);
1284 
1285 	zend_test_class_with_property_attribute = register_class_ZendTestClassWithPropertyAttribute();
1286 	{
1287 		zend_property_info *prop_info = zend_hash_str_find_ptr(&zend_test_class_with_property_attribute->properties_info, "attributed", sizeof("attributed") - 1);
1288 		zend_add_property_attribute(zend_test_class_with_property_attribute, prop_info, zend_test_attribute->name, 0);
1289 	}
1290 
1291 	zend_test_forbid_dynamic_call = register_class_ZendTestForbidDynamicCall();
1292 
1293 	zend_test_ns_foo_class = register_class_ZendTestNS_Foo();
1294 	zend_test_ns_unlikely_compile_error_class = register_class_ZendTestNS_UnlikelyCompileError();
1295 	zend_test_ns_not_unlikely_compile_error_class = register_class_ZendTestNS_NotUnlikelyCompileError();
1296 	zend_test_ns2_foo_class = register_class_ZendTestNS2_Foo();
1297 	zend_test_ns2_ns_foo_class = register_class_ZendTestNS2_ZendSubNS_Foo();
1298 
1299 	zend_test_unit_enum = register_class_ZendTestUnitEnum();
1300 	zend_test_string_enum = register_class_ZendTestStringEnum();
1301 	zend_test_int_enum = register_class_ZendTestIntEnum();
1302 
1303 	zend_test_magic_call = register_class__ZendTestMagicCall();
1304 
1305 	register_class__ZendTestMagicCallForward();
1306 
1307 	zend_register_functions(NULL, ext_function_legacy, NULL, EG(current_module)->type);
1308 
1309 	// Loading via dl() not supported with the observer API
1310 	if (type != MODULE_TEMPORARY) {
1311 		REGISTER_INI_ENTRIES();
1312 	} else {
1313 		(void)ini_entries;
1314 	}
1315 
1316 	if (ZT_G(replace_zend_execute_ex)) {
1317 		old_zend_execute_ex = zend_execute_ex;
1318 		zend_execute_ex = custom_zend_execute_ex;
1319 	}
1320 
1321 	if (ZT_G(register_passes)) {
1322 		zend_optimizer_register_pass(pass1);
1323 		zend_optimizer_register_pass(pass2);
1324 	}
1325 
1326 	zend_test_observer_init(INIT_FUNC_ARGS_PASSTHRU);
1327 	zend_test_mm_custom_handlers_minit(INIT_FUNC_ARGS_PASSTHRU);
1328 	zend_test_fiber_init();
1329 	zend_test_iterators_init();
1330 	zend_test_object_handlers_init();
1331 
1332 	le_throwing_resource = zend_register_list_destructors_ex(le_throwing_resource_dtor, NULL, "throwing resource", module_number);
1333 
1334 	return SUCCESS;
1335 }
1336 
PHP_MSHUTDOWN_FUNCTION(zend_test)1337 PHP_MSHUTDOWN_FUNCTION(zend_test)
1338 {
1339 	if (type != MODULE_TEMPORARY) {
1340 		UNREGISTER_INI_ENTRIES();
1341 	}
1342 
1343 	zend_test_observer_shutdown(SHUTDOWN_FUNC_ARGS_PASSTHRU);
1344 
1345 	if (ZT_G(print_stderr_mshutdown)) {
1346 		fprintf(stderr, "[zend_test] MSHUTDOWN\n");
1347 	}
1348 
1349 	return SUCCESS;
1350 }
1351 
PHP_RINIT_FUNCTION(zend_test)1352 PHP_RINIT_FUNCTION(zend_test)
1353 {
1354 	zend_hash_init(&ZT_G(global_weakmap), 8, NULL, ZVAL_PTR_DTOR, 0);
1355 	ZT_G(observer_nesting_depth) = 0;
1356 	zend_test_mm_custom_handlers_rinit();
1357 	return SUCCESS;
1358 }
1359 
PHP_RSHUTDOWN_FUNCTION(zend_test)1360 PHP_RSHUTDOWN_FUNCTION(zend_test)
1361 {
1362 	zend_weakrefs_hash_destroy(&ZT_G(global_weakmap));
1363 
1364 	if (ZT_G(zend_test_heap))  {
1365 		free(ZT_G(zend_test_heap));
1366 		ZT_G(zend_test_heap) = NULL;
1367 		zend_mm_set_heap(ZT_G(zend_orig_heap));
1368 	}
1369 
1370 	zend_test_mm_custom_handlers_rshutdown();
1371 	return SUCCESS;
1372 }
1373 
PHP_GINIT_FUNCTION(zend_test)1374 static PHP_GINIT_FUNCTION(zend_test)
1375 {
1376 #if defined(COMPILE_DL_ZEND_TEST) && defined(ZTS)
1377 	ZEND_TSRMLS_CACHE_UPDATE();
1378 #endif
1379 	memset(zend_test_globals, 0, sizeof(*zend_test_globals));
1380 
1381 	zend_test_observer_ginit(zend_test_globals);
1382 }
1383 
PHP_GSHUTDOWN_FUNCTION(zend_test)1384 static PHP_GSHUTDOWN_FUNCTION(zend_test)
1385 {
1386 	zend_test_observer_gshutdown(zend_test_globals);
1387 }
1388 
PHP_MINFO_FUNCTION(zend_test)1389 PHP_MINFO_FUNCTION(zend_test)
1390 {
1391 	php_info_print_table_start();
1392 	php_info_print_table_row(2, "zend_test extension", "enabled");
1393 	php_info_print_table_end();
1394 
1395 	DISPLAY_INI_ENTRIES();
1396 }
1397 
1398 zend_module_entry zend_test_module_entry = {
1399 	STANDARD_MODULE_HEADER,
1400 	"zend_test",
1401 	ext_functions,
1402 	PHP_MINIT(zend_test),
1403 	PHP_MSHUTDOWN(zend_test),
1404 	PHP_RINIT(zend_test),
1405 	PHP_RSHUTDOWN(zend_test),
1406 	PHP_MINFO(zend_test),
1407 	PHP_ZEND_TEST_VERSION,
1408 	PHP_MODULE_GLOBALS(zend_test),
1409 	PHP_GINIT(zend_test),
1410 	PHP_GSHUTDOWN(zend_test),
1411 	NULL,
1412 	STANDARD_MODULE_PROPERTIES_EX
1413 };
1414 
1415 #ifdef COMPILE_DL_ZEND_TEST
1416 # ifdef ZTS
1417 ZEND_TSRMLS_CACHE_DEFINE()
1418 # endif
ZEND_GET_MODULE(zend_test)1419 ZEND_GET_MODULE(zend_test)
1420 #endif
1421 
1422 /* The important part here is the ZEND_FASTCALL. */
1423 PHP_ZEND_TEST_API int ZEND_FASTCALL bug78270(const char *str, size_t str_len)
1424 {
1425 	char * copy = zend_strndup(str, str_len);
1426 	int r = (int) ZEND_ATOL(copy);
1427 	free(copy);
1428 	return r;
1429 }
1430 
bug79096(void)1431 PHP_ZEND_TEST_API struct bug79096 bug79096(void)
1432 {
1433 	struct bug79096 b;
1434 
1435 	b.a = 1;
1436 	b.b = 1;
1437 	return b;
1438 }
1439 
bug79532(off_t * array,size_t elems)1440 PHP_ZEND_TEST_API void bug79532(off_t *array, size_t elems)
1441 {
1442 	for (size_t i = 0; i < elems; i++) {
1443 		array[i] = i;
1444 	}
1445 }
1446 
1447 PHP_ZEND_TEST_API int *(*bug79177_cb)(void);
bug79177(void)1448 void bug79177(void)
1449 {
1450 	bug79177_cb();
1451 }
1452 
1453 typedef struct bug80847_01 {
1454 	uint64_t b;
1455 	double c;
1456 } bug80847_01;
1457 typedef struct bug80847_02 {
1458 	bug80847_01 a;
1459 } bug80847_02;
1460 
ffi_bug80847(bug80847_02 s)1461 PHP_ZEND_TEST_API bug80847_02 ffi_bug80847(bug80847_02 s) {
1462 	s.a.b += 10;
1463 	s.a.c -= 10.0;
1464 	return s;
1465 }
1466 
1467 PHP_ZEND_TEST_API void (*bug_gh9090_void_none_ptr)(void) = NULL;
1468 PHP_ZEND_TEST_API void (*bug_gh9090_void_int_char_ptr)(int, char *) = NULL;
1469 PHP_ZEND_TEST_API void (*bug_gh9090_void_int_char_var_ptr)(int, char *, ...) = NULL;
1470 PHP_ZEND_TEST_API void (*bug_gh9090_void_char_int_ptr)(char *, int) = NULL;
1471 PHP_ZEND_TEST_API int (*bug_gh9090_int_int_char_ptr)(int, char *) = NULL;
1472 
bug_gh9090_void_none(void)1473 PHP_ZEND_TEST_API void bug_gh9090_void_none(void) {
1474     php_printf("bug_gh9090_none\n");
1475 }
1476 
bug_gh9090_void_int_char(int i,char * s)1477 PHP_ZEND_TEST_API void bug_gh9090_void_int_char(int i, char *s) {
1478     php_printf("bug_gh9090_int_char %d %s\n", i, s);
1479 }
1480 
bug_gh9090_void_int_char_var(int i,char * fmt,...)1481 PHP_ZEND_TEST_API void bug_gh9090_void_int_char_var(int i, char *fmt, ...) {
1482     va_list args;
1483     char *buffer;
1484 
1485     va_start(args, fmt);
1486 
1487     zend_vspprintf(&buffer, 0, fmt, args);
1488     php_printf("bug_gh9090_void_int_char_var %s\n", buffer);
1489     efree(buffer);
1490 
1491     va_end(args);
1492 }
1493 
1494 PHP_ZEND_TEST_API int gh11934b_ffi_var_test_cdata;
1495 
1496 #ifdef HAVE_COPY_FILE_RANGE
1497 /**
1498  * This function allows us to simulate early return of copy_file_range by setting the limit_copy_file_range ini setting.
1499  */
1500 #ifdef __MUSL__
1501 typedef off_t off64_t;
1502 #endif
copy_file_range(int fd_in,off64_t * off_in,int fd_out,off64_t * off_out,size_t len,unsigned int flags)1503 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)
1504 {
1505 	ssize_t (*original_copy_file_range)(int, off64_t *, int, off64_t *, size_t, unsigned int) = dlsym(RTLD_NEXT, "copy_file_range");
1506 	if (ZT_G(limit_copy_file_range) >= Z_L(0)) {
1507 		len = ZT_G(limit_copy_file_range);
1508 	}
1509 	return original_copy_file_range(fd_in, off_in, fd_out, off_out, len, flags);
1510 }
1511 #endif
1512 
1513 
PHP_FUNCTION(zend_test_create_throwing_resource)1514 static PHP_FUNCTION(zend_test_create_throwing_resource)
1515 {
1516 	ZEND_PARSE_PARAMETERS_NONE();
1517 	zend_resource *res = zend_register_resource(NULL, le_throwing_resource);
1518 	ZVAL_RES(return_value, res);
1519 }
1520