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