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