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