1 /*
2 +----------------------------------------------------------------------+
3 | Zend Engine |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1998-2018 Zend Technologies Ltd. (http://www.zend.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 2.00 of the Zend license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.zend.com/license/2_00.txt. |
11 | If you did not receive a copy of the Zend license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@zend.com so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
15 | Authors: Andi Gutmans <andi@php.net> |
16 | Zeev Suraski <zeev@php.net> |
17 | Andrei Zmievski <andrei@php.net> |
18 | Dmitry Stogov <dmitry@php.net> |
19 +----------------------------------------------------------------------+
20 */
21
22 #include "zend.h"
23 #include "zend_execute.h"
24 #include "zend_API.h"
25 #include "zend_modules.h"
26 #include "zend_extensions.h"
27 #include "zend_constants.h"
28 #include "zend_interfaces.h"
29 #include "zend_exceptions.h"
30 #include "zend_closures.h"
31 #include "zend_inheritance.h"
32
33 #ifdef HAVE_STDARG_H
34 #include <stdarg.h>
35 #endif
36
37 /* these variables are true statics/globals, and have to be mutex'ed on every access */
38 ZEND_API HashTable module_registry;
39
40 static zend_module_entry **module_request_startup_handlers;
41 static zend_module_entry **module_request_shutdown_handlers;
42 static zend_module_entry **module_post_deactivate_handlers;
43
44 static zend_class_entry **class_cleanup_handlers;
45
_zend_get_parameters_array_ex(int param_count,zval * argument_array)46 ZEND_API int _zend_get_parameters_array_ex(int param_count, zval *argument_array) /* {{{ */
47 {
48 zval *param_ptr;
49 int arg_count;
50
51 param_ptr = ZEND_CALL_ARG(EG(current_execute_data), 1);
52 arg_count = ZEND_CALL_NUM_ARGS(EG(current_execute_data));
53
54 if (param_count>arg_count) {
55 return FAILURE;
56 }
57
58 while (param_count-->0) {
59 ZVAL_COPY_VALUE(argument_array, param_ptr);
60 argument_array++;
61 param_ptr++;
62 }
63
64 return SUCCESS;
65 }
66 /* }}} */
67
zend_copy_parameters_array(int param_count,zval * argument_array)68 ZEND_API int zend_copy_parameters_array(int param_count, zval *argument_array) /* {{{ */
69 {
70 zval *param_ptr;
71 int arg_count;
72
73 param_ptr = ZEND_CALL_ARG(EG(current_execute_data), 1);
74 arg_count = ZEND_CALL_NUM_ARGS(EG(current_execute_data));
75
76 if (param_count>arg_count) {
77 return FAILURE;
78 }
79
80 while (param_count-->0) {
81 Z_TRY_ADDREF_P(param_ptr);
82 zend_hash_next_index_insert_new(Z_ARRVAL_P(argument_array), param_ptr);
83 param_ptr++;
84 }
85
86 return SUCCESS;
87 }
88 /* }}} */
89
zend_wrong_param_count(void)90 ZEND_API ZEND_COLD void zend_wrong_param_count(void) /* {{{ */
91 {
92 const char *space;
93 const char *class_name = get_active_class_name(&space);
94
95 zend_internal_argument_count_error(ZEND_ARG_USES_STRICT_TYPES(), "Wrong parameter count for %s%s%s()", class_name, space, get_active_function_name());
96 }
97 /* }}} */
98
99 /* Argument parsing API -- andrei */
zend_get_type_by_const(int type)100 ZEND_API char *zend_get_type_by_const(int type) /* {{{ */
101 {
102 switch(type) {
103 case IS_FALSE:
104 case IS_TRUE:
105 case _IS_BOOL:
106 return "bool";
107 case IS_LONG:
108 return "int";
109 case IS_DOUBLE:
110 return "float";
111 case IS_STRING:
112 return "string";
113 case IS_OBJECT:
114 return "object";
115 case IS_RESOURCE:
116 return "resource";
117 case IS_NULL:
118 return "null";
119 case IS_CALLABLE:
120 return "callable";
121 case IS_ITERABLE:
122 return "iterable";
123 case IS_ARRAY:
124 return "array";
125 case IS_VOID:
126 return "void";
127 case _IS_NUMBER:
128 return "number";
129 default:
130 return "unknown";
131 }
132 }
133 /* }}} */
134
zend_zval_type_name(const zval * arg)135 ZEND_API char *zend_zval_type_name(const zval *arg) /* {{{ */
136 {
137 ZVAL_DEREF(arg);
138 return zend_get_type_by_const(Z_TYPE_P(arg));
139 }
140 /* }}} */
141
zend_zval_get_type(const zval * arg)142 ZEND_API zend_string *zend_zval_get_type(const zval *arg) /* {{{ */
143 {
144 switch (Z_TYPE_P(arg)) {
145 case IS_NULL:
146 return ZSTR_KNOWN(ZEND_STR_NULL);
147 case IS_FALSE:
148 case IS_TRUE:
149 return ZSTR_KNOWN(ZEND_STR_BOOLEAN);
150 case IS_LONG:
151 return ZSTR_KNOWN(ZEND_STR_INTEGER);
152 case IS_DOUBLE:
153 return ZSTR_KNOWN(ZEND_STR_DOUBLE);
154 case IS_STRING:
155 return ZSTR_KNOWN(ZEND_STR_STRING);
156 case IS_ARRAY:
157 return ZSTR_KNOWN(ZEND_STR_ARRAY);
158 case IS_OBJECT:
159 return ZSTR_KNOWN(ZEND_STR_OBJECT);
160 case IS_RESOURCE:
161 if (zend_rsrc_list_get_rsrc_type(Z_RES_P(arg))) {
162 return ZSTR_KNOWN(ZEND_STR_RESOURCE);
163 } else {
164 return ZSTR_KNOWN(ZEND_STR_CLOSED_RESOURCE);
165 }
166 default:
167 return NULL;
168 }
169 }
170 /* }}} */
171
zend_wrong_parameters_none_error(void)172 ZEND_API ZEND_COLD int ZEND_FASTCALL zend_wrong_parameters_none_error(void) /* {{{ */
173 {
174 int num_args = ZEND_CALL_NUM_ARGS(EG(current_execute_data));
175 zend_function *active_function = EG(current_execute_data)->func;
176 const char *class_name = active_function->common.scope ? ZSTR_VAL(active_function->common.scope->name) : "";
177
178 zend_internal_argument_count_error(
179 ZEND_ARG_USES_STRICT_TYPES(),
180 "%s%s%s() expects %s %d parameter%s, %d given",
181 class_name, \
182 class_name[0] ? "::" : "", \
183 ZSTR_VAL(active_function->common.function_name),
184 "exactly",
185 0,
186 "s",
187 num_args);
188 return FAILURE;
189 }
190 /* }}} */
191
zend_wrong_parameters_none_exception(void)192 ZEND_API ZEND_COLD int ZEND_FASTCALL zend_wrong_parameters_none_exception(void) /* {{{ */
193 {
194 int num_args = ZEND_CALL_NUM_ARGS(EG(current_execute_data));
195 zend_function *active_function = EG(current_execute_data)->func;
196 const char *class_name = active_function->common.scope ? ZSTR_VAL(active_function->common.scope->name) : "";
197
198 zend_internal_argument_count_error(
199 1,
200 "%s%s%s() expects %s %d parameter%s, %d given",
201 class_name, \
202 class_name[0] ? "::" : "", \
203 ZSTR_VAL(active_function->common.function_name),
204 "exactly",
205 0,
206 "s",
207 num_args);
208 return FAILURE;
209 }
210 /* }}} */
211
zend_wrong_parameters_count_error(int min_num_args,int max_num_args)212 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameters_count_error(int min_num_args, int max_num_args) /* {{{ */
213 {
214 int num_args = ZEND_CALL_NUM_ARGS(EG(current_execute_data));
215 zend_function *active_function = EG(current_execute_data)->func;
216 const char *class_name = active_function->common.scope ? ZSTR_VAL(active_function->common.scope->name) : "";
217
218 zend_internal_argument_count_error(
219 ZEND_ARG_USES_STRICT_TYPES(),
220 "%s%s%s() expects %s %d parameter%s, %d given",
221 class_name, \
222 class_name[0] ? "::" : "", \
223 ZSTR_VAL(active_function->common.function_name),
224 min_num_args == max_num_args ? "exactly" : num_args < min_num_args ? "at least" : "at most",
225 num_args < min_num_args ? min_num_args : max_num_args,
226 (num_args < min_num_args ? min_num_args : max_num_args) == 1 ? "" : "s",
227 num_args);
228 }
229 /* }}} */
230
zend_wrong_parameters_count_exception(int min_num_args,int max_num_args)231 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameters_count_exception(int min_num_args, int max_num_args) /* {{{ */
232 {
233 int num_args = ZEND_CALL_NUM_ARGS(EG(current_execute_data));
234 zend_function *active_function = EG(current_execute_data)->func;
235 const char *class_name = active_function->common.scope ? ZSTR_VAL(active_function->common.scope->name) : "";
236
237 zend_internal_argument_count_error(
238 1,
239 "%s%s%s() expects %s %d parameter%s, %d given",
240 class_name, \
241 class_name[0] ? "::" : "", \
242 ZSTR_VAL(active_function->common.function_name),
243 min_num_args == max_num_args ? "exactly" : num_args < min_num_args ? "at least" : "at most",
244 num_args < min_num_args ? min_num_args : max_num_args,
245 (num_args < min_num_args ? min_num_args : max_num_args) == 1 ? "" : "s",
246 num_args);
247 }
248 /* }}} */
249
zend_wrong_parameter_type_error(int num,zend_expected_type expected_type,zval * arg)250 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_type_error(int num, zend_expected_type expected_type, zval *arg) /* {{{ */
251 {
252 const char *space;
253 const char *class_name = get_active_class_name(&space);
254 static const char * const expected_error[] = {
255 Z_EXPECTED_TYPES(Z_EXPECTED_TYPE_STR)
256 NULL
257 };
258
259 zend_internal_type_error(ZEND_ARG_USES_STRICT_TYPES(), "%s%s%s() expects parameter %d to be %s, %s given",
260 class_name, space, get_active_function_name(), num, expected_error[expected_type], zend_zval_type_name(arg));
261 }
262 /* }}} */
263
zend_wrong_parameter_type_exception(int num,zend_expected_type expected_type,zval * arg)264 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_type_exception(int num, zend_expected_type expected_type, zval *arg) /* {{{ */
265 {
266 const char *space;
267 const char *class_name = get_active_class_name(&space);
268 static const char * const expected_error[] = {
269 Z_EXPECTED_TYPES(Z_EXPECTED_TYPE_STR)
270 NULL
271 };
272
273 zend_internal_type_error(1, "%s%s%s() expects parameter %d to be %s, %s given",
274 class_name, space, get_active_function_name(), num, expected_error[expected_type], zend_zval_type_name(arg));
275 }
276 /* }}} */
277
zend_wrong_parameter_class_error(int num,char * name,zval * arg)278 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_error(int num, char *name, zval *arg) /* {{{ */
279 {
280 const char *space;
281 const char *class_name = get_active_class_name(&space);
282
283 zend_internal_type_error(ZEND_ARG_USES_STRICT_TYPES(), "%s%s%s() expects parameter %d to be %s, %s given",
284 class_name, space, get_active_function_name(), num, name, zend_zval_type_name(arg));
285 }
286 /* }}} */
287
zend_wrong_parameter_class_exception(int num,char * name,zval * arg)288 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_exception(int num, char *name, zval *arg) /* {{{ */
289 {
290 const char *space;
291 const char *class_name = get_active_class_name(&space);
292
293 zend_internal_type_error(1, "%s%s%s() expects parameter %d to be %s, %s given",
294 class_name, space, get_active_function_name(), num, name, zend_zval_type_name(arg));
295 }
296 /* }}} */
297
zend_wrong_callback_error(int num,char * error)298 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_error(int num, char *error) /* {{{ */
299 {
300 const char *space;
301 const char *class_name = get_active_class_name(&space);
302
303 zend_internal_type_error(ZEND_ARG_USES_STRICT_TYPES(), "%s%s%s() expects parameter %d to be a valid callback, %s",
304 class_name, space, get_active_function_name(), num, error);
305 efree(error);
306 }
307 /* }}} */
308
zend_wrong_callback_exception(int num,char * error)309 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_exception(int num, char *error) /* {{{ */
310 {
311 const char *space;
312 const char *class_name = get_active_class_name(&space);
313
314 zend_internal_type_error(1, "%s%s%s() expects parameter %d to be a valid callback, %s",
315 class_name, space, get_active_function_name(), num, error);
316 efree(error);
317 }
318 /* }}} */
319
zend_wrong_callback_deprecated(int num,char * error)320 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_deprecated(int num, char *error) /* {{{ */
321 {
322 const char *space;
323 const char *class_name = get_active_class_name(&space);
324
325 zend_error(E_DEPRECATED, "%s%s%s() expects parameter %d to be a valid callback, %s",
326 class_name, space, get_active_function_name(), num, error);
327 efree(error);
328 }
329 /* }}} */
330
zend_parse_arg_class(zval * arg,zend_class_entry ** pce,int num,int check_null)331 ZEND_API int ZEND_FASTCALL zend_parse_arg_class(zval *arg, zend_class_entry **pce, int num, int check_null) /* {{{ */
332 {
333 zend_class_entry *ce_base = *pce;
334
335 if (check_null && Z_TYPE_P(arg) == IS_NULL) {
336 *pce = NULL;
337 return 1;
338 }
339 convert_to_string_ex(arg);
340 *pce = zend_lookup_class(Z_STR_P(arg));
341 if (ce_base) {
342 if ((!*pce || !instanceof_function(*pce, ce_base))) {
343 const char *space;
344 const char *class_name = get_active_class_name(&space);
345
346 zend_internal_type_error(ZEND_ARG_USES_STRICT_TYPES(), "%s%s%s() expects parameter %d to be a class name derived from %s, '%s' given",
347 class_name, space, get_active_function_name(), num,
348 ZSTR_VAL(ce_base->name), Z_STRVAL_P(arg));
349 *pce = NULL;
350 return 0;
351 }
352 }
353 if (!*pce) {
354 const char *space;
355 const char *class_name = get_active_class_name(&space);
356
357 zend_internal_type_error(ZEND_ARG_USES_STRICT_TYPES(), "%s%s%s() expects parameter %d to be a valid class name, '%s' given",
358 class_name, space, get_active_function_name(), num,
359 Z_STRVAL_P(arg));
360 return 0;
361 }
362 return 1;
363 }
364 /* }}} */
365
zend_parse_arg_bool_weak(zval * arg,zend_bool * dest)366 ZEND_API int ZEND_FASTCALL zend_parse_arg_bool_weak(zval *arg, zend_bool *dest) /* {{{ */
367 {
368 if (EXPECTED(Z_TYPE_P(arg) <= IS_STRING)) {
369 *dest = zend_is_true(arg);
370 } else {
371 return 0;
372 }
373 return 1;
374 }
375 /* }}} */
376
zend_parse_arg_bool_slow(zval * arg,zend_bool * dest)377 ZEND_API int ZEND_FASTCALL zend_parse_arg_bool_slow(zval *arg, zend_bool *dest) /* {{{ */
378 {
379 if (UNEXPECTED(ZEND_ARG_USES_STRICT_TYPES())) {
380 return 0;
381 }
382 return zend_parse_arg_bool_weak(arg, dest);
383 }
384 /* }}} */
385
zend_parse_arg_long_weak(zval * arg,zend_long * dest)386 ZEND_API int ZEND_FASTCALL zend_parse_arg_long_weak(zval *arg, zend_long *dest) /* {{{ */
387 {
388 if (EXPECTED(Z_TYPE_P(arg) == IS_DOUBLE)) {
389 if (UNEXPECTED(zend_isnan(Z_DVAL_P(arg)))) {
390 return 0;
391 }
392 if (UNEXPECTED(!ZEND_DOUBLE_FITS_LONG(Z_DVAL_P(arg)))) {
393 return 0;
394 } else {
395 *dest = zend_dval_to_lval(Z_DVAL_P(arg));
396 }
397 } else if (EXPECTED(Z_TYPE_P(arg) == IS_STRING)) {
398 double d;
399 int type;
400
401 if (UNEXPECTED((type = is_numeric_str_function(Z_STR_P(arg), dest, &d)) != IS_LONG)) {
402 if (EXPECTED(type != 0)) {
403 if (UNEXPECTED(zend_isnan(d))) {
404 return 0;
405 }
406 if (UNEXPECTED(!ZEND_DOUBLE_FITS_LONG(d))) {
407 return 0;
408 } else {
409 *dest = zend_dval_to_lval(d);
410 }
411 } else {
412 return 0;
413 }
414 }
415 } else if (EXPECTED(Z_TYPE_P(arg) < IS_TRUE)) {
416 *dest = 0;
417 } else if (EXPECTED(Z_TYPE_P(arg) == IS_TRUE)) {
418 *dest = 1;
419 } else {
420 return 0;
421 }
422 return 1;
423 }
424 /* }}} */
425
zend_parse_arg_long_slow(zval * arg,zend_long * dest)426 ZEND_API int ZEND_FASTCALL zend_parse_arg_long_slow(zval *arg, zend_long *dest) /* {{{ */
427 {
428 if (UNEXPECTED(ZEND_ARG_USES_STRICT_TYPES())) {
429 return 0;
430 }
431 return zend_parse_arg_long_weak(arg, dest);
432 }
433 /* }}} */
434
zend_parse_arg_long_cap_weak(zval * arg,zend_long * dest)435 ZEND_API int ZEND_FASTCALL zend_parse_arg_long_cap_weak(zval *arg, zend_long *dest) /* {{{ */
436 {
437 if (EXPECTED(Z_TYPE_P(arg) == IS_DOUBLE)) {
438 if (UNEXPECTED(zend_isnan(Z_DVAL_P(arg)))) {
439 return 0;
440 }
441 *dest = zend_dval_to_lval_cap(Z_DVAL_P(arg));
442 } else if (EXPECTED(Z_TYPE_P(arg) == IS_STRING)) {
443 double d;
444 int type;
445
446 if (UNEXPECTED((type = is_numeric_str_function(Z_STR_P(arg), dest, &d)) != IS_LONG)) {
447 if (EXPECTED(type != 0)) {
448 if (UNEXPECTED(zend_isnan(d))) {
449 return 0;
450 }
451 *dest = zend_dval_to_lval_cap(d);
452 } else {
453 return 0;
454 }
455 }
456 } else if (EXPECTED(Z_TYPE_P(arg) < IS_TRUE)) {
457 *dest = 0;
458 } else if (EXPECTED(Z_TYPE_P(arg) == IS_TRUE)) {
459 *dest = 1;
460 } else {
461 return 0;
462 }
463 return 1;
464 }
465 /* }}} */
466
zend_parse_arg_long_cap_slow(zval * arg,zend_long * dest)467 ZEND_API int ZEND_FASTCALL zend_parse_arg_long_cap_slow(zval *arg, zend_long *dest) /* {{{ */
468 {
469 if (UNEXPECTED(ZEND_ARG_USES_STRICT_TYPES())) {
470 return 0;
471 }
472 return zend_parse_arg_long_cap_weak(arg, dest);
473 }
474 /* }}} */
475
zend_parse_arg_double_weak(zval * arg,double * dest)476 ZEND_API int ZEND_FASTCALL zend_parse_arg_double_weak(zval *arg, double *dest) /* {{{ */
477 {
478 if (EXPECTED(Z_TYPE_P(arg) == IS_LONG)) {
479 *dest = (double)Z_LVAL_P(arg);
480 } else if (EXPECTED(Z_TYPE_P(arg) == IS_STRING)) {
481 zend_long l;
482 int type;
483
484 if (UNEXPECTED((type = is_numeric_str_function(Z_STR_P(arg), &l, dest)) != IS_DOUBLE)) {
485 if (EXPECTED(type != 0)) {
486 *dest = (double)(l);
487 } else {
488 return 0;
489 }
490 }
491 } else if (EXPECTED(Z_TYPE_P(arg) < IS_TRUE)) {
492 *dest = 0.0;
493 } else if (EXPECTED(Z_TYPE_P(arg) == IS_TRUE)) {
494 *dest = 1.0;
495 } else {
496 return 0;
497 }
498 return 1;
499 }
500 /* }}} */
501
zend_parse_arg_double_slow(zval * arg,double * dest)502 ZEND_API int ZEND_FASTCALL zend_parse_arg_double_slow(zval *arg, double *dest) /* {{{ */
503 {
504 if (EXPECTED(Z_TYPE_P(arg) == IS_LONG)) {
505 /* SSTH Exception: IS_LONG may be accepted instead as IS_DOUBLE */
506 *dest = (double)Z_LVAL_P(arg);
507 } else if (UNEXPECTED(ZEND_ARG_USES_STRICT_TYPES())) {
508 return 0;
509 }
510 return zend_parse_arg_double_weak(arg, dest);
511 }
512 /* }}} */
513
zend_parse_arg_str_weak(zval * arg,zend_string ** dest)514 ZEND_API int ZEND_FASTCALL zend_parse_arg_str_weak(zval *arg, zend_string **dest) /* {{{ */
515 {
516 if (EXPECTED(Z_TYPE_P(arg) < IS_STRING)) {
517 convert_to_string(arg);
518 *dest = Z_STR_P(arg);
519 } else if (UNEXPECTED(Z_TYPE_P(arg) == IS_OBJECT)) {
520 if (Z_OBJ_HANDLER_P(arg, cast_object)) {
521 zval obj;
522 if (Z_OBJ_HANDLER_P(arg, cast_object)(arg, &obj, IS_STRING) == SUCCESS) {
523 zval_ptr_dtor(arg);
524 ZVAL_COPY_VALUE(arg, &obj);
525 *dest = Z_STR_P(arg);
526 return 1;
527 }
528 } else if (Z_OBJ_HANDLER_P(arg, get)) {
529 zval rv;
530 zval *z = Z_OBJ_HANDLER_P(arg, get)(arg, &rv);
531
532 if (Z_TYPE_P(z) != IS_OBJECT) {
533 zval_ptr_dtor(arg);
534 if (Z_TYPE_P(z) == IS_STRING) {
535 ZVAL_COPY_VALUE(arg, z);
536 } else {
537 ZVAL_STR(arg, zval_get_string_func(z));
538 zval_ptr_dtor(z);
539 }
540 *dest = Z_STR_P(arg);
541 return 1;
542 }
543 zval_ptr_dtor(z);
544 }
545 return 0;
546 } else {
547 return 0;
548 }
549 return 1;
550 }
551 /* }}} */
552
zend_parse_arg_str_slow(zval * arg,zend_string ** dest)553 ZEND_API int ZEND_FASTCALL zend_parse_arg_str_slow(zval *arg, zend_string **dest) /* {{{ */
554 {
555 if (UNEXPECTED(ZEND_ARG_USES_STRICT_TYPES())) {
556 return 0;
557 }
558 return zend_parse_arg_str_weak(arg, dest);
559 }
560 /* }}} */
561
zend_parse_arg_impl(int arg_num,zval * arg,va_list * va,const char ** spec,char ** error,int * severity)562 static const char *zend_parse_arg_impl(int arg_num, zval *arg, va_list *va, const char **spec, char **error, int *severity) /* {{{ */
563 {
564 const char *spec_walk = *spec;
565 char c = *spec_walk++;
566 int check_null = 0;
567 int separate = 0;
568 zval *real_arg = arg;
569
570 /* scan through modifiers */
571 ZVAL_DEREF(arg);
572 while (1) {
573 if (*spec_walk == '/') {
574 SEPARATE_ZVAL_NOREF(arg);
575 real_arg = arg;
576 separate = 1;
577 } else if (*spec_walk == '!') {
578 check_null = 1;
579 } else {
580 break;
581 }
582 spec_walk++;
583 }
584
585 switch (c) {
586 case 'l':
587 case 'L':
588 {
589 zend_long *p = va_arg(*va, zend_long *);
590 zend_bool *is_null = NULL;
591
592 if (check_null) {
593 is_null = va_arg(*va, zend_bool *);
594 }
595
596 if (!zend_parse_arg_long(arg, p, is_null, check_null, c == 'L')) {
597 return "int";
598 }
599 }
600 break;
601
602 case 'd':
603 {
604 double *p = va_arg(*va, double *);
605 zend_bool *is_null = NULL;
606
607 if (check_null) {
608 is_null = va_arg(*va, zend_bool *);
609 }
610
611 if (!zend_parse_arg_double(arg, p, is_null, check_null)) {
612 return "float";
613 }
614 }
615 break;
616
617 case 's':
618 {
619 char **p = va_arg(*va, char **);
620 size_t *pl = va_arg(*va, size_t *);
621 if (!zend_parse_arg_string(arg, p, pl, check_null)) {
622 return "string";
623 }
624 }
625 break;
626
627 case 'p':
628 {
629 char **p = va_arg(*va, char **);
630 size_t *pl = va_arg(*va, size_t *);
631 if (!zend_parse_arg_path(arg, p, pl, check_null)) {
632 return "a valid path";
633 }
634 }
635 break;
636
637 case 'P':
638 {
639 zend_string **str = va_arg(*va, zend_string **);
640 if (!zend_parse_arg_path_str(arg, str, check_null)) {
641 return "a valid path";
642 }
643 }
644 break;
645
646 case 'S':
647 {
648 zend_string **str = va_arg(*va, zend_string **);
649 if (!zend_parse_arg_str(arg, str, check_null)) {
650 return "string";
651 }
652 }
653 break;
654
655 case 'b':
656 {
657 zend_bool *p = va_arg(*va, zend_bool *);
658 zend_bool *is_null = NULL;
659
660 if (check_null) {
661 is_null = va_arg(*va, zend_bool *);
662 }
663
664 if (!zend_parse_arg_bool(arg, p, is_null, check_null)) {
665 return "bool";
666 }
667 }
668 break;
669
670 case 'r':
671 {
672 zval **p = va_arg(*va, zval **);
673
674 if (!zend_parse_arg_resource(arg, p, check_null)) {
675 return "resource";
676 }
677 }
678 break;
679
680 case 'A':
681 case 'a':
682 {
683 zval **p = va_arg(*va, zval **);
684
685 if (!zend_parse_arg_array(arg, p, check_null, c == 'A')) {
686 return "array";
687 }
688 }
689 break;
690
691 case 'H':
692 case 'h':
693 {
694 HashTable **p = va_arg(*va, HashTable **);
695
696 if (!zend_parse_arg_array_ht(arg, p, check_null, c == 'H', separate)) {
697 return "array";
698 }
699 }
700 break;
701
702 case 'o':
703 {
704 zval **p = va_arg(*va, zval **);
705
706 if (!zend_parse_arg_object(arg, p, NULL, check_null)) {
707 return "object";
708 }
709 }
710 break;
711
712 case 'O':
713 {
714 zval **p = va_arg(*va, zval **);
715 zend_class_entry *ce = va_arg(*va, zend_class_entry *);
716
717 if (!zend_parse_arg_object(arg, p, ce, check_null)) {
718 if (ce) {
719 return ZSTR_VAL(ce->name);
720 } else {
721 return "object";
722 }
723 }
724 }
725 break;
726
727 case 'C':
728 {
729 zend_class_entry *lookup, **pce = va_arg(*va, zend_class_entry **);
730 zend_class_entry *ce_base = *pce;
731
732 if (check_null && Z_TYPE_P(arg) == IS_NULL) {
733 *pce = NULL;
734 break;
735 }
736 convert_to_string_ex(arg);
737 if ((lookup = zend_lookup_class(Z_STR_P(arg))) == NULL) {
738 *pce = NULL;
739 } else {
740 *pce = lookup;
741 }
742 if (ce_base) {
743 if ((!*pce || !instanceof_function(*pce, ce_base))) {
744 zend_spprintf(error, 0, "to be a class name derived from %s, '%s' given",
745 ZSTR_VAL(ce_base->name), Z_STRVAL_P(arg));
746 *pce = NULL;
747 return "";
748 }
749 }
750 if (!*pce) {
751 zend_spprintf(error, 0, "to be a valid class name, '%s' given",
752 Z_STRVAL_P(arg));
753 return "";
754 }
755 break;
756
757 }
758 break;
759
760 case 'f':
761 {
762 zend_fcall_info *fci = va_arg(*va, zend_fcall_info *);
763 zend_fcall_info_cache *fcc = va_arg(*va, zend_fcall_info_cache *);
764 char *is_callable_error = NULL;
765
766 if (check_null && Z_TYPE_P(arg) == IS_NULL) {
767 fci->size = 0;
768 fcc->function_handler = 0;
769 break;
770 }
771
772 if (zend_fcall_info_init(arg, 0, fci, fcc, NULL, &is_callable_error) == SUCCESS) {
773 if (is_callable_error) {
774 *severity = E_DEPRECATED;
775 zend_spprintf(error, 0, "to be a valid callback, %s", is_callable_error);
776 efree(is_callable_error);
777 *spec = spec_walk;
778 return "";
779 }
780 break;
781 } else {
782 if (is_callable_error) {
783 *severity = E_ERROR;
784 zend_spprintf(error, 0, "to be a valid callback, %s", is_callable_error);
785 efree(is_callable_error);
786 return "";
787 } else {
788 return "valid callback";
789 }
790 }
791 }
792
793 case 'z':
794 {
795 zval **p = va_arg(*va, zval **);
796
797 zend_parse_arg_zval_deref(real_arg, p, check_null);
798 }
799 break;
800
801 case 'Z':
802 /* 'Z' iz not supported anymore and should be replaced with 'z' */
803 ZEND_ASSERT(c != 'Z');
804 default:
805 return "unknown";
806 }
807
808 *spec = spec_walk;
809
810 return NULL;
811 }
812 /* }}} */
813
zend_parse_arg(int arg_num,zval * arg,va_list * va,const char ** spec,int flags)814 static int zend_parse_arg(int arg_num, zval *arg, va_list *va, const char **spec, int flags) /* {{{ */
815 {
816 const char *expected_type = NULL;
817 char *error = NULL;
818 int severity = 0;
819
820 expected_type = zend_parse_arg_impl(arg_num, arg, va, spec, &error, &severity);
821 if (expected_type) {
822 if (!(flags & ZEND_PARSE_PARAMS_QUIET) && (*expected_type || error)) {
823 const char *space;
824 const char *class_name = get_active_class_name(&space);
825 zend_bool throw_exception =
826 ZEND_ARG_USES_STRICT_TYPES() || (flags & ZEND_PARSE_PARAMS_THROW);
827
828 if (error) {
829 zend_internal_type_error(throw_exception, "%s%s%s() expects parameter %d %s",
830 class_name, space, get_active_function_name(), arg_num, error);
831 efree(error);
832 } else {
833 zend_internal_type_error(throw_exception,
834 "%s%s%s() expects parameter %d to be %s, %s given",
835 class_name, space, get_active_function_name(), arg_num, expected_type,
836 zend_zval_type_name(arg));
837 }
838 }
839 if (severity != E_DEPRECATED) {
840 return FAILURE;
841 }
842 }
843
844 return SUCCESS;
845 }
846 /* }}} */
847
zend_parse_parameter(int flags,int arg_num,zval * arg,const char * spec,...)848 ZEND_API int zend_parse_parameter(int flags, int arg_num, zval *arg, const char *spec, ...)
849 {
850 va_list va;
851 int ret;
852
853 va_start(va, spec);
854 ret = zend_parse_arg(arg_num, arg, &va, &spec, flags);
855 va_end(va);
856
857 return ret;
858 }
859
zend_parse_parameters_debug_error(const char * msg)860 static ZEND_COLD void zend_parse_parameters_debug_error(const char *msg) {
861 zend_function *active_function = EG(current_execute_data)->func;
862 const char *class_name = active_function->common.scope
863 ? ZSTR_VAL(active_function->common.scope->name) : "";
864 zend_error_noreturn(E_CORE_ERROR, "%s%s%s(): %s",
865 class_name, class_name[0] ? "::" : "",
866 ZSTR_VAL(active_function->common.function_name), msg);
867 }
868
zend_parse_va_args(int num_args,const char * type_spec,va_list * va,int flags)869 static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va, int flags) /* {{{ */
870 {
871 const char *spec_walk;
872 int c, i;
873 int min_num_args = -1;
874 int max_num_args = 0;
875 int post_varargs = 0;
876 zval *arg;
877 int arg_count;
878 zend_bool have_varargs = 0;
879 zval **varargs = NULL;
880 int *n_varargs = NULL;
881
882 for (spec_walk = type_spec; *spec_walk; spec_walk++) {
883 c = *spec_walk;
884 switch (c) {
885 case 'l': case 'd':
886 case 's': case 'b':
887 case 'r': case 'a':
888 case 'o': case 'O':
889 case 'z': case 'Z':
890 case 'C': case 'h':
891 case 'f': case 'A':
892 case 'H': case 'p':
893 case 'S': case 'P':
894 case 'L':
895 max_num_args++;
896 break;
897
898 case '|':
899 min_num_args = max_num_args;
900 break;
901
902 case '/':
903 case '!':
904 /* Pass */
905 break;
906
907 case '*':
908 case '+':
909 if (have_varargs) {
910 zend_parse_parameters_debug_error(
911 "only one varargs specifier (* or +) is permitted");
912 return FAILURE;
913 }
914 have_varargs = 1;
915 /* we expect at least one parameter in varargs */
916 if (c == '+') {
917 max_num_args++;
918 }
919 /* mark the beginning of varargs */
920 post_varargs = max_num_args;
921 break;
922
923 default:
924 zend_parse_parameters_debug_error("bad type specifier while parsing parameters");
925 return FAILURE;
926 }
927 }
928
929 if (min_num_args < 0) {
930 min_num_args = max_num_args;
931 }
932
933 if (have_varargs) {
934 /* calculate how many required args are at the end of the specifier list */
935 post_varargs = max_num_args - post_varargs;
936 max_num_args = -1;
937 }
938
939 if (num_args < min_num_args || (num_args > max_num_args && max_num_args >= 0)) {
940 if (!(flags & ZEND_PARSE_PARAMS_QUIET)) {
941 zend_function *active_function = EG(current_execute_data)->func;
942 const char *class_name = active_function->common.scope ? ZSTR_VAL(active_function->common.scope->name) : "";
943 zend_bool throw_exception = ZEND_ARG_USES_STRICT_TYPES() || (flags & ZEND_PARSE_PARAMS_THROW);
944 zend_internal_argument_count_error(throw_exception, "%s%s%s() expects %s %d parameter%s, %d given",
945 class_name,
946 class_name[0] ? "::" : "",
947 ZSTR_VAL(active_function->common.function_name),
948 min_num_args == max_num_args ? "exactly" : num_args < min_num_args ? "at least" : "at most",
949 num_args < min_num_args ? min_num_args : max_num_args,
950 (num_args < min_num_args ? min_num_args : max_num_args) == 1 ? "" : "s",
951 num_args);
952 }
953 return FAILURE;
954 }
955
956 arg_count = ZEND_CALL_NUM_ARGS(EG(current_execute_data));
957
958 if (num_args > arg_count) {
959 zend_parse_parameters_debug_error("could not obtain parameters for parsing");
960 return FAILURE;
961 }
962
963 i = 0;
964 while (num_args-- > 0) {
965 if (*type_spec == '|') {
966 type_spec++;
967 }
968
969 if (*type_spec == '*' || *type_spec == '+') {
970 int num_varargs = num_args + 1 - post_varargs;
971
972 /* eat up the passed in storage even if it won't be filled in with varargs */
973 varargs = va_arg(*va, zval **);
974 n_varargs = va_arg(*va, int *);
975 type_spec++;
976
977 if (num_varargs > 0) {
978 *n_varargs = num_varargs;
979 *varargs = ZEND_CALL_ARG(EG(current_execute_data), i + 1);
980 /* adjust how many args we have left and restart loop */
981 num_args += 1 - num_varargs;
982 i += num_varargs;
983 continue;
984 } else {
985 *varargs = NULL;
986 *n_varargs = 0;
987 }
988 }
989
990 arg = ZEND_CALL_ARG(EG(current_execute_data), i + 1);
991
992 if (zend_parse_arg(i+1, arg, va, &type_spec, flags) == FAILURE) {
993 /* clean up varargs array if it was used */
994 if (varargs && *varargs) {
995 *varargs = NULL;
996 }
997 return FAILURE;
998 }
999 i++;
1000 }
1001
1002 return SUCCESS;
1003 }
1004 /* }}} */
1005
zend_parse_parameters_ex(int flags,int num_args,const char * type_spec,...)1006 ZEND_API int zend_parse_parameters_ex(int flags, int num_args, const char *type_spec, ...) /* {{{ */
1007 {
1008 va_list va;
1009 int retval;
1010
1011 va_start(va, type_spec);
1012 retval = zend_parse_va_args(num_args, type_spec, &va, flags);
1013 va_end(va);
1014
1015 return retval;
1016 }
1017 /* }}} */
1018
zend_parse_parameters(int num_args,const char * type_spec,...)1019 ZEND_API int zend_parse_parameters(int num_args, const char *type_spec, ...) /* {{{ */
1020 {
1021 va_list va;
1022 int retval;
1023 int flags = 0;
1024
1025 va_start(va, type_spec);
1026 retval = zend_parse_va_args(num_args, type_spec, &va, flags);
1027 va_end(va);
1028
1029 return retval;
1030 }
1031 /* }}} */
1032
zend_parse_parameters_throw(int num_args,const char * type_spec,...)1033 ZEND_API int zend_parse_parameters_throw(int num_args, const char *type_spec, ...) /* {{{ */
1034 {
1035 va_list va;
1036 int retval;
1037 int flags = ZEND_PARSE_PARAMS_THROW;
1038
1039 va_start(va, type_spec);
1040 retval = zend_parse_va_args(num_args, type_spec, &va, flags);
1041 va_end(va);
1042
1043 return retval;
1044 }
1045 /* }}} */
1046
zend_parse_method_parameters(int num_args,zval * this_ptr,const char * type_spec,...)1047 ZEND_API int zend_parse_method_parameters(int num_args, zval *this_ptr, const char *type_spec, ...) /* {{{ */
1048 {
1049 va_list va;
1050 int retval;
1051 int flags = 0;
1052 const char *p = type_spec;
1053 zval **object;
1054 zend_class_entry *ce;
1055
1056 /* Just checking this_ptr is not enough, because fcall_common_helper does not set
1057 * Z_OBJ(EG(This)) to NULL when calling an internal function with common.scope == NULL.
1058 * In that case EG(This) would still be the $this from the calling code and we'd take the
1059 * wrong branch here. */
1060 zend_bool is_method = EG(current_execute_data)->func->common.scope != NULL;
1061
1062 if (!is_method || !this_ptr || Z_TYPE_P(this_ptr) != IS_OBJECT) {
1063 va_start(va, type_spec);
1064 retval = zend_parse_va_args(num_args, type_spec, &va, flags);
1065 va_end(va);
1066 } else {
1067 p++;
1068
1069 va_start(va, type_spec);
1070
1071 object = va_arg(va, zval **);
1072 ce = va_arg(va, zend_class_entry *);
1073 *object = this_ptr;
1074
1075 if (ce && !instanceof_function(Z_OBJCE_P(this_ptr), ce)) {
1076 zend_error_noreturn(E_CORE_ERROR, "%s::%s() must be derived from %s::%s",
1077 ZSTR_VAL(Z_OBJCE_P(this_ptr)->name), get_active_function_name(), ZSTR_VAL(ce->name), get_active_function_name());
1078 }
1079
1080 retval = zend_parse_va_args(num_args, p, &va, flags);
1081 va_end(va);
1082 }
1083 return retval;
1084 }
1085 /* }}} */
1086
zend_parse_method_parameters_ex(int flags,int num_args,zval * this_ptr,const char * type_spec,...)1087 ZEND_API int zend_parse_method_parameters_ex(int flags, int num_args, zval *this_ptr, const char *type_spec, ...) /* {{{ */
1088 {
1089 va_list va;
1090 int retval;
1091 const char *p = type_spec;
1092 zval **object;
1093 zend_class_entry *ce;
1094
1095 if (!this_ptr) {
1096 va_start(va, type_spec);
1097 retval = zend_parse_va_args(num_args, type_spec, &va, flags);
1098 va_end(va);
1099 } else {
1100 p++;
1101 va_start(va, type_spec);
1102
1103 object = va_arg(va, zval **);
1104 ce = va_arg(va, zend_class_entry *);
1105 *object = this_ptr;
1106
1107 if (ce && !instanceof_function(Z_OBJCE_P(this_ptr), ce)) {
1108 if (!(flags & ZEND_PARSE_PARAMS_QUIET)) {
1109 zend_error_noreturn(E_CORE_ERROR, "%s::%s() must be derived from %s::%s",
1110 ZSTR_VAL(ce->name), get_active_function_name(), ZSTR_VAL(Z_OBJCE_P(this_ptr)->name), get_active_function_name());
1111 }
1112 va_end(va);
1113 return FAILURE;
1114 }
1115
1116 retval = zend_parse_va_args(num_args, p, &va, flags);
1117 va_end(va);
1118 }
1119 return retval;
1120 }
1121 /* }}} */
1122
1123 /* This function should be called after the constructor has been called
1124 * because it may call __set from the uninitialized object otherwise. */
zend_merge_properties(zval * obj,HashTable * properties)1125 ZEND_API void zend_merge_properties(zval *obj, HashTable *properties) /* {{{ */
1126 {
1127 const zend_object_handlers *obj_ht = Z_OBJ_HT_P(obj);
1128 zend_class_entry *old_scope = EG(fake_scope);
1129 zend_string *key;
1130 zval *value;
1131
1132 EG(fake_scope) = Z_OBJCE_P(obj);
1133 ZEND_HASH_FOREACH_STR_KEY_VAL(properties, key, value) {
1134 if (key) {
1135 zval member;
1136
1137 ZVAL_STR(&member, key);
1138 obj_ht->write_property(obj, &member, value, NULL);
1139 }
1140 } ZEND_HASH_FOREACH_END();
1141 EG(fake_scope) = old_scope;
1142 }
1143 /* }}} */
1144
zend_update_class_constants(zend_class_entry * class_type)1145 ZEND_API int zend_update_class_constants(zend_class_entry *class_type) /* {{{ */
1146 {
1147 if (!(class_type->ce_flags & ZEND_ACC_CONSTANTS_UPDATED)) {
1148 zend_class_entry *ce;
1149 zend_class_constant *c;
1150 zval *val;
1151 zend_property_info *prop_info;
1152
1153 if (class_type->parent) {
1154 if (UNEXPECTED(zend_update_class_constants(class_type->parent) != SUCCESS)) {
1155 return FAILURE;
1156 }
1157 }
1158
1159 ZEND_HASH_FOREACH_PTR(&class_type->constants_table, c) {
1160 val = &c->value;
1161 if (Z_TYPE_P(val) == IS_CONSTANT_AST) {
1162 if (UNEXPECTED(zval_update_constant_ex(val, c->ce) != SUCCESS)) {
1163 return FAILURE;
1164 }
1165 }
1166 } ZEND_HASH_FOREACH_END();
1167
1168 ce = class_type;
1169 while (ce) {
1170 ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop_info) {
1171 if (prop_info->ce == ce) {
1172 if (prop_info->flags & ZEND_ACC_STATIC) {
1173 val = CE_STATIC_MEMBERS(class_type) + prop_info->offset;
1174 } else {
1175 val = (zval*)((char*)class_type->default_properties_table + prop_info->offset - OBJ_PROP_TO_OFFSET(0));
1176 }
1177 ZVAL_DEREF(val);
1178 if (Z_TYPE_P(val) == IS_CONSTANT_AST) {
1179 if (UNEXPECTED(zval_update_constant_ex(val, ce) != SUCCESS)) {
1180 return FAILURE;
1181 }
1182 }
1183 }
1184 } ZEND_HASH_FOREACH_END();
1185 ce = ce->parent;
1186 }
1187
1188 class_type->ce_flags |= ZEND_ACC_CONSTANTS_UPDATED;
1189 }
1190
1191 return SUCCESS;
1192 }
1193 /* }}} */
1194
object_properties_init(zend_object * object,zend_class_entry * class_type)1195 ZEND_API void object_properties_init(zend_object *object, zend_class_entry *class_type) /* {{{ */
1196 {
1197 if (class_type->default_properties_count) {
1198 zval *src = class_type->default_properties_table;
1199 zval *dst = object->properties_table;
1200 zval *end = src + class_type->default_properties_count;
1201
1202 if (UNEXPECTED(class_type->type == ZEND_INTERNAL_CLASS)) {
1203 do {
1204 ZVAL_COPY_OR_DUP(dst, src);
1205 src++;
1206 dst++;
1207 } while (src != end);
1208 } else {
1209 do {
1210 ZVAL_COPY(dst, src);
1211 src++;
1212 dst++;
1213 } while (src != end);
1214 }
1215 object->properties = NULL;
1216 }
1217 }
1218 /* }}} */
1219
object_properties_init_ex(zend_object * object,HashTable * properties)1220 ZEND_API void object_properties_init_ex(zend_object *object, HashTable *properties) /* {{{ */
1221 {
1222 object->properties = properties;
1223 if (object->ce->default_properties_count) {
1224 zval *prop;
1225 zend_string *key;
1226 zend_property_info *property_info;
1227
1228 ZEND_HASH_FOREACH_STR_KEY_VAL(properties, key, prop) {
1229 property_info = zend_get_property_info(object->ce, key, 1);
1230 if (property_info != ZEND_WRONG_PROPERTY_INFO &&
1231 property_info &&
1232 (property_info->flags & ZEND_ACC_STATIC) == 0) {
1233 zval *slot = OBJ_PROP(object, property_info->offset);
1234 ZVAL_COPY_VALUE(slot, prop);
1235 ZVAL_INDIRECT(prop, slot);
1236 }
1237 } ZEND_HASH_FOREACH_END();
1238 }
1239 }
1240 /* }}} */
1241
object_properties_load(zend_object * object,HashTable * properties)1242 ZEND_API void object_properties_load(zend_object *object, HashTable *properties) /* {{{ */
1243 {
1244 zval *prop, tmp;
1245 zend_string *key;
1246 zend_long h;
1247 zend_property_info *property_info;
1248
1249 ZEND_HASH_FOREACH_KEY_VAL(properties, h, key, prop) {
1250 if (key) {
1251 if (ZSTR_VAL(key)[0] == '\0') {
1252 const char *class_name, *prop_name;
1253 size_t prop_name_len;
1254 if (zend_unmangle_property_name_ex(key, &class_name, &prop_name, &prop_name_len) == SUCCESS) {
1255 zend_string *pname = zend_string_init(prop_name, prop_name_len, 0);
1256 zend_class_entry *prev_scope = EG(fake_scope);
1257 if (class_name && class_name[0] != '*') {
1258 zend_string *cname = zend_string_init(class_name, strlen(class_name), 0);
1259 EG(fake_scope) = zend_lookup_class(cname);
1260 zend_string_release_ex(cname, 0);
1261 }
1262 property_info = zend_get_property_info(object->ce, pname, 1);
1263 zend_string_release_ex(pname, 0);
1264 EG(fake_scope) = prev_scope;
1265 } else {
1266 property_info = ZEND_WRONG_PROPERTY_INFO;
1267 }
1268 } else {
1269 property_info = zend_get_property_info(object->ce, key, 1);
1270 }
1271 if (property_info != ZEND_WRONG_PROPERTY_INFO &&
1272 property_info &&
1273 (property_info->flags & ZEND_ACC_STATIC) == 0) {
1274 zval *slot = OBJ_PROP(object, property_info->offset);
1275 zval_ptr_dtor(slot);
1276 ZVAL_COPY_VALUE(slot, prop);
1277 zval_add_ref(slot);
1278 if (object->properties) {
1279 ZVAL_INDIRECT(&tmp, slot);
1280 zend_hash_update(object->properties, key, &tmp);
1281 }
1282 } else {
1283 if (!object->properties) {
1284 rebuild_object_properties(object);
1285 }
1286 prop = zend_hash_update(object->properties, key, prop);
1287 zval_add_ref(prop);
1288 }
1289 } else {
1290 if (!object->properties) {
1291 rebuild_object_properties(object);
1292 }
1293 prop = zend_hash_index_update(object->properties, h, prop);
1294 zval_add_ref(prop);
1295 }
1296 } ZEND_HASH_FOREACH_END();
1297 }
1298 /* }}} */
1299
1300 /* This function requires 'properties' to contain all props declared in the
1301 * class and all props being public. If only a subset is given or the class
1302 * has protected members then you need to merge the properties separately by
1303 * calling zend_merge_properties(). */
object_and_properties_init(zval * arg,zend_class_entry * class_type,HashTable * properties)1304 ZEND_API int object_and_properties_init(zval *arg, zend_class_entry *class_type, HashTable *properties) /* {{{ */
1305 {
1306 if (UNEXPECTED(class_type->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS))) {
1307 if (class_type->ce_flags & ZEND_ACC_INTERFACE) {
1308 zend_throw_error(NULL, "Cannot instantiate interface %s", ZSTR_VAL(class_type->name));
1309 } else if (class_type->ce_flags & ZEND_ACC_TRAIT) {
1310 zend_throw_error(NULL, "Cannot instantiate trait %s", ZSTR_VAL(class_type->name));
1311 } else {
1312 zend_throw_error(NULL, "Cannot instantiate abstract class %s", ZSTR_VAL(class_type->name));
1313 }
1314 ZVAL_NULL(arg);
1315 Z_OBJ_P(arg) = NULL;
1316 return FAILURE;
1317 }
1318
1319 if (UNEXPECTED(!(class_type->ce_flags & ZEND_ACC_CONSTANTS_UPDATED))) {
1320 if (UNEXPECTED(zend_update_class_constants(class_type) != SUCCESS)) {
1321 ZVAL_NULL(arg);
1322 Z_OBJ_P(arg) = NULL;
1323 return FAILURE;
1324 }
1325 }
1326
1327 if (class_type->create_object == NULL) {
1328 ZVAL_OBJ(arg, zend_objects_new(class_type));
1329 if (properties) {
1330 object_properties_init_ex(Z_OBJ_P(arg), properties);
1331 } else {
1332 object_properties_init(Z_OBJ_P(arg), class_type);
1333 }
1334 } else {
1335 ZVAL_OBJ(arg, class_type->create_object(class_type));
1336 }
1337 return SUCCESS;
1338 }
1339 /* }}} */
1340
object_init_ex(zval * arg,zend_class_entry * class_type)1341 ZEND_API int object_init_ex(zval *arg, zend_class_entry *class_type) /* {{{ */
1342 {
1343 return object_and_properties_init(arg, class_type, 0);
1344 }
1345 /* }}} */
1346
object_init(zval * arg)1347 ZEND_API int object_init(zval *arg) /* {{{ */
1348 {
1349 ZVAL_OBJ(arg, zend_objects_new(zend_standard_class_def));
1350 return SUCCESS;
1351 }
1352 /* }}} */
1353
add_assoc_long_ex(zval * arg,const char * key,size_t key_len,zend_long n)1354 ZEND_API int add_assoc_long_ex(zval *arg, const char *key, size_t key_len, zend_long n) /* {{{ */
1355 {
1356 zval tmp;
1357
1358 ZVAL_LONG(&tmp, n);
1359 zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1360 return SUCCESS;
1361 }
1362 /* }}} */
1363
add_assoc_null_ex(zval * arg,const char * key,size_t key_len)1364 ZEND_API int add_assoc_null_ex(zval *arg, const char *key, size_t key_len) /* {{{ */
1365 {
1366 zval tmp;
1367
1368 ZVAL_NULL(&tmp);
1369 zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1370 return SUCCESS;
1371 }
1372 /* }}} */
1373
add_assoc_bool_ex(zval * arg,const char * key,size_t key_len,int b)1374 ZEND_API int add_assoc_bool_ex(zval *arg, const char *key, size_t key_len, int b) /* {{{ */
1375 {
1376 zval tmp;
1377
1378 ZVAL_BOOL(&tmp, b);
1379 zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1380 return SUCCESS;
1381 }
1382 /* }}} */
1383
add_assoc_resource_ex(zval * arg,const char * key,size_t key_len,zend_resource * r)1384 ZEND_API int add_assoc_resource_ex(zval *arg, const char *key, size_t key_len, zend_resource *r) /* {{{ */
1385 {
1386 zval tmp;
1387
1388 ZVAL_RES(&tmp, r);
1389 zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1390 return SUCCESS;
1391 }
1392 /* }}} */
1393
add_assoc_double_ex(zval * arg,const char * key,size_t key_len,double d)1394 ZEND_API int add_assoc_double_ex(zval *arg, const char *key, size_t key_len, double d) /* {{{ */
1395 {
1396 zval tmp;
1397
1398 ZVAL_DOUBLE(&tmp, d);
1399 zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1400 return SUCCESS;
1401 }
1402 /* }}} */
1403
add_assoc_str_ex(zval * arg,const char * key,size_t key_len,zend_string * str)1404 ZEND_API int add_assoc_str_ex(zval *arg, const char *key, size_t key_len, zend_string *str) /* {{{ */
1405 {
1406 zval tmp;
1407
1408 ZVAL_STR(&tmp, str);
1409 zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1410 return SUCCESS;
1411 }
1412 /* }}} */
1413
add_assoc_string_ex(zval * arg,const char * key,size_t key_len,const char * str)1414 ZEND_API int add_assoc_string_ex(zval *arg, const char *key, size_t key_len, const char *str) /* {{{ */
1415 {
1416 zval tmp;
1417
1418 ZVAL_STRING(&tmp, str);
1419 zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1420 return SUCCESS;
1421 }
1422 /* }}} */
1423
add_assoc_stringl_ex(zval * arg,const char * key,size_t key_len,const char * str,size_t length)1424 ZEND_API int add_assoc_stringl_ex(zval *arg, const char *key, size_t key_len, const char *str, size_t length) /* {{{ */
1425 {
1426 zval tmp;
1427
1428 ZVAL_STRINGL(&tmp, str, length);
1429 zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1430 return SUCCESS;
1431 }
1432 /* }}} */
1433
add_assoc_zval_ex(zval * arg,const char * key,size_t key_len,zval * value)1434 ZEND_API int add_assoc_zval_ex(zval *arg, const char *key, size_t key_len, zval *value) /* {{{ */
1435 {
1436 zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, value);
1437 return SUCCESS;
1438 }
1439 /* }}} */
1440
add_index_long(zval * arg,zend_ulong index,zend_long n)1441 ZEND_API int add_index_long(zval *arg, zend_ulong index, zend_long n) /* {{{ */
1442 {
1443 zval tmp;
1444
1445 ZVAL_LONG(&tmp, n);
1446 zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
1447 return SUCCESS;
1448 }
1449 /* }}} */
1450
add_index_null(zval * arg,zend_ulong index)1451 ZEND_API int add_index_null(zval *arg, zend_ulong index) /* {{{ */
1452 {
1453 zval tmp;
1454
1455 ZVAL_NULL(&tmp);
1456 zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
1457 return SUCCESS;
1458 }
1459 /* }}} */
1460
add_index_bool(zval * arg,zend_ulong index,int b)1461 ZEND_API int add_index_bool(zval *arg, zend_ulong index, int b) /* {{{ */
1462 {
1463 zval tmp;
1464
1465 ZVAL_BOOL(&tmp, b);
1466 zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
1467 return SUCCESS;
1468 }
1469 /* }}} */
1470
add_index_resource(zval * arg,zend_ulong index,zend_resource * r)1471 ZEND_API int add_index_resource(zval *arg, zend_ulong index, zend_resource *r) /* {{{ */
1472 {
1473 zval tmp;
1474
1475 ZVAL_RES(&tmp, r);
1476 zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
1477 return SUCCESS;
1478 }
1479 /* }}} */
1480
add_index_double(zval * arg,zend_ulong index,double d)1481 ZEND_API int add_index_double(zval *arg, zend_ulong index, double d) /* {{{ */
1482 {
1483 zval tmp;
1484
1485 ZVAL_DOUBLE(&tmp, d);
1486 zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
1487 return SUCCESS;
1488 }
1489 /* }}} */
1490
add_index_str(zval * arg,zend_ulong index,zend_string * str)1491 ZEND_API int add_index_str(zval *arg, zend_ulong index, zend_string *str) /* {{{ */
1492 {
1493 zval tmp;
1494
1495 ZVAL_STR(&tmp, str);
1496 zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
1497 return SUCCESS;
1498 }
1499 /* }}} */
1500
add_index_string(zval * arg,zend_ulong index,const char * str)1501 ZEND_API int add_index_string(zval *arg, zend_ulong index, const char *str) /* {{{ */
1502 {
1503 zval tmp;
1504
1505 ZVAL_STRING(&tmp, str);
1506 zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
1507 return SUCCESS;
1508 }
1509 /* }}} */
1510
add_index_stringl(zval * arg,zend_ulong index,const char * str,size_t length)1511 ZEND_API int add_index_stringl(zval *arg, zend_ulong index, const char *str, size_t length) /* {{{ */
1512 {
1513 zval tmp;
1514
1515 ZVAL_STRINGL(&tmp, str, length);
1516 zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
1517 return SUCCESS;
1518 }
1519 /* }}} */
1520
add_index_zval(zval * arg,zend_ulong index,zval * value)1521 ZEND_API int add_index_zval(zval *arg, zend_ulong index, zval *value) /* {{{ */
1522 {
1523 zend_hash_index_update(Z_ARRVAL_P(arg), index, value);
1524 return SUCCESS;
1525 }
1526 /* }}} */
1527
add_next_index_long(zval * arg,zend_long n)1528 ZEND_API int add_next_index_long(zval *arg, zend_long n) /* {{{ */
1529 {
1530 zval tmp;
1531
1532 ZVAL_LONG(&tmp, n);
1533 return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
1534 }
1535 /* }}} */
1536
add_next_index_null(zval * arg)1537 ZEND_API int add_next_index_null(zval *arg) /* {{{ */
1538 {
1539 zval tmp;
1540
1541 ZVAL_NULL(&tmp);
1542 return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
1543 }
1544 /* }}} */
1545
add_next_index_bool(zval * arg,int b)1546 ZEND_API int add_next_index_bool(zval *arg, int b) /* {{{ */
1547 {
1548 zval tmp;
1549
1550 ZVAL_BOOL(&tmp, b);
1551 return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
1552 }
1553 /* }}} */
1554
add_next_index_resource(zval * arg,zend_resource * r)1555 ZEND_API int add_next_index_resource(zval *arg, zend_resource *r) /* {{{ */
1556 {
1557 zval tmp;
1558
1559 ZVAL_RES(&tmp, r);
1560 return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
1561 }
1562 /* }}} */
1563
add_next_index_double(zval * arg,double d)1564 ZEND_API int add_next_index_double(zval *arg, double d) /* {{{ */
1565 {
1566 zval tmp;
1567
1568 ZVAL_DOUBLE(&tmp, d);
1569 return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
1570 }
1571 /* }}} */
1572
add_next_index_str(zval * arg,zend_string * str)1573 ZEND_API int add_next_index_str(zval *arg, zend_string *str) /* {{{ */
1574 {
1575 zval tmp;
1576
1577 ZVAL_STR(&tmp, str);
1578 return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
1579 }
1580 /* }}} */
1581
add_next_index_string(zval * arg,const char * str)1582 ZEND_API int add_next_index_string(zval *arg, const char *str) /* {{{ */
1583 {
1584 zval tmp;
1585
1586 ZVAL_STRING(&tmp, str);
1587 return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
1588 }
1589 /* }}} */
1590
add_next_index_stringl(zval * arg,const char * str,size_t length)1591 ZEND_API int add_next_index_stringl(zval *arg, const char *str, size_t length) /* {{{ */
1592 {
1593 zval tmp;
1594
1595 ZVAL_STRINGL(&tmp, str, length);
1596 return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
1597 }
1598 /* }}} */
1599
add_next_index_zval(zval * arg,zval * value)1600 ZEND_API int add_next_index_zval(zval *arg, zval *value) /* {{{ */
1601 {
1602 return zend_hash_next_index_insert(Z_ARRVAL_P(arg), value) ? SUCCESS : FAILURE;
1603 }
1604 /* }}} */
1605
add_get_assoc_string_ex(zval * arg,const char * key,uint32_t key_len,const char * str)1606 ZEND_API zval *add_get_assoc_string_ex(zval *arg, const char *key, uint32_t key_len, const char *str) /* {{{ */
1607 {
1608 zval tmp, *ret;
1609
1610 ZVAL_STRING(&tmp, str);
1611 ret = zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1612 return ret;
1613 }
1614 /* }}} */
1615
add_get_assoc_stringl_ex(zval * arg,const char * key,uint32_t key_len,const char * str,size_t length)1616 ZEND_API zval *add_get_assoc_stringl_ex(zval *arg, const char *key, uint32_t key_len, const char *str, size_t length) /* {{{ */
1617 {
1618 zval tmp, *ret;
1619
1620 ZVAL_STRINGL(&tmp, str, length);
1621 ret = zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1622 return ret;
1623 }
1624 /* }}} */
1625
add_get_index_long(zval * arg,zend_ulong index,zend_long l)1626 ZEND_API zval *add_get_index_long(zval *arg, zend_ulong index, zend_long l) /* {{{ */
1627 {
1628 zval tmp;
1629
1630 ZVAL_LONG(&tmp, l);
1631 return zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
1632 }
1633 /* }}} */
1634
add_get_index_double(zval * arg,zend_ulong index,double d)1635 ZEND_API zval *add_get_index_double(zval *arg, zend_ulong index, double d) /* {{{ */
1636 {
1637 zval tmp;
1638
1639 ZVAL_DOUBLE(&tmp, d);
1640 return zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
1641 }
1642 /* }}} */
1643
add_get_index_str(zval * arg,zend_ulong index,zend_string * str)1644 ZEND_API zval *add_get_index_str(zval *arg, zend_ulong index, zend_string *str) /* {{{ */
1645 {
1646 zval tmp;
1647
1648 ZVAL_STR(&tmp, str);
1649 return zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
1650 }
1651 /* }}} */
1652
add_get_index_string(zval * arg,zend_ulong index,const char * str)1653 ZEND_API zval *add_get_index_string(zval *arg, zend_ulong index, const char *str) /* {{{ */
1654 {
1655 zval tmp;
1656
1657 ZVAL_STRING(&tmp, str);
1658 return zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
1659 }
1660 /* }}} */
1661
add_get_index_stringl(zval * arg,zend_ulong index,const char * str,size_t length)1662 ZEND_API zval *add_get_index_stringl(zval *arg, zend_ulong index, const char *str, size_t length) /* {{{ */
1663 {
1664 zval tmp;
1665
1666 ZVAL_STRINGL(&tmp, str, length);
1667 return zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
1668 }
1669 /* }}} */
1670
array_set_zval_key(HashTable * ht,zval * key,zval * value)1671 ZEND_API int array_set_zval_key(HashTable *ht, zval *key, zval *value) /* {{{ */
1672 {
1673 zval *result;
1674
1675 switch (Z_TYPE_P(key)) {
1676 case IS_STRING:
1677 result = zend_symtable_update(ht, Z_STR_P(key), value);
1678 break;
1679 case IS_NULL:
1680 result = zend_symtable_update(ht, ZSTR_EMPTY_ALLOC(), value);
1681 break;
1682 case IS_RESOURCE:
1683 zend_error(E_NOTICE, "Resource ID#%d used as offset, casting to integer (%d)", Z_RES_HANDLE_P(key), Z_RES_HANDLE_P(key));
1684 result = zend_hash_index_update(ht, Z_RES_HANDLE_P(key), value);
1685 break;
1686 case IS_FALSE:
1687 result = zend_hash_index_update(ht, 0, value);
1688 break;
1689 case IS_TRUE:
1690 result = zend_hash_index_update(ht, 1, value);
1691 break;
1692 case IS_LONG:
1693 result = zend_hash_index_update(ht, Z_LVAL_P(key), value);
1694 break;
1695 case IS_DOUBLE:
1696 result = zend_hash_index_update(ht, zend_dval_to_lval(Z_DVAL_P(key)), value);
1697 break;
1698 default:
1699 zend_error(E_WARNING, "Illegal offset type");
1700 result = NULL;
1701 }
1702
1703 if (result) {
1704 Z_TRY_ADDREF_P(result);
1705 return SUCCESS;
1706 } else {
1707 return FAILURE;
1708 }
1709 }
1710 /* }}} */
1711
add_property_long_ex(zval * arg,const char * key,size_t key_len,zend_long n)1712 ZEND_API int add_property_long_ex(zval *arg, const char *key, size_t key_len, zend_long n) /* {{{ */
1713 {
1714 zval tmp;
1715 zval z_key;
1716
1717 ZVAL_LONG(&tmp, n);
1718 ZVAL_STRINGL(&z_key, key, key_len);
1719 Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, &tmp, NULL);
1720 zval_ptr_dtor(&z_key);
1721 return SUCCESS;
1722 }
1723 /* }}} */
1724
add_property_bool_ex(zval * arg,const char * key,size_t key_len,zend_long b)1725 ZEND_API int add_property_bool_ex(zval *arg, const char *key, size_t key_len, zend_long b) /* {{{ */
1726 {
1727 zval tmp;
1728 zval z_key;
1729
1730 ZVAL_BOOL(&tmp, b);
1731 ZVAL_STRINGL(&z_key, key, key_len);
1732 Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, &tmp, NULL);
1733 zval_ptr_dtor(&z_key);
1734 return SUCCESS;
1735 }
1736 /* }}} */
1737
add_property_null_ex(zval * arg,const char * key,size_t key_len)1738 ZEND_API int add_property_null_ex(zval *arg, const char *key, size_t key_len) /* {{{ */
1739 {
1740 zval tmp;
1741 zval z_key;
1742
1743 ZVAL_NULL(&tmp);
1744 ZVAL_STRINGL(&z_key, key, key_len);
1745 Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, &tmp, NULL);
1746 zval_ptr_dtor(&z_key);
1747 return SUCCESS;
1748 }
1749 /* }}} */
1750
add_property_resource_ex(zval * arg,const char * key,size_t key_len,zend_resource * r)1751 ZEND_API int add_property_resource_ex(zval *arg, const char *key, size_t key_len, zend_resource *r) /* {{{ */
1752 {
1753 zval tmp;
1754 zval z_key;
1755
1756 ZVAL_RES(&tmp, r);
1757 ZVAL_STRINGL(&z_key, key, key_len);
1758 Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, &tmp, NULL);
1759 zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
1760 zval_ptr_dtor(&z_key);
1761 return SUCCESS;
1762 }
1763 /* }}} */
1764
add_property_double_ex(zval * arg,const char * key,size_t key_len,double d)1765 ZEND_API int add_property_double_ex(zval *arg, const char *key, size_t key_len, double d) /* {{{ */
1766 {
1767 zval tmp;
1768 zval z_key;
1769
1770 ZVAL_DOUBLE(&tmp, d);
1771 ZVAL_STRINGL(&z_key, key, key_len);
1772 Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, &tmp, NULL);
1773 zval_ptr_dtor(&z_key);
1774 return SUCCESS;
1775 }
1776 /* }}} */
1777
add_property_str_ex(zval * arg,const char * key,size_t key_len,zend_string * str)1778 ZEND_API int add_property_str_ex(zval *arg, const char *key, size_t key_len, zend_string *str) /* {{{ */
1779 {
1780 zval tmp;
1781 zval z_key;
1782
1783 ZVAL_STR(&tmp, str);
1784 ZVAL_STRINGL(&z_key, key, key_len);
1785 Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, &tmp, NULL);
1786 zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
1787 zval_ptr_dtor(&z_key);
1788 return SUCCESS;
1789 }
1790 /* }}} */
1791
add_property_string_ex(zval * arg,const char * key,size_t key_len,const char * str)1792 ZEND_API int add_property_string_ex(zval *arg, const char *key, size_t key_len, const char *str) /* {{{ */
1793 {
1794 zval tmp;
1795 zval z_key;
1796
1797 ZVAL_STRING(&tmp, str);
1798 ZVAL_STRINGL(&z_key, key, key_len);
1799 Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, &tmp, NULL);
1800 zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
1801 zval_ptr_dtor(&z_key);
1802 return SUCCESS;
1803 }
1804 /* }}} */
1805
add_property_stringl_ex(zval * arg,const char * key,size_t key_len,const char * str,size_t length)1806 ZEND_API int add_property_stringl_ex(zval *arg, const char *key, size_t key_len, const char *str, size_t length) /* {{{ */
1807 {
1808 zval tmp;
1809 zval z_key;
1810
1811 ZVAL_STRINGL(&tmp, str, length);
1812 ZVAL_STRINGL(&z_key, key, key_len);
1813 Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, &tmp, NULL);
1814 zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
1815 zval_ptr_dtor(&z_key);
1816 return SUCCESS;
1817 }
1818 /* }}} */
1819
add_property_zval_ex(zval * arg,const char * key,size_t key_len,zval * value)1820 ZEND_API int add_property_zval_ex(zval *arg, const char *key, size_t key_len, zval *value) /* {{{ */
1821 {
1822 zval z_key;
1823
1824 ZVAL_STRINGL(&z_key, key, key_len);
1825 Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, value, NULL);
1826 zval_ptr_dtor(&z_key);
1827 return SUCCESS;
1828 }
1829 /* }}} */
1830
zend_startup_module_ex(zend_module_entry * module)1831 ZEND_API int zend_startup_module_ex(zend_module_entry *module) /* {{{ */
1832 {
1833 size_t name_len;
1834 zend_string *lcname;
1835
1836 if (module->module_started) {
1837 return SUCCESS;
1838 }
1839 module->module_started = 1;
1840
1841 /* Check module dependencies */
1842 if (module->deps) {
1843 const zend_module_dep *dep = module->deps;
1844
1845 while (dep->name) {
1846 if (dep->type == MODULE_DEP_REQUIRED) {
1847 zend_module_entry *req_mod;
1848
1849 name_len = strlen(dep->name);
1850 lcname = zend_string_alloc(name_len, 0);
1851 zend_str_tolower_copy(ZSTR_VAL(lcname), dep->name, name_len);
1852
1853 if ((req_mod = zend_hash_find_ptr(&module_registry, lcname)) == NULL || !req_mod->module_started) {
1854 zend_string_efree(lcname);
1855 /* TODO: Check version relationship */
1856 zend_error(E_CORE_WARNING, "Cannot load module '%s' because required module '%s' is not loaded", module->name, dep->name);
1857 module->module_started = 0;
1858 return FAILURE;
1859 }
1860 zend_string_efree(lcname);
1861 }
1862 ++dep;
1863 }
1864 }
1865
1866 /* Initialize module globals */
1867 if (module->globals_size) {
1868 #ifdef ZTS
1869 ts_allocate_id(module->globals_id_ptr, module->globals_size, (ts_allocate_ctor) module->globals_ctor, (ts_allocate_dtor) module->globals_dtor);
1870 #else
1871 if (module->globals_ctor) {
1872 module->globals_ctor(module->globals_ptr);
1873 }
1874 #endif
1875 }
1876 if (module->module_startup_func) {
1877 EG(current_module) = module;
1878 if (module->module_startup_func(module->type, module->module_number)==FAILURE) {
1879 zend_error_noreturn(E_CORE_ERROR,"Unable to start %s module", module->name);
1880 EG(current_module) = NULL;
1881 return FAILURE;
1882 }
1883 EG(current_module) = NULL;
1884 }
1885 return SUCCESS;
1886 }
1887 /* }}} */
1888
zend_startup_module_zval(zval * zv)1889 static int zend_startup_module_zval(zval *zv) /* {{{ */
1890 {
1891 zend_module_entry *module = Z_PTR_P(zv);
1892
1893 return (zend_startup_module_ex(module) == SUCCESS) ? ZEND_HASH_APPLY_KEEP : ZEND_HASH_APPLY_REMOVE;
1894 }
1895 /* }}} */
1896
zend_sort_modules(void * base,size_t count,size_t siz,compare_func_t compare,swap_func_t swp)1897 static void zend_sort_modules(void *base, size_t count, size_t siz, compare_func_t compare, swap_func_t swp) /* {{{ */
1898 {
1899 Bucket *b1 = base;
1900 Bucket *b2;
1901 Bucket *end = b1 + count;
1902 Bucket tmp;
1903 zend_module_entry *m, *r;
1904
1905 while (b1 < end) {
1906 try_again:
1907 m = (zend_module_entry*)Z_PTR(b1->val);
1908 if (!m->module_started && m->deps) {
1909 const zend_module_dep *dep = m->deps;
1910 while (dep->name) {
1911 if (dep->type == MODULE_DEP_REQUIRED || dep->type == MODULE_DEP_OPTIONAL) {
1912 b2 = b1 + 1;
1913 while (b2 < end) {
1914 r = (zend_module_entry*)Z_PTR(b2->val);
1915 if (strcasecmp(dep->name, r->name) == 0) {
1916 tmp = *b1;
1917 *b1 = *b2;
1918 *b2 = tmp;
1919 goto try_again;
1920 }
1921 b2++;
1922 }
1923 }
1924 dep++;
1925 }
1926 }
1927 b1++;
1928 }
1929 }
1930 /* }}} */
1931
zend_collect_module_handlers(void)1932 ZEND_API void zend_collect_module_handlers(void) /* {{{ */
1933 {
1934 zend_module_entry *module;
1935 int startup_count = 0;
1936 int shutdown_count = 0;
1937 int post_deactivate_count = 0;
1938 zend_class_entry *ce;
1939 int class_count = 0;
1940
1941 /* Collect extensions with request startup/shutdown handlers */
1942 ZEND_HASH_FOREACH_PTR(&module_registry, module) {
1943 if (module->request_startup_func) {
1944 startup_count++;
1945 }
1946 if (module->request_shutdown_func) {
1947 shutdown_count++;
1948 }
1949 if (module->post_deactivate_func) {
1950 post_deactivate_count++;
1951 }
1952 } ZEND_HASH_FOREACH_END();
1953 module_request_startup_handlers = (zend_module_entry**)malloc(
1954 sizeof(zend_module_entry*) *
1955 (startup_count + 1 +
1956 shutdown_count + 1 +
1957 post_deactivate_count + 1));
1958 module_request_startup_handlers[startup_count] = NULL;
1959 module_request_shutdown_handlers = module_request_startup_handlers + startup_count + 1;
1960 module_request_shutdown_handlers[shutdown_count] = NULL;
1961 module_post_deactivate_handlers = module_request_shutdown_handlers + shutdown_count + 1;
1962 module_post_deactivate_handlers[post_deactivate_count] = NULL;
1963 startup_count = 0;
1964
1965 ZEND_HASH_FOREACH_PTR(&module_registry, module) {
1966 if (module->request_startup_func) {
1967 module_request_startup_handlers[startup_count++] = module;
1968 }
1969 if (module->request_shutdown_func) {
1970 module_request_shutdown_handlers[--shutdown_count] = module;
1971 }
1972 if (module->post_deactivate_func) {
1973 module_post_deactivate_handlers[--post_deactivate_count] = module;
1974 }
1975 } ZEND_HASH_FOREACH_END();
1976
1977 /* Collect internal classes with static members */
1978 ZEND_HASH_FOREACH_PTR(CG(class_table), ce) {
1979 if (ce->type == ZEND_INTERNAL_CLASS &&
1980 ce->default_static_members_count > 0) {
1981 class_count++;
1982 }
1983 } ZEND_HASH_FOREACH_END();
1984
1985 class_cleanup_handlers = (zend_class_entry**)malloc(
1986 sizeof(zend_class_entry*) *
1987 (class_count + 1));
1988 class_cleanup_handlers[class_count] = NULL;
1989
1990 if (class_count) {
1991 ZEND_HASH_FOREACH_PTR(CG(class_table), ce) {
1992 if (ce->type == ZEND_INTERNAL_CLASS &&
1993 ce->default_static_members_count > 0) {
1994 class_cleanup_handlers[--class_count] = ce;
1995 }
1996 } ZEND_HASH_FOREACH_END();
1997 }
1998 }
1999 /* }}} */
2000
zend_startup_modules(void)2001 ZEND_API int zend_startup_modules(void) /* {{{ */
2002 {
2003 zend_hash_sort_ex(&module_registry, zend_sort_modules, NULL, 0);
2004 zend_hash_apply(&module_registry, zend_startup_module_zval);
2005 return SUCCESS;
2006 }
2007 /* }}} */
2008
zend_destroy_modules(void)2009 ZEND_API void zend_destroy_modules(void) /* {{{ */
2010 {
2011 free(class_cleanup_handlers);
2012 free(module_request_startup_handlers);
2013 zend_hash_graceful_reverse_destroy(&module_registry);
2014 }
2015 /* }}} */
2016
zend_register_module_ex(zend_module_entry * module)2017 ZEND_API zend_module_entry* zend_register_module_ex(zend_module_entry *module) /* {{{ */
2018 {
2019 size_t name_len;
2020 zend_string *lcname;
2021 zend_module_entry *module_ptr;
2022
2023 if (!module) {
2024 return NULL;
2025 }
2026
2027 #if 0
2028 zend_printf("%s: Registering module %d\n", module->name, module->module_number);
2029 #endif
2030
2031 /* Check module dependencies */
2032 if (module->deps) {
2033 const zend_module_dep *dep = module->deps;
2034
2035 while (dep->name) {
2036 if (dep->type == MODULE_DEP_CONFLICTS) {
2037 name_len = strlen(dep->name);
2038 lcname = zend_string_alloc(name_len, 0);
2039 zend_str_tolower_copy(ZSTR_VAL(lcname), dep->name, name_len);
2040
2041 if (zend_hash_exists(&module_registry, lcname) || zend_get_extension(dep->name)) {
2042 zend_string_efree(lcname);
2043 /* TODO: Check version relationship */
2044 zend_error(E_CORE_WARNING, "Cannot load module '%s' because conflicting module '%s' is already loaded", module->name, dep->name);
2045 return NULL;
2046 }
2047 zend_string_efree(lcname);
2048 }
2049 ++dep;
2050 }
2051 }
2052
2053 name_len = strlen(module->name);
2054 lcname = zend_string_alloc(name_len, module->type == MODULE_PERSISTENT);
2055 zend_str_tolower_copy(ZSTR_VAL(lcname), module->name, name_len);
2056
2057 lcname = zend_new_interned_string(lcname);
2058 if ((module_ptr = zend_hash_add_mem(&module_registry, lcname, module, sizeof(zend_module_entry))) == NULL) {
2059 zend_error(E_CORE_WARNING, "Module '%s' already loaded", module->name);
2060 zend_string_release(lcname);
2061 return NULL;
2062 }
2063 module = module_ptr;
2064 EG(current_module) = module;
2065
2066 if (module->functions && zend_register_functions(NULL, module->functions, NULL, module->type)==FAILURE) {
2067 zend_hash_del(&module_registry, lcname);
2068 zend_string_release(lcname);
2069 EG(current_module) = NULL;
2070 zend_error(E_CORE_WARNING,"%s: Unable to register functions, unable to load", module->name);
2071 return NULL;
2072 }
2073
2074 EG(current_module) = NULL;
2075 zend_string_release(lcname);
2076 return module;
2077 }
2078 /* }}} */
2079
zend_register_internal_module(zend_module_entry * module)2080 ZEND_API zend_module_entry* zend_register_internal_module(zend_module_entry *module) /* {{{ */
2081 {
2082 module->module_number = zend_next_free_module();
2083 module->type = MODULE_PERSISTENT;
2084 return zend_register_module_ex(module);
2085 }
2086 /* }}} */
2087
zend_check_magic_method_implementation(const zend_class_entry * ce,const zend_function * fptr,int error_type)2088 ZEND_API void zend_check_magic_method_implementation(const zend_class_entry *ce, const zend_function *fptr, int error_type) /* {{{ */
2089 {
2090 char lcname[16];
2091 size_t name_len;
2092
2093 if (ZSTR_VAL(fptr->common.function_name)[0] != '_'
2094 || ZSTR_VAL(fptr->common.function_name)[1] != '_') {
2095 return;
2096 }
2097
2098 /* we don't care if the function name is longer, in fact lowercasing only
2099 * the beginning of the name speeds up the check process */
2100 name_len = ZSTR_LEN(fptr->common.function_name);
2101 zend_str_tolower_copy(lcname, ZSTR_VAL(fptr->common.function_name), MIN(name_len, sizeof(lcname)-1));
2102 lcname[sizeof(lcname)-1] = '\0'; /* zend_str_tolower_copy won't necessarily set the zero byte */
2103
2104 if (name_len == sizeof(ZEND_DESTRUCTOR_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_DESTRUCTOR_FUNC_NAME, sizeof(ZEND_DESTRUCTOR_FUNC_NAME) - 1) && fptr->common.num_args != 0) {
2105 zend_error(error_type, "Destructor %s::%s() cannot take arguments", ZSTR_VAL(ce->name), ZEND_DESTRUCTOR_FUNC_NAME);
2106 } else if (name_len == sizeof(ZEND_CLONE_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME) - 1) && fptr->common.num_args != 0) {
2107 zend_error(error_type, "Method %s::%s() cannot accept any arguments", ZSTR_VAL(ce->name), ZEND_CLONE_FUNC_NAME);
2108 } else if (name_len == sizeof(ZEND_GET_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME) - 1)) {
2109 if (fptr->common.num_args != 1) {
2110 zend_error(error_type, "Method %s::%s() must take exactly 1 argument", ZSTR_VAL(ce->name), ZEND_GET_FUNC_NAME);
2111 } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr, 1)) {
2112 zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ZSTR_VAL(ce->name), ZEND_GET_FUNC_NAME);
2113 }
2114 } else if (name_len == sizeof(ZEND_SET_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME) - 1)) {
2115 if (fptr->common.num_args != 2) {
2116 zend_error(error_type, "Method %s::%s() must take exactly 2 arguments", ZSTR_VAL(ce->name), ZEND_SET_FUNC_NAME);
2117 } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr, 1) || ARG_SHOULD_BE_SENT_BY_REF(fptr, 2)) {
2118 zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ZSTR_VAL(ce->name), ZEND_SET_FUNC_NAME);
2119 }
2120 } else if (name_len == sizeof(ZEND_UNSET_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_UNSET_FUNC_NAME, sizeof(ZEND_UNSET_FUNC_NAME) - 1)) {
2121 if (fptr->common.num_args != 1) {
2122 zend_error(error_type, "Method %s::%s() must take exactly 1 argument", ZSTR_VAL(ce->name), ZEND_UNSET_FUNC_NAME);
2123 } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr, 1)) {
2124 zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ZSTR_VAL(ce->name), ZEND_UNSET_FUNC_NAME);
2125 }
2126 } else if (name_len == sizeof(ZEND_ISSET_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_ISSET_FUNC_NAME, sizeof(ZEND_ISSET_FUNC_NAME) - 1)) {
2127 if (fptr->common.num_args != 1) {
2128 zend_error(error_type, "Method %s::%s() must take exactly 1 argument", ZSTR_VAL(ce->name), ZEND_ISSET_FUNC_NAME);
2129 } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr, 1)) {
2130 zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ZSTR_VAL(ce->name), ZEND_ISSET_FUNC_NAME);
2131 }
2132 } else if (name_len == sizeof(ZEND_CALL_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME) - 1)) {
2133 if (fptr->common.num_args != 2) {
2134 zend_error(error_type, "Method %s::%s() must take exactly 2 arguments", ZSTR_VAL(ce->name), ZEND_CALL_FUNC_NAME);
2135 } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr, 1) || ARG_SHOULD_BE_SENT_BY_REF(fptr, 2)) {
2136 zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ZSTR_VAL(ce->name), ZEND_CALL_FUNC_NAME);
2137 }
2138 } else if (name_len == sizeof(ZEND_CALLSTATIC_FUNC_NAME) - 1 &&
2139 !memcmp(lcname, ZEND_CALLSTATIC_FUNC_NAME, sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1)
2140 ) {
2141 if (fptr->common.num_args != 2) {
2142 zend_error(error_type, "Method %s::__callStatic() must take exactly 2 arguments", ZSTR_VAL(ce->name));
2143 } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr, 1) || ARG_SHOULD_BE_SENT_BY_REF(fptr, 2)) {
2144 zend_error(error_type, "Method %s::__callStatic() cannot take arguments by reference", ZSTR_VAL(ce->name));
2145 }
2146 } else if (name_len == sizeof(ZEND_TOSTRING_FUNC_NAME) - 1 &&
2147 !memcmp(lcname, ZEND_TOSTRING_FUNC_NAME, sizeof(ZEND_TOSTRING_FUNC_NAME)-1) && fptr->common.num_args != 0
2148 ) {
2149 zend_error(error_type, "Method %s::%s() cannot take arguments", ZSTR_VAL(ce->name), ZEND_TOSTRING_FUNC_NAME);
2150 } else if (name_len == sizeof(ZEND_DEBUGINFO_FUNC_NAME) - 1 &&
2151 !memcmp(lcname, ZEND_DEBUGINFO_FUNC_NAME, sizeof(ZEND_DEBUGINFO_FUNC_NAME)-1) && fptr->common.num_args != 0) {
2152 zend_error(error_type, "Method %s::%s() cannot take arguments", ZSTR_VAL(ce->name), ZEND_DEBUGINFO_FUNC_NAME);
2153 }
2154 }
2155 /* }}} */
2156
2157 /* registers all functions in *library_functions in the function hash */
zend_register_functions(zend_class_entry * scope,const zend_function_entry * functions,HashTable * function_table,int type)2158 ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_function_entry *functions, HashTable *function_table, int type) /* {{{ */
2159 {
2160 const zend_function_entry *ptr = functions;
2161 zend_function function, *reg_function;
2162 zend_internal_function *internal_function = (zend_internal_function *)&function;
2163 int count=0, unload=0;
2164 HashTable *target_function_table = function_table;
2165 int error_type;
2166 zend_function *ctor = NULL, *dtor = NULL, *clone = NULL, *__get = NULL, *__set = NULL, *__unset = NULL, *__isset = NULL, *__call = NULL, *__callstatic = NULL, *__tostring = NULL, *__debugInfo = NULL;
2167 zend_string *lowercase_name;
2168 size_t fname_len;
2169 const char *lc_class_name = NULL;
2170 size_t class_name_len = 0;
2171
2172 if (type==MODULE_PERSISTENT) {
2173 error_type = E_CORE_WARNING;
2174 } else {
2175 error_type = E_WARNING;
2176 }
2177
2178 if (!target_function_table) {
2179 target_function_table = CG(function_table);
2180 }
2181 internal_function->type = ZEND_INTERNAL_FUNCTION;
2182 internal_function->module = EG(current_module);
2183 memset(internal_function->reserved, 0, ZEND_MAX_RESERVED_RESOURCES * sizeof(void*));
2184
2185 if (scope) {
2186 class_name_len = ZSTR_LEN(scope->name);
2187 if ((lc_class_name = zend_memrchr(ZSTR_VAL(scope->name), '\\', class_name_len))) {
2188 ++lc_class_name;
2189 class_name_len -= (lc_class_name - ZSTR_VAL(scope->name));
2190 lc_class_name = zend_str_tolower_dup(lc_class_name, class_name_len);
2191 } else {
2192 lc_class_name = zend_str_tolower_dup(ZSTR_VAL(scope->name), class_name_len);
2193 }
2194 }
2195
2196 while (ptr->fname) {
2197 fname_len = strlen(ptr->fname);
2198 internal_function->handler = ptr->handler;
2199 internal_function->function_name = zend_string_init_interned(ptr->fname, fname_len, 1);
2200 internal_function->scope = scope;
2201 internal_function->prototype = NULL;
2202 if (ptr->flags) {
2203 if (!(ptr->flags & ZEND_ACC_PPP_MASK)) {
2204 if (ptr->flags != ZEND_ACC_DEPRECATED && scope) {
2205 zend_error(error_type, "Invalid access level for %s%s%s() - access must be exactly one of public, protected or private", scope ? ZSTR_VAL(scope->name) : "", scope ? "::" : "", ptr->fname);
2206 }
2207 internal_function->fn_flags = ZEND_ACC_PUBLIC | ptr->flags;
2208 } else {
2209 internal_function->fn_flags = ptr->flags;
2210 }
2211 } else {
2212 internal_function->fn_flags = ZEND_ACC_PUBLIC;
2213 }
2214 if (ptr->arg_info) {
2215 zend_internal_function_info *info = (zend_internal_function_info*)ptr->arg_info;
2216
2217 internal_function->arg_info = (zend_internal_arg_info*)ptr->arg_info+1;
2218 internal_function->num_args = ptr->num_args;
2219 /* Currently you cannot denote that the function can accept less arguments than num_args */
2220 if (info->required_num_args == (zend_uintptr_t)-1) {
2221 internal_function->required_num_args = ptr->num_args;
2222 } else {
2223 internal_function->required_num_args = info->required_num_args;
2224 }
2225 if (info->return_reference) {
2226 internal_function->fn_flags |= ZEND_ACC_RETURN_REFERENCE;
2227 }
2228 if (ptr->arg_info[ptr->num_args].is_variadic) {
2229 internal_function->fn_flags |= ZEND_ACC_VARIADIC;
2230 /* Don't count the variadic argument */
2231 internal_function->num_args--;
2232 }
2233 if (ZEND_TYPE_IS_SET(info->type)) {
2234 if (ZEND_TYPE_IS_CLASS(info->type)) {
2235 const char *type_name = (const char*)info->type;
2236
2237 if (type_name[0] == '?') {
2238 type_name++;
2239 }
2240 if (!scope && (!strcasecmp(type_name, "self") || !strcasecmp(type_name, "parent"))) {
2241 zend_error_noreturn(E_CORE_ERROR, "Cannot declare a return type of %s outside of a class scope", type_name);
2242 }
2243 }
2244
2245 internal_function->fn_flags |= ZEND_ACC_HAS_RETURN_TYPE;
2246 }
2247 } else {
2248 internal_function->arg_info = NULL;
2249 internal_function->num_args = 0;
2250 internal_function->required_num_args = 0;
2251 }
2252 zend_set_function_arg_flags((zend_function*)internal_function);
2253 if (ptr->flags & ZEND_ACC_ABSTRACT) {
2254 if (scope) {
2255 /* This is a class that must be abstract itself. Here we set the check info. */
2256 scope->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
2257 if (!(scope->ce_flags & ZEND_ACC_INTERFACE)) {
2258 /* Since the class is not an interface it needs to be declared as a abstract class. */
2259 /* Since here we are handling internal functions only we can add the keyword flag. */
2260 /* This time we set the flag for the keyword 'abstract'. */
2261 scope->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;
2262 }
2263 }
2264 if (ptr->flags & ZEND_ACC_STATIC && (!scope || !(scope->ce_flags & ZEND_ACC_INTERFACE))) {
2265 zend_error(error_type, "Static function %s%s%s() cannot be abstract", scope ? ZSTR_VAL(scope->name) : "", scope ? "::" : "", ptr->fname);
2266 }
2267 } else {
2268 if (scope && (scope->ce_flags & ZEND_ACC_INTERFACE)) {
2269 efree((char*)lc_class_name);
2270 zend_error(error_type, "Interface %s cannot contain non abstract method %s()", ZSTR_VAL(scope->name), ptr->fname);
2271 return FAILURE;
2272 }
2273 if (!internal_function->handler) {
2274 if (scope) {
2275 efree((char*)lc_class_name);
2276 }
2277 zend_error(error_type, "Method %s%s%s() cannot be a NULL function", scope ? ZSTR_VAL(scope->name) : "", scope ? "::" : "", ptr->fname);
2278 zend_unregister_functions(functions, count, target_function_table);
2279 return FAILURE;
2280 }
2281 }
2282 lowercase_name = zend_string_tolower_ex(internal_function->function_name, type == MODULE_PERSISTENT);
2283 lowercase_name = zend_new_interned_string(lowercase_name);
2284 reg_function = malloc(sizeof(zend_internal_function));
2285 memcpy(reg_function, &function, sizeof(zend_internal_function));
2286 if (zend_hash_add_ptr(target_function_table, lowercase_name, reg_function) == NULL) {
2287 unload=1;
2288 free(reg_function);
2289 zend_string_release(lowercase_name);
2290 break;
2291 }
2292
2293 /* If types of arguments have to be checked */
2294 if (reg_function->common.arg_info && reg_function->common.num_args) {
2295 uint32_t i;
2296 for (i = 0; i < reg_function->common.num_args; i++) {
2297 if (ZEND_TYPE_IS_SET(reg_function->common.arg_info[i].type)) {
2298 reg_function->common.fn_flags |= ZEND_ACC_HAS_TYPE_HINTS;
2299 break;
2300 }
2301 }
2302 }
2303
2304 if (reg_function->common.arg_info &&
2305 (reg_function->common.fn_flags & (ZEND_ACC_HAS_RETURN_TYPE|ZEND_ACC_HAS_TYPE_HINTS))) {
2306 /* convert "const char*" class type names into "zend_string*" */
2307 uint32_t i;
2308 uint32_t num_args = reg_function->common.num_args + 1;
2309 zend_arg_info *arg_info = reg_function->common.arg_info - 1;
2310 zend_arg_info *new_arg_info;
2311
2312 if (reg_function->common.fn_flags & ZEND_ACC_VARIADIC) {
2313 num_args++;
2314 }
2315 new_arg_info = malloc(sizeof(zend_arg_info) * num_args);
2316 memcpy(new_arg_info, arg_info, sizeof(zend_arg_info) * num_args);
2317 reg_function->common.arg_info = new_arg_info + 1;
2318 for (i = 0; i < num_args; i++) {
2319 if (ZEND_TYPE_IS_CLASS(new_arg_info[i].type)) {
2320 const char *class_name = (const char*)new_arg_info[i].type;
2321 zend_bool allow_null = 0;
2322 zend_string *str;
2323
2324 if (class_name[0] == '?') {
2325 class_name++;
2326 allow_null = 1;
2327 }
2328 str = zend_string_init_interned(class_name, strlen(class_name), 1);
2329 new_arg_info[i].type = ZEND_TYPE_ENCODE_CLASS(str, allow_null);
2330 }
2331 }
2332 }
2333
2334 if (scope) {
2335 /* Look for ctor, dtor, clone
2336 * If it's an old-style constructor, store it only if we don't have
2337 * a constructor already.
2338 */
2339 if ((fname_len == class_name_len) && !ctor && !memcmp(ZSTR_VAL(lowercase_name), lc_class_name, class_name_len+1)) {
2340 ctor = reg_function;
2341 } else if (ZSTR_VAL(lowercase_name)[0] != '_' || ZSTR_VAL(lowercase_name)[1] != '_') {
2342 reg_function = NULL;
2343 } else if (zend_string_equals_literal(lowercase_name, ZEND_CONSTRUCTOR_FUNC_NAME)) {
2344 ctor = reg_function;
2345 } else if (zend_string_equals_literal(lowercase_name, ZEND_DESTRUCTOR_FUNC_NAME)) {
2346 dtor = reg_function;
2347 if (internal_function->num_args) {
2348 zend_error(error_type, "Destructor %s::%s() cannot take arguments", ZSTR_VAL(scope->name), ptr->fname);
2349 }
2350 } else if (zend_string_equals_literal(lowercase_name, ZEND_CLONE_FUNC_NAME)) {
2351 clone = reg_function;
2352 } else if (zend_string_equals_literal(lowercase_name, ZEND_CALL_FUNC_NAME)) {
2353 __call = reg_function;
2354 } else if (zend_string_equals_literal(lowercase_name, ZEND_CALLSTATIC_FUNC_NAME)) {
2355 __callstatic = reg_function;
2356 } else if (zend_string_equals_literal(lowercase_name, ZEND_TOSTRING_FUNC_NAME)) {
2357 __tostring = reg_function;
2358 } else if (zend_string_equals_literal(lowercase_name, ZEND_GET_FUNC_NAME)) {
2359 __get = reg_function;
2360 scope->ce_flags |= ZEND_ACC_USE_GUARDS;
2361 } else if (zend_string_equals_literal(lowercase_name, ZEND_SET_FUNC_NAME)) {
2362 __set = reg_function;
2363 scope->ce_flags |= ZEND_ACC_USE_GUARDS;
2364 } else if (zend_string_equals_literal(lowercase_name, ZEND_UNSET_FUNC_NAME)) {
2365 __unset = reg_function;
2366 scope->ce_flags |= ZEND_ACC_USE_GUARDS;
2367 } else if (zend_string_equals_literal(lowercase_name, ZEND_ISSET_FUNC_NAME)) {
2368 __isset = reg_function;
2369 scope->ce_flags |= ZEND_ACC_USE_GUARDS;
2370 } else if (zend_string_equals_literal(lowercase_name, ZEND_DEBUGINFO_FUNC_NAME)) {
2371 __debugInfo = reg_function;
2372 } else {
2373 reg_function = NULL;
2374 }
2375 if (reg_function) {
2376 zend_check_magic_method_implementation(scope, reg_function, error_type);
2377 }
2378 }
2379 ptr++;
2380 count++;
2381 zend_string_release(lowercase_name);
2382 }
2383 if (unload) { /* before unloading, display all remaining bad function in the module */
2384 if (scope) {
2385 efree((char*)lc_class_name);
2386 }
2387 while (ptr->fname) {
2388 fname_len = strlen(ptr->fname);
2389 lowercase_name = zend_string_alloc(fname_len, 0);
2390 zend_str_tolower_copy(ZSTR_VAL(lowercase_name), ptr->fname, fname_len);
2391 if (zend_hash_exists(target_function_table, lowercase_name)) {
2392 zend_error(error_type, "Function registration failed - duplicate name - %s%s%s", scope ? ZSTR_VAL(scope->name) : "", scope ? "::" : "", ptr->fname);
2393 }
2394 zend_string_efree(lowercase_name);
2395 ptr++;
2396 }
2397 zend_unregister_functions(functions, count, target_function_table);
2398 return FAILURE;
2399 }
2400 if (scope) {
2401 scope->constructor = ctor;
2402 scope->destructor = dtor;
2403 scope->clone = clone;
2404 scope->__call = __call;
2405 scope->__callstatic = __callstatic;
2406 scope->__tostring = __tostring;
2407 scope->__get = __get;
2408 scope->__set = __set;
2409 scope->__unset = __unset;
2410 scope->__isset = __isset;
2411 scope->__debugInfo = __debugInfo;
2412 if (ctor) {
2413 ctor->common.fn_flags |= ZEND_ACC_CTOR;
2414 if (ctor->common.fn_flags & ZEND_ACC_STATIC) {
2415 zend_error(error_type, "Constructor %s::%s() cannot be static", ZSTR_VAL(scope->name), ZSTR_VAL(ctor->common.function_name));
2416 }
2417 ctor->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
2418 }
2419 if (dtor) {
2420 dtor->common.fn_flags |= ZEND_ACC_DTOR;
2421 if (dtor->common.fn_flags & ZEND_ACC_STATIC) {
2422 zend_error(error_type, "Destructor %s::%s() cannot be static", ZSTR_VAL(scope->name), ZSTR_VAL(dtor->common.function_name));
2423 }
2424 dtor->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
2425 }
2426 if (clone) {
2427 if (clone->common.fn_flags & ZEND_ACC_STATIC) {
2428 zend_error(error_type, "%s::%s() cannot be static", ZSTR_VAL(scope->name), ZSTR_VAL(clone->common.function_name));
2429 }
2430 clone->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
2431 }
2432 if (__call) {
2433 if (__call->common.fn_flags & ZEND_ACC_STATIC) {
2434 zend_error(error_type, "Method %s::%s() cannot be static", ZSTR_VAL(scope->name), ZSTR_VAL(__call->common.function_name));
2435 }
2436 __call->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
2437 }
2438 if (__callstatic) {
2439 if (!(__callstatic->common.fn_flags & ZEND_ACC_STATIC)) {
2440 zend_error(error_type, "Method %s::%s() must be static", ZSTR_VAL(scope->name), ZSTR_VAL(__callstatic->common.function_name));
2441 }
2442 __callstatic->common.fn_flags |= ZEND_ACC_STATIC;
2443 }
2444 if (__tostring) {
2445 if (__tostring->common.fn_flags & ZEND_ACC_STATIC) {
2446 zend_error(error_type, "Method %s::%s() cannot be static", ZSTR_VAL(scope->name), ZSTR_VAL(__tostring->common.function_name));
2447 }
2448 __tostring->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
2449 }
2450 if (__get) {
2451 if (__get->common.fn_flags & ZEND_ACC_STATIC) {
2452 zend_error(error_type, "Method %s::%s() cannot be static", ZSTR_VAL(scope->name), ZSTR_VAL(__get->common.function_name));
2453 }
2454 __get->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
2455 }
2456 if (__set) {
2457 if (__set->common.fn_flags & ZEND_ACC_STATIC) {
2458 zend_error(error_type, "Method %s::%s() cannot be static", ZSTR_VAL(scope->name), ZSTR_VAL(__set->common.function_name));
2459 }
2460 __set->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
2461 }
2462 if (__unset) {
2463 if (__unset->common.fn_flags & ZEND_ACC_STATIC) {
2464 zend_error(error_type, "Method %s::%s() cannot be static", ZSTR_VAL(scope->name), ZSTR_VAL(__unset->common.function_name));
2465 }
2466 __unset->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
2467 }
2468 if (__isset) {
2469 if (__isset->common.fn_flags & ZEND_ACC_STATIC) {
2470 zend_error(error_type, "Method %s::%s() cannot be static", ZSTR_VAL(scope->name), ZSTR_VAL(__isset->common.function_name));
2471 }
2472 __isset->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
2473 }
2474 if (__debugInfo) {
2475 if (__debugInfo->common.fn_flags & ZEND_ACC_STATIC) {
2476 zend_error(error_type, "Method %s::%s() cannot be static", ZSTR_VAL(scope->name), ZSTR_VAL(__debugInfo->common.function_name));
2477 }
2478 }
2479
2480 if (ctor && ctor->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE && ctor->common.fn_flags & ZEND_ACC_CTOR) {
2481 zend_error_noreturn(E_CORE_ERROR, "Constructor %s::%s() cannot declare a return type", ZSTR_VAL(scope->name), ZSTR_VAL(ctor->common.function_name));
2482 }
2483
2484 if (dtor && dtor->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE && dtor->common.fn_flags & ZEND_ACC_DTOR) {
2485 zend_error_noreturn(E_CORE_ERROR, "Destructor %s::%s() cannot declare a return type", ZSTR_VAL(scope->name), ZSTR_VAL(dtor->common.function_name));
2486 }
2487
2488 if (clone && (clone->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE)) {
2489 zend_error_noreturn(E_CORE_ERROR, "%s::%s() cannot declare a return type", ZSTR_VAL(scope->name), ZSTR_VAL(clone->common.function_name));
2490 }
2491 efree((char*)lc_class_name);
2492 }
2493 return SUCCESS;
2494 }
2495 /* }}} */
2496
2497 /* count=-1 means erase all functions, otherwise,
2498 * erase the first count functions
2499 */
zend_unregister_functions(const zend_function_entry * functions,int count,HashTable * function_table)2500 ZEND_API void zend_unregister_functions(const zend_function_entry *functions, int count, HashTable *function_table) /* {{{ */
2501 {
2502 const zend_function_entry *ptr = functions;
2503 int i=0;
2504 HashTable *target_function_table = function_table;
2505 zend_string *lowercase_name;
2506 size_t fname_len;
2507
2508 if (!target_function_table) {
2509 target_function_table = CG(function_table);
2510 }
2511 while (ptr->fname) {
2512 if (count!=-1 && i>=count) {
2513 break;
2514 }
2515 fname_len = strlen(ptr->fname);
2516 lowercase_name = zend_string_alloc(fname_len, 0);
2517 zend_str_tolower_copy(ZSTR_VAL(lowercase_name), ptr->fname, fname_len);
2518 zend_hash_del(target_function_table, lowercase_name);
2519 zend_string_efree(lowercase_name);
2520 ptr++;
2521 i++;
2522 }
2523 }
2524 /* }}} */
2525
zend_startup_module(zend_module_entry * module)2526 ZEND_API int zend_startup_module(zend_module_entry *module) /* {{{ */
2527 {
2528 if ((module = zend_register_internal_module(module)) != NULL && zend_startup_module_ex(module) == SUCCESS) {
2529 return SUCCESS;
2530 }
2531 return FAILURE;
2532 }
2533 /* }}} */
2534
zend_get_module_started(const char * module_name)2535 ZEND_API int zend_get_module_started(const char *module_name) /* {{{ */
2536 {
2537 zend_module_entry *module;
2538
2539 module = zend_hash_str_find_ptr(&module_registry, module_name, strlen(module_name));
2540 return (module && module->module_started) ? SUCCESS : FAILURE;
2541 }
2542 /* }}} */
2543
clean_module_class(zval * el,void * arg)2544 static int clean_module_class(zval *el, void *arg) /* {{{ */
2545 {
2546 zend_class_entry *ce = (zend_class_entry *)Z_PTR_P(el);
2547 int module_number = *(int *)arg;
2548 if (ce->type == ZEND_INTERNAL_CLASS && ce->info.internal.module->module_number == module_number) {
2549 return ZEND_HASH_APPLY_REMOVE;
2550 } else {
2551 return ZEND_HASH_APPLY_KEEP;
2552 }
2553 }
2554 /* }}} */
2555
clean_module_classes(int module_number)2556 static void clean_module_classes(int module_number) /* {{{ */
2557 {
2558 zend_hash_apply_with_argument(EG(class_table), clean_module_class, (void *) &module_number);
2559 }
2560 /* }}} */
2561
module_destructor(zend_module_entry * module)2562 void module_destructor(zend_module_entry *module) /* {{{ */
2563 {
2564
2565 if (module->type == MODULE_TEMPORARY) {
2566 zend_clean_module_rsrc_dtors(module->module_number);
2567 clean_module_constants(module->module_number);
2568 clean_module_classes(module->module_number);
2569 }
2570
2571 if (module->module_started && module->module_shutdown_func) {
2572 #if 0
2573 zend_printf("%s: Module shutdown\n", module->name);
2574 #endif
2575 module->module_shutdown_func(module->type, module->module_number);
2576 }
2577
2578 /* Deinitilaise module globals */
2579 if (module->globals_size) {
2580 #ifdef ZTS
2581 if (*module->globals_id_ptr) {
2582 ts_free_id(*module->globals_id_ptr);
2583 }
2584 #else
2585 if (module->globals_dtor) {
2586 module->globals_dtor(module->globals_ptr);
2587 }
2588 #endif
2589 }
2590
2591 module->module_started=0;
2592 if (module->type == MODULE_TEMPORARY && module->functions) {
2593 zend_unregister_functions(module->functions, -1, NULL);
2594 }
2595
2596 #if HAVE_LIBDL
2597 if (module->handle && !getenv("ZEND_DONT_UNLOAD_MODULES")) {
2598 DL_UNLOAD(module->handle);
2599 }
2600 #endif
2601 }
2602 /* }}} */
2603
zend_activate_modules(void)2604 ZEND_API void zend_activate_modules(void) /* {{{ */
2605 {
2606 zend_module_entry **p = module_request_startup_handlers;
2607
2608 while (*p) {
2609 zend_module_entry *module = *p;
2610
2611 if (module->request_startup_func(module->type, module->module_number)==FAILURE) {
2612 zend_error(E_WARNING, "request_startup() for %s module failed", module->name);
2613 exit(1);
2614 }
2615 p++;
2616 }
2617 }
2618 /* }}} */
2619
2620 /* call request shutdown for all modules */
module_registry_cleanup(zval * zv)2621 static int module_registry_cleanup(zval *zv) /* {{{ */
2622 {
2623 zend_module_entry *module = Z_PTR_P(zv);
2624
2625 if (module->request_shutdown_func) {
2626 #if 0
2627 zend_printf("%s: Request shutdown\n", module->name);
2628 #endif
2629 module->request_shutdown_func(module->type, module->module_number);
2630 }
2631 return 0;
2632 }
2633 /* }}} */
2634
zend_deactivate_modules(void)2635 ZEND_API void zend_deactivate_modules(void) /* {{{ */
2636 {
2637 EG(current_execute_data) = NULL; /* we're no longer executing anything */
2638
2639 zend_try {
2640 if (EG(full_tables_cleanup)) {
2641 zend_hash_reverse_apply(&module_registry, module_registry_cleanup);
2642 } else {
2643 zend_module_entry **p = module_request_shutdown_handlers;
2644
2645 while (*p) {
2646 zend_module_entry *module = *p;
2647
2648 module->request_shutdown_func(module->type, module->module_number);
2649 p++;
2650 }
2651 }
2652 } zend_end_try();
2653 }
2654 /* }}} */
2655
zend_cleanup_internal_classes(void)2656 ZEND_API void zend_cleanup_internal_classes(void) /* {{{ */
2657 {
2658 zend_class_entry **p = class_cleanup_handlers;
2659
2660 while (*p) {
2661 zend_cleanup_internal_class_data(*p);
2662 p++;
2663 }
2664 }
2665 /* }}} */
2666
module_registry_unload_temp(const zend_module_entry * module)2667 int module_registry_unload_temp(const zend_module_entry *module) /* {{{ */
2668 {
2669 return (module->type == MODULE_TEMPORARY) ? ZEND_HASH_APPLY_REMOVE : ZEND_HASH_APPLY_STOP;
2670 }
2671 /* }}} */
2672
module_registry_unload_temp_wrapper(zval * el)2673 static int module_registry_unload_temp_wrapper(zval *el) /* {{{ */
2674 {
2675 zend_module_entry *module = (zend_module_entry *)Z_PTR_P(el);
2676 return module_registry_unload_temp((const zend_module_entry *)module);
2677 }
2678 /* }}} */
2679
exec_done_cb(zval * el)2680 static int exec_done_cb(zval *el) /* {{{ */
2681 {
2682 zend_module_entry *module = (zend_module_entry *)Z_PTR_P(el);
2683 if (module->post_deactivate_func) {
2684 module->post_deactivate_func();
2685 }
2686 return 0;
2687 }
2688 /* }}} */
2689
zend_post_deactivate_modules(void)2690 ZEND_API void zend_post_deactivate_modules(void) /* {{{ */
2691 {
2692 if (EG(full_tables_cleanup)) {
2693 zend_hash_apply(&module_registry, exec_done_cb);
2694 zend_hash_reverse_apply(&module_registry, module_registry_unload_temp_wrapper);
2695 } else {
2696 zend_module_entry **p = module_post_deactivate_handlers;
2697
2698 while (*p) {
2699 zend_module_entry *module = *p;
2700
2701 module->post_deactivate_func();
2702 p++;
2703 }
2704 }
2705 }
2706 /* }}} */
2707
2708 /* return the next free module number */
zend_next_free_module(void)2709 ZEND_API int zend_next_free_module(void) /* {{{ */
2710 {
2711 return zend_hash_num_elements(&module_registry) + 1;
2712 }
2713 /* }}} */
2714
do_register_internal_class(zend_class_entry * orig_class_entry,uint32_t ce_flags)2715 static zend_class_entry *do_register_internal_class(zend_class_entry *orig_class_entry, uint32_t ce_flags) /* {{{ */
2716 {
2717 zend_class_entry *class_entry = malloc(sizeof(zend_class_entry));
2718 zend_string *lowercase_name;
2719 *class_entry = *orig_class_entry;
2720
2721 class_entry->type = ZEND_INTERNAL_CLASS;
2722 zend_initialize_class_data(class_entry, 0);
2723 class_entry->ce_flags = ce_flags | ZEND_ACC_CONSTANTS_UPDATED;
2724 class_entry->info.internal.module = EG(current_module);
2725
2726 if (class_entry->info.internal.builtin_functions) {
2727 zend_register_functions(class_entry, class_entry->info.internal.builtin_functions, &class_entry->function_table, EG(current_module)->type);
2728 }
2729
2730 lowercase_name = zend_string_tolower_ex(orig_class_entry->name, EG(current_module)->type == MODULE_PERSISTENT);
2731 lowercase_name = zend_new_interned_string(lowercase_name);
2732 zend_hash_update_ptr(CG(class_table), lowercase_name, class_entry);
2733 zend_string_release_ex(lowercase_name, 1);
2734 return class_entry;
2735 }
2736 /* }}} */
2737
2738 /* If parent_ce is not NULL then it inherits from parent_ce
2739 * If parent_ce is NULL and parent_name isn't then it looks for the parent and inherits from it
2740 * If both parent_ce and parent_name are NULL it does a regular class registration
2741 * If parent_name is specified but not found NULL is returned
2742 */
zend_register_internal_class_ex(zend_class_entry * class_entry,zend_class_entry * parent_ce)2743 ZEND_API zend_class_entry *zend_register_internal_class_ex(zend_class_entry *class_entry, zend_class_entry *parent_ce) /* {{{ */
2744 {
2745 zend_class_entry *register_class;
2746
2747 register_class = zend_register_internal_class(class_entry);
2748
2749 if (parent_ce) {
2750 zend_do_inheritance(register_class, parent_ce);
2751 }
2752 return register_class;
2753 }
2754 /* }}} */
2755
zend_class_implements(zend_class_entry * class_entry,int num_interfaces,...)2756 ZEND_API void zend_class_implements(zend_class_entry *class_entry, int num_interfaces, ...) /* {{{ */
2757 {
2758 zend_class_entry *interface_entry;
2759 va_list interface_list;
2760 va_start(interface_list, num_interfaces);
2761
2762 while (num_interfaces--) {
2763 interface_entry = va_arg(interface_list, zend_class_entry *);
2764 zend_do_implement_interface(class_entry, interface_entry);
2765 }
2766
2767 va_end(interface_list);
2768 }
2769 /* }}} */
2770
2771 /* A class that contains at least one abstract method automatically becomes an abstract class.
2772 */
zend_register_internal_class(zend_class_entry * orig_class_entry)2773 ZEND_API zend_class_entry *zend_register_internal_class(zend_class_entry *orig_class_entry) /* {{{ */
2774 {
2775 return do_register_internal_class(orig_class_entry, 0);
2776 }
2777 /* }}} */
2778
zend_register_internal_interface(zend_class_entry * orig_class_entry)2779 ZEND_API zend_class_entry *zend_register_internal_interface(zend_class_entry *orig_class_entry) /* {{{ */
2780 {
2781 return do_register_internal_class(orig_class_entry, ZEND_ACC_INTERFACE);
2782 }
2783 /* }}} */
2784
zend_register_class_alias_ex(const char * name,size_t name_len,zend_class_entry * ce,int persistent)2785 ZEND_API int zend_register_class_alias_ex(const char *name, size_t name_len, zend_class_entry *ce, int persistent) /* {{{ */
2786 {
2787 zend_string *lcname;
2788
2789 /* TODO: Move this out of here in 7.4. */
2790 if (persistent && EG(current_module) && EG(current_module)->type == MODULE_TEMPORARY) {
2791 persistent = 0;
2792 }
2793
2794 if (name[0] == '\\') {
2795 lcname = zend_string_alloc(name_len-1, persistent);
2796 zend_str_tolower_copy(ZSTR_VAL(lcname), name+1, name_len-1);
2797 } else {
2798 lcname = zend_string_alloc(name_len, persistent);
2799 zend_str_tolower_copy(ZSTR_VAL(lcname), name, name_len);
2800 }
2801
2802 zend_assert_valid_class_name(lcname);
2803
2804 lcname = zend_new_interned_string(lcname);
2805 ce = zend_hash_add_ptr(CG(class_table), lcname, ce);
2806 zend_string_release_ex(lcname, 0);
2807 if (ce) {
2808 ce->refcount++;
2809 return SUCCESS;
2810 }
2811 return FAILURE;
2812 }
2813 /* }}} */
2814
zend_set_hash_symbol(zval * symbol,const char * name,int name_length,zend_bool is_ref,int num_symbol_tables,...)2815 ZEND_API int zend_set_hash_symbol(zval *symbol, const char *name, int name_length, zend_bool is_ref, int num_symbol_tables, ...) /* {{{ */
2816 {
2817 HashTable *symbol_table;
2818 va_list symbol_table_list;
2819
2820 if (num_symbol_tables <= 0) return FAILURE;
2821
2822 if (is_ref) {
2823 ZVAL_MAKE_REF(symbol);
2824 }
2825
2826 va_start(symbol_table_list, num_symbol_tables);
2827 while (num_symbol_tables-- > 0) {
2828 symbol_table = va_arg(symbol_table_list, HashTable *);
2829 zend_hash_str_update(symbol_table, name, name_length, symbol);
2830 Z_TRY_ADDREF_P(symbol);
2831 }
2832 va_end(symbol_table_list);
2833 return SUCCESS;
2834 }
2835 /* }}} */
2836
2837 /* Disabled functions support */
2838
2839 /* {{{ proto void display_disabled_function(void)
2840 Dummy function which displays an error when a disabled function is called. */
ZEND_FUNCTION(display_disabled_function)2841 ZEND_API ZEND_FUNCTION(display_disabled_function)
2842 {
2843 zend_error(E_WARNING, "%s() has been disabled for security reasons", get_active_function_name());
2844 }
2845 /* }}} */
2846
zend_disable_function(char * function_name,size_t function_name_length)2847 ZEND_API int zend_disable_function(char *function_name, size_t function_name_length) /* {{{ */
2848 {
2849 zend_internal_function *func;
2850 if ((func = zend_hash_str_find_ptr(CG(function_table), function_name, function_name_length))) {
2851 func->fn_flags &= ~(ZEND_ACC_VARIADIC | ZEND_ACC_HAS_TYPE_HINTS | ZEND_ACC_HAS_RETURN_TYPE);
2852 func->num_args = 0;
2853 func->arg_info = NULL;
2854 func->handler = ZEND_FN(display_disabled_function);
2855 return SUCCESS;
2856 }
2857 return FAILURE;
2858 }
2859 /* }}} */
2860
2861 #ifdef ZEND_WIN32
2862 #pragma optimize("", off)
2863 #endif
display_disabled_class(zend_class_entry * class_type)2864 static zend_object *display_disabled_class(zend_class_entry *class_type) /* {{{ */
2865 {
2866 zend_object *intern;
2867
2868 intern = zend_objects_new(class_type);
2869
2870 /* Initialize default properties */
2871 if (EXPECTED(class_type->default_properties_count != 0)) {
2872 zval *p = intern->properties_table;
2873 zval *end = p + class_type->default_properties_count;
2874 do {
2875 ZVAL_UNDEF(p);
2876 p++;
2877 } while (p != end);
2878 }
2879
2880 zend_error(E_WARNING, "%s() has been disabled for security reasons", ZSTR_VAL(class_type->name));
2881 return intern;
2882 }
2883 #ifdef ZEND_WIN32
2884 #pragma optimize("", on)
2885 #endif
2886 /* }}} */
2887
2888 static const zend_function_entry disabled_class_new[] = {
2889 ZEND_FE_END
2890 };
2891
zend_disable_class(char * class_name,size_t class_name_length)2892 ZEND_API int zend_disable_class(char *class_name, size_t class_name_length) /* {{{ */
2893 {
2894 zend_class_entry *disabled_class;
2895 zend_string *key;
2896
2897 key = zend_string_alloc(class_name_length, 0);
2898 zend_str_tolower_copy(ZSTR_VAL(key), class_name, class_name_length);
2899 disabled_class = zend_hash_find_ptr(CG(class_table), key);
2900 zend_string_release_ex(key, 0);
2901 if (!disabled_class) {
2902 return FAILURE;
2903 }
2904 INIT_CLASS_ENTRY_INIT_METHODS((*disabled_class), disabled_class_new);
2905 disabled_class->create_object = display_disabled_class;
2906 zend_hash_clean(&disabled_class->function_table);
2907 return SUCCESS;
2908 }
2909 /* }}} */
2910
zend_is_callable_check_class(zend_string * name,zend_class_entry * scope,zend_fcall_info_cache * fcc,int * strict_class,char ** error)2911 static int zend_is_callable_check_class(zend_string *name, zend_class_entry *scope, zend_fcall_info_cache *fcc, int *strict_class, char **error) /* {{{ */
2912 {
2913 int ret = 0;
2914 zend_class_entry *ce;
2915 size_t name_len = ZSTR_LEN(name);
2916 zend_string *lcname;
2917 ALLOCA_FLAG(use_heap);
2918
2919 ZSTR_ALLOCA_ALLOC(lcname, name_len, use_heap);
2920 zend_str_tolower_copy(ZSTR_VAL(lcname), ZSTR_VAL(name), name_len);
2921
2922 *strict_class = 0;
2923 if (zend_string_equals_literal(lcname, "self")) {
2924 if (!scope) {
2925 if (error) *error = estrdup("cannot access self:: when no class scope is active");
2926 } else {
2927 fcc->called_scope = zend_get_called_scope(EG(current_execute_data));
2928 fcc->calling_scope = scope;
2929 if (!fcc->object) {
2930 fcc->object = zend_get_this_object(EG(current_execute_data));
2931 }
2932 ret = 1;
2933 }
2934 } else if (zend_string_equals_literal(lcname, "parent")) {
2935 if (!scope) {
2936 if (error) *error = estrdup("cannot access parent:: when no class scope is active");
2937 } else if (!scope->parent) {
2938 if (error) *error = estrdup("cannot access parent:: when current class scope has no parent");
2939 } else {
2940 fcc->called_scope = zend_get_called_scope(EG(current_execute_data));
2941 fcc->calling_scope = scope->parent;
2942 if (!fcc->object) {
2943 fcc->object = zend_get_this_object(EG(current_execute_data));
2944 }
2945 *strict_class = 1;
2946 ret = 1;
2947 }
2948 } else if (zend_string_equals_literal(lcname, "static")) {
2949 zend_class_entry *called_scope = zend_get_called_scope(EG(current_execute_data));
2950
2951 if (!called_scope) {
2952 if (error) *error = estrdup("cannot access static:: when no class scope is active");
2953 } else {
2954 fcc->called_scope = called_scope;
2955 fcc->calling_scope = called_scope;
2956 if (!fcc->object) {
2957 fcc->object = zend_get_this_object(EG(current_execute_data));
2958 }
2959 *strict_class = 1;
2960 ret = 1;
2961 }
2962 } else if ((ce = zend_lookup_class_ex(name, NULL, 1)) != NULL) {
2963 zend_class_entry *scope;
2964 zend_execute_data *ex = EG(current_execute_data);
2965
2966 while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->type))) {
2967 ex = ex->prev_execute_data;
2968 }
2969 scope = ex ? ex->func->common.scope : NULL;
2970 fcc->calling_scope = ce;
2971 if (scope && !fcc->object) {
2972 zend_object *object = zend_get_this_object(EG(current_execute_data));
2973
2974 if (object &&
2975 instanceof_function(object->ce, scope) &&
2976 instanceof_function(scope, ce)) {
2977 fcc->object = object;
2978 fcc->called_scope = object->ce;
2979 } else {
2980 fcc->called_scope = ce;
2981 }
2982 } else {
2983 fcc->called_scope = fcc->object ? fcc->object->ce : ce;
2984 }
2985 *strict_class = 1;
2986 ret = 1;
2987 } else {
2988 if (error) zend_spprintf(error, 0, "class '%.*s' not found", (int)name_len, ZSTR_VAL(name));
2989 }
2990 ZSTR_ALLOCA_FREE(lcname, use_heap);
2991 return ret;
2992 }
2993 /* }}} */
2994
zend_is_callable_check_func(int check_flags,zval * callable,zend_fcall_info_cache * fcc,int strict_class,char ** error)2995 static zend_always_inline int zend_is_callable_check_func(int check_flags, zval *callable, zend_fcall_info_cache *fcc, int strict_class, char **error) /* {{{ */
2996 {
2997 zend_class_entry *ce_org = fcc->calling_scope;
2998 int retval = 0;
2999 zend_string *mname, *cname;
3000 zend_string *lmname;
3001 const char *colon;
3002 size_t clen;
3003 HashTable *ftable;
3004 int call_via_handler = 0;
3005 zend_class_entry *scope;
3006 zval *zv;
3007 ALLOCA_FLAG(use_heap)
3008
3009 fcc->calling_scope = NULL;
3010
3011 if (!ce_org) {
3012 zend_function *func;
3013 zend_string *lmname;
3014
3015 /* Check if function with given name exists.
3016 * This may be a compound name that includes namespace name */
3017 if (UNEXPECTED(Z_STRVAL_P(callable)[0] == '\\')) {
3018 /* Skip leading \ */
3019 ZSTR_ALLOCA_ALLOC(lmname, Z_STRLEN_P(callable) - 1, use_heap);
3020 zend_str_tolower_copy(ZSTR_VAL(lmname), Z_STRVAL_P(callable) + 1, Z_STRLEN_P(callable) - 1);
3021 func = zend_fetch_function(lmname);
3022 ZSTR_ALLOCA_FREE(lmname, use_heap);
3023 } else {
3024 lmname = Z_STR_P(callable);
3025 func = zend_fetch_function(lmname);
3026 if (!func) {
3027 ZSTR_ALLOCA_ALLOC(lmname, Z_STRLEN_P(callable), use_heap);
3028 zend_str_tolower_copy(ZSTR_VAL(lmname), Z_STRVAL_P(callable), Z_STRLEN_P(callable));
3029 func = zend_fetch_function(lmname);
3030 ZSTR_ALLOCA_FREE(lmname, use_heap);
3031 }
3032 }
3033 if (EXPECTED(func != NULL)) {
3034 fcc->function_handler = func;
3035 return 1;
3036 }
3037 }
3038
3039 /* Split name into class/namespace and method/function names */
3040 if ((colon = zend_memrchr(Z_STRVAL_P(callable), ':', Z_STRLEN_P(callable))) != NULL &&
3041 colon > Z_STRVAL_P(callable) &&
3042 *(colon-1) == ':'
3043 ) {
3044 size_t mlen;
3045
3046 colon--;
3047 clen = colon - Z_STRVAL_P(callable);
3048 mlen = Z_STRLEN_P(callable) - clen - 2;
3049
3050 if (colon == Z_STRVAL_P(callable)) {
3051 if (error) *error = estrdup("invalid function name");
3052 return 0;
3053 }
3054
3055 /* This is a compound name.
3056 * Try to fetch class and then find static method. */
3057 if (ce_org) {
3058 scope = ce_org;
3059 } else {
3060 scope = zend_get_executed_scope();
3061 }
3062
3063 cname = zend_string_init(Z_STRVAL_P(callable), clen, 0);
3064 if (!zend_is_callable_check_class(cname, scope, fcc, &strict_class, error)) {
3065 zend_string_release_ex(cname, 0);
3066 return 0;
3067 }
3068 zend_string_release_ex(cname, 0);
3069
3070 ftable = &fcc->calling_scope->function_table;
3071 if (ce_org && !instanceof_function(ce_org, fcc->calling_scope)) {
3072 if (error) zend_spprintf(error, 0, "class '%s' is not a subclass of '%s'", ZSTR_VAL(ce_org->name), ZSTR_VAL(fcc->calling_scope->name));
3073 return 0;
3074 }
3075 mname = zend_string_init(Z_STRVAL_P(callable) + clen + 2, mlen, 0);
3076 } else if (ce_org) {
3077 /* Try to fetch find static method of given class. */
3078 mname = Z_STR_P(callable);
3079 zend_string_addref(mname);
3080 ftable = &ce_org->function_table;
3081 fcc->calling_scope = ce_org;
3082 } else {
3083 /* We already checked for plain function before. */
3084 if (error && !(check_flags & IS_CALLABLE_CHECK_SILENT)) {
3085 zend_spprintf(error, 0, "function '%s' not found or invalid function name", Z_STRVAL_P(callable));
3086 }
3087 return 0;
3088 }
3089
3090 lmname = zend_string_tolower(mname);
3091 if (strict_class &&
3092 fcc->calling_scope &&
3093 zend_string_equals_literal(lmname, ZEND_CONSTRUCTOR_FUNC_NAME)) {
3094 fcc->function_handler = fcc->calling_scope->constructor;
3095 if (fcc->function_handler) {
3096 retval = 1;
3097 }
3098 } else if ((zv = zend_hash_find(ftable, lmname)) != NULL) {
3099 fcc->function_handler = Z_PTR_P(zv);
3100 retval = 1;
3101 if ((fcc->function_handler->op_array.fn_flags & ZEND_ACC_CHANGED) &&
3102 !strict_class) {
3103 scope = zend_get_executed_scope();
3104 if (scope &&
3105 instanceof_function(fcc->function_handler->common.scope, scope)) {
3106
3107 zv = zend_hash_find(&scope->function_table, lmname);
3108 if (zv != NULL) {
3109 zend_function *priv_fbc = Z_PTR_P(zv);
3110
3111 if (priv_fbc->common.fn_flags & ZEND_ACC_PRIVATE
3112 && priv_fbc->common.scope == scope) {
3113 fcc->function_handler = priv_fbc;
3114 }
3115 }
3116 }
3117 }
3118 if ((check_flags & IS_CALLABLE_CHECK_NO_ACCESS) == 0 &&
3119 (fcc->calling_scope &&
3120 ((fcc->object && fcc->calling_scope->__call) ||
3121 (!fcc->object && fcc->calling_scope->__callstatic)))) {
3122 if (fcc->function_handler->op_array.fn_flags & ZEND_ACC_PRIVATE) {
3123 scope = zend_get_executed_scope();
3124 if (!zend_check_private(fcc->function_handler, fcc->object ? fcc->object->ce : scope, lmname)) {
3125 retval = 0;
3126 fcc->function_handler = NULL;
3127 goto get_function_via_handler;
3128 }
3129 } else if (fcc->function_handler->common.fn_flags & ZEND_ACC_PROTECTED) {
3130 scope = zend_get_executed_scope();
3131 if (!zend_check_protected(fcc->function_handler->common.scope, scope)) {
3132 retval = 0;
3133 fcc->function_handler = NULL;
3134 goto get_function_via_handler;
3135 }
3136 }
3137 }
3138 } else {
3139 get_function_via_handler:
3140 if (fcc->object && fcc->calling_scope == ce_org) {
3141 if (strict_class && ce_org->__call) {
3142 fcc->function_handler = zend_get_call_trampoline_func(ce_org, mname, 0);
3143 call_via_handler = 1;
3144 retval = 1;
3145 } else if (fcc->object->handlers->get_method) {
3146 fcc->function_handler = fcc->object->handlers->get_method(&fcc->object, mname, NULL);
3147 if (fcc->function_handler) {
3148 if (strict_class &&
3149 (!fcc->function_handler->common.scope ||
3150 !instanceof_function(ce_org, fcc->function_handler->common.scope))) {
3151 if (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) {
3152 if (fcc->function_handler->type != ZEND_OVERLOADED_FUNCTION &&
3153 fcc->function_handler->common.function_name) {
3154 zend_string_release_ex(fcc->function_handler->common.function_name, 0);
3155 }
3156 zend_free_trampoline(fcc->function_handler);
3157 }
3158 } else {
3159 retval = 1;
3160 call_via_handler = (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) != 0;
3161 }
3162 }
3163 }
3164 } else if (fcc->calling_scope) {
3165 if (fcc->calling_scope->get_static_method) {
3166 fcc->function_handler = fcc->calling_scope->get_static_method(fcc->calling_scope, mname);
3167 } else {
3168 fcc->function_handler = zend_std_get_static_method(fcc->calling_scope, mname, NULL);
3169 }
3170 if (fcc->function_handler) {
3171 retval = 1;
3172 call_via_handler = (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) != 0;
3173 if (call_via_handler && !fcc->object) {
3174 zend_object *object = zend_get_this_object(EG(current_execute_data));
3175 if (object &&
3176 instanceof_function(object->ce, fcc->calling_scope)) {
3177 fcc->object = object;
3178 }
3179 }
3180 }
3181 }
3182 }
3183
3184 if (retval) {
3185 if (fcc->calling_scope && !call_via_handler) {
3186 if (fcc->function_handler->common.fn_flags & ZEND_ACC_ABSTRACT) {
3187 if (error) {
3188 zend_spprintf(error, 0, "cannot call abstract method %s::%s()", ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(fcc->function_handler->common.function_name));
3189 retval = 0;
3190 } else {
3191 zend_throw_error(NULL, "Cannot call abstract method %s::%s()", ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(fcc->function_handler->common.function_name));
3192 retval = 0;
3193 }
3194 } else if (!fcc->object && !(fcc->function_handler->common.fn_flags & ZEND_ACC_STATIC)) {
3195 int severity;
3196 char *verb;
3197 if (fcc->function_handler->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
3198 severity = E_DEPRECATED;
3199 verb = "should not";
3200 } else {
3201 /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
3202 severity = E_ERROR;
3203 verb = "cannot";
3204 }
3205 if ((check_flags & IS_CALLABLE_CHECK_IS_STATIC) != 0) {
3206 retval = 0;
3207 }
3208 if (error) {
3209 zend_spprintf(error, 0, "non-static method %s::%s() %s be called statically", ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(fcc->function_handler->common.function_name), verb);
3210 if (severity != E_DEPRECATED) {
3211 retval = 0;
3212 }
3213 } else if (retval) {
3214 if (severity == E_ERROR) {
3215 zend_throw_error(NULL, "Non-static method %s::%s() %s be called statically", ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(fcc->function_handler->common.function_name), verb);
3216 } else {
3217 zend_error(severity, "Non-static method %s::%s() %s be called statically", ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(fcc->function_handler->common.function_name), verb);
3218 }
3219 }
3220 }
3221 if (retval && (check_flags & IS_CALLABLE_CHECK_NO_ACCESS) == 0) {
3222 if (fcc->function_handler->op_array.fn_flags & ZEND_ACC_PRIVATE) {
3223 scope = zend_get_executed_scope();
3224 if (!zend_check_private(fcc->function_handler, fcc->object ? fcc->object->ce : scope, lmname)) {
3225 if (error) {
3226 if (*error) {
3227 efree(*error);
3228 }
3229 zend_spprintf(error, 0, "cannot access private method %s::%s()", ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(fcc->function_handler->common.function_name));
3230 }
3231 retval = 0;
3232 }
3233 } else if ((fcc->function_handler->common.fn_flags & ZEND_ACC_PROTECTED)) {
3234 scope = zend_get_executed_scope();
3235 if (!zend_check_protected(fcc->function_handler->common.scope, scope)) {
3236 if (error) {
3237 if (*error) {
3238 efree(*error);
3239 }
3240 zend_spprintf(error, 0, "cannot access protected method %s::%s()", ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(fcc->function_handler->common.function_name));
3241 }
3242 retval = 0;
3243 }
3244 }
3245 }
3246 }
3247 } else if (error && !(check_flags & IS_CALLABLE_CHECK_SILENT)) {
3248 if (fcc->calling_scope) {
3249 if (error) zend_spprintf(error, 0, "class '%s' does not have a method '%s'", ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(mname));
3250 } else {
3251 if (error) zend_spprintf(error, 0, "function '%s' does not exist", ZSTR_VAL(mname));
3252 }
3253 }
3254 zend_string_release_ex(lmname, 0);
3255 zend_string_release_ex(mname, 0);
3256
3257 if (fcc->object) {
3258 fcc->called_scope = fcc->object->ce;
3259 }
3260 return retval;
3261 }
3262 /* }}} */
3263
zend_create_method_string(zend_string * class_name,zend_string * method_name)3264 static zend_string *zend_create_method_string(zend_string *class_name, zend_string *method_name) {
3265 zend_string *callable_name = zend_string_alloc(
3266 ZSTR_LEN(class_name) + ZSTR_LEN(method_name) + sizeof("::") - 1, 0);
3267 char *ptr = ZSTR_VAL(callable_name);
3268 memcpy(ptr, ZSTR_VAL(class_name), ZSTR_LEN(class_name));
3269 ptr += ZSTR_LEN(class_name);
3270 memcpy(ptr, "::", sizeof("::") - 1);
3271 ptr += sizeof("::") - 1;
3272 memcpy(ptr, ZSTR_VAL(method_name), ZSTR_LEN(method_name) + 1);
3273 return callable_name;
3274 }
3275
zend_get_callable_name_ex(zval * callable,zend_object * object)3276 ZEND_API zend_string *zend_get_callable_name_ex(zval *callable, zend_object *object) /* {{{ */
3277 {
3278 try_again:
3279 switch (Z_TYPE_P(callable)) {
3280 case IS_STRING:
3281 if (object) {
3282 return zend_create_method_string(object->ce->name, Z_STR_P(callable));
3283 }
3284 return zend_string_copy(Z_STR_P(callable));
3285
3286 case IS_ARRAY:
3287 {
3288 zval *method = NULL;
3289 zval *obj = NULL;
3290
3291 if (zend_hash_num_elements(Z_ARRVAL_P(callable)) == 2) {
3292 obj = zend_hash_index_find_deref(Z_ARRVAL_P(callable), 0);
3293 method = zend_hash_index_find_deref(Z_ARRVAL_P(callable), 1);
3294 }
3295
3296 if (obj == NULL || method == NULL || Z_TYPE_P(method) != IS_STRING) {
3297 return zend_string_init("Array", sizeof("Array")-1, 0);
3298 }
3299
3300 if (Z_TYPE_P(obj) == IS_STRING) {
3301 return zend_create_method_string(Z_STR_P(obj), Z_STR_P(method));
3302 } else if (Z_TYPE_P(obj) == IS_OBJECT) {
3303 return zend_create_method_string(Z_OBJCE_P(obj)->name, Z_STR_P(method));
3304 } else {
3305 return zend_string_init("Array", sizeof("Array")-1, 0);
3306 }
3307 }
3308 case IS_OBJECT:
3309 {
3310 zend_class_entry *calling_scope;
3311 zend_function *fptr;
3312 zend_object *object;
3313 if (Z_OBJ_HANDLER_P(callable, get_closure)
3314 && Z_OBJ_HANDLER_P(callable, get_closure)(callable, &calling_scope, &fptr, &object) == SUCCESS) {
3315 zend_class_entry *ce = Z_OBJCE_P(callable);
3316 zend_string *callable_name = zend_string_alloc(
3317 ZSTR_LEN(ce->name) + sizeof("::__invoke") - 1, 0);
3318 memcpy(ZSTR_VAL(callable_name), ZSTR_VAL(ce->name), ZSTR_LEN(ce->name));
3319 memcpy(ZSTR_VAL(callable_name) + ZSTR_LEN(ce->name), "::__invoke", sizeof("::__invoke"));
3320 return callable_name;
3321 }
3322 return zval_get_string(callable);
3323 }
3324 case IS_REFERENCE:
3325 callable = Z_REFVAL_P(callable);
3326 goto try_again;
3327 default:
3328 return zval_get_string_func(callable);
3329 }
3330 }
3331 /* }}} */
3332
zend_get_callable_name(zval * callable)3333 ZEND_API zend_string *zend_get_callable_name(zval *callable) /* {{{ */
3334 {
3335 return zend_get_callable_name_ex(callable, NULL);
3336 }
3337 /* }}} */
3338
zend_is_callable_impl(zval * callable,zend_object * object,uint32_t check_flags,zend_fcall_info_cache * fcc,char ** error)3339 static zend_always_inline zend_bool zend_is_callable_impl(zval *callable, zend_object *object, uint32_t check_flags, zend_fcall_info_cache *fcc, char **error) /* {{{ */
3340 {
3341 zend_bool ret;
3342 zend_fcall_info_cache fcc_local;
3343 int strict_class = 0;
3344
3345 if (fcc == NULL) {
3346 fcc = &fcc_local;
3347 }
3348 if (error) {
3349 *error = NULL;
3350 }
3351
3352 fcc->calling_scope = NULL;
3353 fcc->called_scope = NULL;
3354 fcc->function_handler = NULL;
3355 fcc->object = NULL;
3356
3357 again:
3358 switch (Z_TYPE_P(callable)) {
3359 case IS_STRING:
3360 if (object) {
3361 fcc->object = object;
3362 fcc->calling_scope = object->ce;
3363 }
3364
3365 if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) {
3366 fcc->called_scope = fcc->calling_scope;
3367 return 1;
3368 }
3369
3370 check_func:
3371 ret = zend_is_callable_check_func(check_flags, callable, fcc, strict_class, error);
3372 if (fcc == &fcc_local &&
3373 fcc->function_handler &&
3374 ((fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) ||
3375 fcc->function_handler->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY ||
3376 fcc->function_handler->type == ZEND_OVERLOADED_FUNCTION)) {
3377 if (fcc->function_handler->type != ZEND_OVERLOADED_FUNCTION &&
3378 fcc->function_handler->common.function_name) {
3379 zend_string_release_ex(fcc->function_handler->common.function_name, 0);
3380 }
3381 zend_free_trampoline(fcc->function_handler);
3382 }
3383 return ret;
3384
3385 case IS_ARRAY:
3386 {
3387 zval *method = NULL;
3388 zval *obj = NULL;
3389
3390 if (zend_hash_num_elements(Z_ARRVAL_P(callable)) == 2) {
3391 obj = zend_hash_index_find(Z_ARRVAL_P(callable), 0);
3392 method = zend_hash_index_find(Z_ARRVAL_P(callable), 1);
3393 }
3394
3395 do {
3396 if (obj == NULL || method == NULL) {
3397 break;
3398 }
3399
3400 ZVAL_DEREF(method);
3401 if (Z_TYPE_P(method) != IS_STRING) {
3402 break;
3403 }
3404
3405 ZVAL_DEREF(obj);
3406 if (Z_TYPE_P(obj) == IS_STRING) {
3407 if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) {
3408 return 1;
3409 }
3410
3411 if (!zend_is_callable_check_class(Z_STR_P(obj), zend_get_executed_scope(), fcc, &strict_class, error)) {
3412 return 0;
3413 }
3414
3415 } else if (Z_TYPE_P(obj) == IS_OBJECT) {
3416
3417 fcc->calling_scope = Z_OBJCE_P(obj); /* TBFixed: what if it's overloaded? */
3418
3419 fcc->object = Z_OBJ_P(obj);
3420
3421 if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) {
3422 fcc->called_scope = fcc->calling_scope;
3423 return 1;
3424 }
3425 } else {
3426 break;
3427 }
3428
3429 callable = method;
3430 goto check_func;
3431
3432 } while (0);
3433 if (zend_hash_num_elements(Z_ARRVAL_P(callable)) == 2) {
3434 if (!obj || (!Z_ISREF_P(obj)?
3435 (Z_TYPE_P(obj) != IS_STRING && Z_TYPE_P(obj) != IS_OBJECT) :
3436 (Z_TYPE_P(Z_REFVAL_P(obj)) != IS_STRING && Z_TYPE_P(Z_REFVAL_P(obj)) != IS_OBJECT))) {
3437 if (error) *error = estrdup("first array member is not a valid class name or object");
3438 } else {
3439 if (error) *error = estrdup("second array member is not a valid method");
3440 }
3441 } else {
3442 if (error) *error = estrdup("array must have exactly two members");
3443 }
3444 }
3445 return 0;
3446 case IS_OBJECT:
3447 if (Z_OBJ_HANDLER_P(callable, get_closure) && Z_OBJ_HANDLER_P(callable, get_closure)(callable, &fcc->calling_scope, &fcc->function_handler, &fcc->object) == SUCCESS) {
3448 fcc->called_scope = fcc->calling_scope;
3449 return 1;
3450 }
3451 if (error) *error = estrdup("no array or string given");
3452 return 0;
3453 case IS_REFERENCE:
3454 callable = Z_REFVAL_P(callable);
3455 goto again;
3456 default:
3457 if (error) *error = estrdup("no array or string given");
3458 return 0;
3459 }
3460 }
3461 /* }}} */
3462
zend_is_callable_ex(zval * callable,zend_object * object,uint32_t check_flags,zend_string ** callable_name,zend_fcall_info_cache * fcc,char ** error)3463 ZEND_API zend_bool zend_is_callable_ex(zval *callable, zend_object *object, uint32_t check_flags, zend_string **callable_name, zend_fcall_info_cache *fcc, char **error) /* {{{ */
3464 {
3465 zend_bool ret = zend_is_callable_impl(callable, object, check_flags, fcc, error);
3466 if (callable_name) {
3467 *callable_name = zend_get_callable_name_ex(callable, object);
3468 }
3469 return ret;
3470 }
3471
zend_is_callable(zval * callable,uint32_t check_flags,zend_string ** callable_name)3472 ZEND_API zend_bool zend_is_callable(zval *callable, uint32_t check_flags, zend_string **callable_name) /* {{{ */
3473 {
3474 return zend_is_callable_ex(callable, NULL, check_flags, callable_name, NULL, NULL);
3475 }
3476 /* }}} */
3477
zend_make_callable(zval * callable,zend_string ** callable_name)3478 ZEND_API zend_bool zend_make_callable(zval *callable, zend_string **callable_name) /* {{{ */
3479 {
3480 zend_fcall_info_cache fcc;
3481
3482 if (zend_is_callable_ex(callable, NULL, IS_CALLABLE_STRICT, callable_name, &fcc, NULL)) {
3483 if (Z_TYPE_P(callable) == IS_STRING && fcc.calling_scope) {
3484 zval_ptr_dtor_str(callable);
3485 array_init(callable);
3486 add_next_index_str(callable, zend_string_copy(fcc.calling_scope->name));
3487 add_next_index_str(callable, zend_string_copy(fcc.function_handler->common.function_name));
3488 }
3489 if (fcc.function_handler &&
3490 ((fcc.function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) ||
3491 fcc.function_handler->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY ||
3492 fcc.function_handler->type == ZEND_OVERLOADED_FUNCTION)) {
3493 if (fcc.function_handler->type != ZEND_OVERLOADED_FUNCTION) {
3494 zend_string_release_ex(fcc.function_handler->common.function_name, 0);
3495 }
3496 zend_free_trampoline(fcc.function_handler);
3497 }
3498 return 1;
3499 }
3500 return 0;
3501 }
3502 /* }}} */
3503
zend_fcall_info_init(zval * callable,uint32_t check_flags,zend_fcall_info * fci,zend_fcall_info_cache * fcc,zend_string ** callable_name,char ** error)3504 ZEND_API int zend_fcall_info_init(zval *callable, uint32_t check_flags, zend_fcall_info *fci, zend_fcall_info_cache *fcc, zend_string **callable_name, char **error) /* {{{ */
3505 {
3506 if (!zend_is_callable_ex(callable, NULL, check_flags, callable_name, fcc, error)) {
3507 return FAILURE;
3508 }
3509
3510 fci->size = sizeof(*fci);
3511 fci->object = fcc->object;
3512 ZVAL_COPY_VALUE(&fci->function_name, callable);
3513 fci->retval = NULL;
3514 fci->param_count = 0;
3515 fci->params = NULL;
3516 fci->no_separation = 1;
3517
3518 return SUCCESS;
3519 }
3520 /* }}} */
3521
zend_fcall_info_args_clear(zend_fcall_info * fci,int free_mem)3522 ZEND_API void zend_fcall_info_args_clear(zend_fcall_info *fci, int free_mem) /* {{{ */
3523 {
3524 if (fci->params) {
3525 zval *p = fci->params;
3526 zval *end = p + fci->param_count;
3527
3528 while (p != end) {
3529 i_zval_ptr_dtor(p ZEND_FILE_LINE_CC);
3530 p++;
3531 }
3532 if (free_mem) {
3533 efree(fci->params);
3534 fci->params = NULL;
3535 }
3536 }
3537 fci->param_count = 0;
3538 }
3539 /* }}} */
3540
zend_fcall_info_args_save(zend_fcall_info * fci,int * param_count,zval ** params)3541 ZEND_API void zend_fcall_info_args_save(zend_fcall_info *fci, int *param_count, zval **params) /* {{{ */
3542 {
3543 *param_count = fci->param_count;
3544 *params = fci->params;
3545 fci->param_count = 0;
3546 fci->params = NULL;
3547 }
3548 /* }}} */
3549
zend_fcall_info_args_restore(zend_fcall_info * fci,int param_count,zval * params)3550 ZEND_API void zend_fcall_info_args_restore(zend_fcall_info *fci, int param_count, zval *params) /* {{{ */
3551 {
3552 zend_fcall_info_args_clear(fci, 1);
3553 fci->param_count = param_count;
3554 fci->params = params;
3555 }
3556 /* }}} */
3557
zend_fcall_info_args_ex(zend_fcall_info * fci,zend_function * func,zval * args)3558 ZEND_API int zend_fcall_info_args_ex(zend_fcall_info *fci, zend_function *func, zval *args) /* {{{ */
3559 {
3560 zval *arg, *params;
3561 uint32_t n = 1;
3562
3563 zend_fcall_info_args_clear(fci, !args);
3564
3565 if (!args) {
3566 return SUCCESS;
3567 }
3568
3569 if (Z_TYPE_P(args) != IS_ARRAY) {
3570 return FAILURE;
3571 }
3572
3573 fci->param_count = zend_hash_num_elements(Z_ARRVAL_P(args));
3574 fci->params = params = (zval *) erealloc(fci->params, fci->param_count * sizeof(zval));
3575
3576 ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(args), arg) {
3577 if (func && !Z_ISREF_P(arg) && ARG_SHOULD_BE_SENT_BY_REF(func, n)) {
3578 ZVAL_NEW_REF(params, arg);
3579 Z_TRY_ADDREF_P(arg);
3580 } else {
3581 ZVAL_COPY(params, arg);
3582 }
3583 params++;
3584 n++;
3585 } ZEND_HASH_FOREACH_END();
3586
3587 return SUCCESS;
3588 }
3589 /* }}} */
3590
zend_fcall_info_args(zend_fcall_info * fci,zval * args)3591 ZEND_API int zend_fcall_info_args(zend_fcall_info *fci, zval *args) /* {{{ */
3592 {
3593 return zend_fcall_info_args_ex(fci, NULL, args);
3594 }
3595 /* }}} */
3596
zend_fcall_info_argp(zend_fcall_info * fci,int argc,zval * argv)3597 ZEND_API int zend_fcall_info_argp(zend_fcall_info *fci, int argc, zval *argv) /* {{{ */
3598 {
3599 int i;
3600
3601 if (argc < 0) {
3602 return FAILURE;
3603 }
3604
3605 zend_fcall_info_args_clear(fci, !argc);
3606
3607 if (argc) {
3608 fci->param_count = argc;
3609 fci->params = (zval *) erealloc(fci->params, fci->param_count * sizeof(zval));
3610
3611 for (i = 0; i < argc; ++i) {
3612 ZVAL_COPY(&fci->params[i], &argv[i]);
3613 }
3614 }
3615
3616 return SUCCESS;
3617 }
3618 /* }}} */
3619
zend_fcall_info_argv(zend_fcall_info * fci,int argc,va_list * argv)3620 ZEND_API int zend_fcall_info_argv(zend_fcall_info *fci, int argc, va_list *argv) /* {{{ */
3621 {
3622 int i;
3623 zval *arg;
3624
3625 if (argc < 0) {
3626 return FAILURE;
3627 }
3628
3629 zend_fcall_info_args_clear(fci, !argc);
3630
3631 if (argc) {
3632 fci->param_count = argc;
3633 fci->params = (zval *) erealloc(fci->params, fci->param_count * sizeof(zval));
3634
3635 for (i = 0; i < argc; ++i) {
3636 arg = va_arg(*argv, zval *);
3637 ZVAL_COPY(&fci->params[i], arg);
3638 }
3639 }
3640
3641 return SUCCESS;
3642 }
3643 /* }}} */
3644
zend_fcall_info_argn(zend_fcall_info * fci,int argc,...)3645 ZEND_API int zend_fcall_info_argn(zend_fcall_info *fci, int argc, ...) /* {{{ */
3646 {
3647 int ret;
3648 va_list argv;
3649
3650 va_start(argv, argc);
3651 ret = zend_fcall_info_argv(fci, argc, &argv);
3652 va_end(argv);
3653
3654 return ret;
3655 }
3656 /* }}} */
3657
zend_fcall_info_call(zend_fcall_info * fci,zend_fcall_info_cache * fcc,zval * retval_ptr,zval * args)3658 ZEND_API int zend_fcall_info_call(zend_fcall_info *fci, zend_fcall_info_cache *fcc, zval *retval_ptr, zval *args) /* {{{ */
3659 {
3660 zval retval, *org_params = NULL;
3661 int result, org_count = 0;
3662
3663 fci->retval = retval_ptr ? retval_ptr : &retval;
3664 if (args) {
3665 zend_fcall_info_args_save(fci, &org_count, &org_params);
3666 zend_fcall_info_args(fci, args);
3667 }
3668 result = zend_call_function(fci, fcc);
3669
3670 if (!retval_ptr && Z_TYPE(retval) != IS_UNDEF) {
3671 zval_ptr_dtor(&retval);
3672 }
3673 if (args) {
3674 zend_fcall_info_args_restore(fci, org_count, org_params);
3675 }
3676 return result;
3677 }
3678 /* }}} */
3679
zend_get_module_version(const char * module_name)3680 ZEND_API const char *zend_get_module_version(const char *module_name) /* {{{ */
3681 {
3682 zend_string *lname;
3683 size_t name_len = strlen(module_name);
3684 zend_module_entry *module;
3685
3686 lname = zend_string_alloc(name_len, 0);
3687 zend_str_tolower_copy(ZSTR_VAL(lname), module_name, name_len);
3688 module = zend_hash_find_ptr(&module_registry, lname);
3689 zend_string_efree(lname);
3690 return module ? module->version : NULL;
3691 }
3692 /* }}} */
3693
zval_make_interned_string(zval * zv)3694 static inline zend_string *zval_make_interned_string(zval *zv) /* {{{ */
3695 {
3696 ZEND_ASSERT(Z_TYPE_P(zv) == IS_STRING);
3697 Z_STR_P(zv) = zend_new_interned_string(Z_STR_P(zv));
3698 if (ZSTR_IS_INTERNED(Z_STR_P(zv))) {
3699 Z_TYPE_FLAGS_P(zv) = 0;
3700 }
3701 return Z_STR_P(zv);
3702 }
3703
is_persistent_class(zend_class_entry * ce)3704 static zend_always_inline zend_bool is_persistent_class(zend_class_entry *ce) {
3705 return (ce->type & ZEND_INTERNAL_CLASS)
3706 && ce->info.internal.module->type == MODULE_PERSISTENT;
3707 }
3708
zend_declare_property_ex(zend_class_entry * ce,zend_string * name,zval * property,int access_type,zend_string * doc_comment)3709 ZEND_API int zend_declare_property_ex(zend_class_entry *ce, zend_string *name, zval *property, int access_type, zend_string *doc_comment) /* {{{ */
3710 {
3711 zend_property_info *property_info, *property_info_ptr;
3712
3713 if (ce->type == ZEND_INTERNAL_CLASS) {
3714 property_info = pemalloc(sizeof(zend_property_info), 1);
3715 } else {
3716 property_info = zend_arena_alloc(&CG(arena), sizeof(zend_property_info));
3717 if (Z_TYPE_P(property) == IS_CONSTANT_AST) {
3718 ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
3719 }
3720 }
3721
3722 if (Z_TYPE_P(property) == IS_STRING && !ZSTR_IS_INTERNED(Z_STR_P(property))) {
3723 zval_make_interned_string(property);
3724 }
3725
3726 if (!(access_type & ZEND_ACC_PPP_MASK)) {
3727 access_type |= ZEND_ACC_PUBLIC;
3728 }
3729 if (access_type & ZEND_ACC_STATIC) {
3730 if ((property_info_ptr = zend_hash_find_ptr(&ce->properties_info, name)) != NULL &&
3731 (property_info_ptr->flags & ZEND_ACC_STATIC) != 0) {
3732 property_info->offset = property_info_ptr->offset;
3733 zval_ptr_dtor(&ce->default_static_members_table[property_info->offset]);
3734 zend_hash_del(&ce->properties_info, name);
3735 } else {
3736 property_info->offset = ce->default_static_members_count++;
3737 ce->default_static_members_table = perealloc(ce->default_static_members_table, sizeof(zval) * ce->default_static_members_count, ce->type == ZEND_INTERNAL_CLASS);
3738 }
3739 ZVAL_COPY_VALUE(&ce->default_static_members_table[property_info->offset], property);
3740 if (ce->type == ZEND_USER_CLASS) {
3741 ce->static_members_table = ce->default_static_members_table;
3742 }
3743 } else {
3744 if ((property_info_ptr = zend_hash_find_ptr(&ce->properties_info, name)) != NULL &&
3745 (property_info_ptr->flags & ZEND_ACC_STATIC) == 0) {
3746 property_info->offset = property_info_ptr->offset;
3747 zval_ptr_dtor(&ce->default_properties_table[OBJ_PROP_TO_NUM(property_info->offset)]);
3748 zend_hash_del(&ce->properties_info, name);
3749 } else {
3750 property_info->offset = OBJ_PROP_TO_OFFSET(ce->default_properties_count);
3751 ce->default_properties_count++;
3752 ce->default_properties_table = perealloc(ce->default_properties_table, sizeof(zval) * ce->default_properties_count, ce->type == ZEND_INTERNAL_CLASS);
3753 }
3754 ZVAL_COPY_VALUE(&ce->default_properties_table[OBJ_PROP_TO_NUM(property_info->offset)], property);
3755 }
3756 if (ce->type & ZEND_INTERNAL_CLASS) {
3757 switch(Z_TYPE_P(property)) {
3758 case IS_ARRAY:
3759 case IS_OBJECT:
3760 case IS_RESOURCE:
3761 zend_error_noreturn(E_CORE_ERROR, "Internal zval's can't be arrays, objects or resources");
3762 break;
3763 default:
3764 break;
3765 }
3766
3767 /* Must be interned to avoid ZTS data races */
3768 name = zend_new_interned_string(zend_string_copy(name));
3769 }
3770
3771 if (access_type & ZEND_ACC_PUBLIC) {
3772 property_info->name = zend_string_copy(name);
3773 } else if (access_type & ZEND_ACC_PRIVATE) {
3774 property_info->name = zend_mangle_property_name(ZSTR_VAL(ce->name), ZSTR_LEN(ce->name), ZSTR_VAL(name), ZSTR_LEN(name), is_persistent_class(ce));
3775 } else {
3776 ZEND_ASSERT(access_type & ZEND_ACC_PROTECTED);
3777 property_info->name = zend_mangle_property_name("*", 1, ZSTR_VAL(name), ZSTR_LEN(name), is_persistent_class(ce));
3778 }
3779
3780 property_info->name = zend_new_interned_string(property_info->name);
3781 property_info->flags = access_type;
3782 property_info->doc_comment = doc_comment;
3783 property_info->ce = ce;
3784 zend_hash_update_ptr(&ce->properties_info, name, property_info);
3785
3786 return SUCCESS;
3787 }
3788 /* }}} */
3789
zend_declare_property(zend_class_entry * ce,const char * name,size_t name_length,zval * property,int access_type)3790 ZEND_API int zend_declare_property(zend_class_entry *ce, const char *name, size_t name_length, zval *property, int access_type) /* {{{ */
3791 {
3792 zend_string *key = zend_string_init(name, name_length, is_persistent_class(ce));
3793 int ret = zend_declare_property_ex(ce, key, property, access_type, NULL);
3794 zend_string_release(key);
3795 return ret;
3796 }
3797 /* }}} */
3798
zend_declare_property_null(zend_class_entry * ce,const char * name,size_t name_length,int access_type)3799 ZEND_API int zend_declare_property_null(zend_class_entry *ce, const char *name, size_t name_length, int access_type) /* {{{ */
3800 {
3801 zval property;
3802
3803 ZVAL_NULL(&property);
3804 return zend_declare_property(ce, name, name_length, &property, access_type);
3805 }
3806 /* }}} */
3807
zend_declare_property_bool(zend_class_entry * ce,const char * name,size_t name_length,zend_long value,int access_type)3808 ZEND_API int zend_declare_property_bool(zend_class_entry *ce, const char *name, size_t name_length, zend_long value, int access_type) /* {{{ */
3809 {
3810 zval property;
3811
3812 ZVAL_BOOL(&property, value);
3813 return zend_declare_property(ce, name, name_length, &property, access_type);
3814 }
3815 /* }}} */
3816
zend_declare_property_long(zend_class_entry * ce,const char * name,size_t name_length,zend_long value,int access_type)3817 ZEND_API int zend_declare_property_long(zend_class_entry *ce, const char *name, size_t name_length, zend_long value, int access_type) /* {{{ */
3818 {
3819 zval property;
3820
3821 ZVAL_LONG(&property, value);
3822 return zend_declare_property(ce, name, name_length, &property, access_type);
3823 }
3824 /* }}} */
3825
zend_declare_property_double(zend_class_entry * ce,const char * name,size_t name_length,double value,int access_type)3826 ZEND_API int zend_declare_property_double(zend_class_entry *ce, const char *name, size_t name_length, double value, int access_type) /* {{{ */
3827 {
3828 zval property;
3829
3830 ZVAL_DOUBLE(&property, value);
3831 return zend_declare_property(ce, name, name_length, &property, access_type);
3832 }
3833 /* }}} */
3834
zend_declare_property_string(zend_class_entry * ce,const char * name,size_t name_length,const char * value,int access_type)3835 ZEND_API int zend_declare_property_string(zend_class_entry *ce, const char *name, size_t name_length, const char *value, int access_type) /* {{{ */
3836 {
3837 zval property;
3838
3839 ZVAL_NEW_STR(&property, zend_string_init(value, strlen(value), ce->type & ZEND_INTERNAL_CLASS));
3840 return zend_declare_property(ce, name, name_length, &property, access_type);
3841 }
3842 /* }}} */
3843
zend_declare_property_stringl(zend_class_entry * ce,const char * name,size_t name_length,const char * value,size_t value_len,int access_type)3844 ZEND_API int zend_declare_property_stringl(zend_class_entry *ce, const char *name, size_t name_length, const char *value, size_t value_len, int access_type) /* {{{ */
3845 {
3846 zval property;
3847
3848 ZVAL_NEW_STR(&property, zend_string_init(value, value_len, ce->type & ZEND_INTERNAL_CLASS));
3849 return zend_declare_property(ce, name, name_length, &property, access_type);
3850 }
3851 /* }}} */
3852
zend_declare_class_constant_ex(zend_class_entry * ce,zend_string * name,zval * value,int access_type,zend_string * doc_comment)3853 ZEND_API int zend_declare_class_constant_ex(zend_class_entry *ce, zend_string *name, zval *value, int access_type, zend_string *doc_comment) /* {{{ */
3854 {
3855 zend_class_constant *c;
3856
3857 if (ce->ce_flags & ZEND_ACC_INTERFACE) {
3858 if (access_type != ZEND_ACC_PUBLIC) {
3859 zend_error_noreturn(E_COMPILE_ERROR, "Access type for interface constant %s::%s must be public", ZSTR_VAL(ce->name), ZSTR_VAL(name));
3860 }
3861 }
3862
3863 if (zend_string_equals_literal_ci(name, "class")) {
3864 zend_error_noreturn(ce->type == ZEND_INTERNAL_CLASS ? E_CORE_ERROR : E_COMPILE_ERROR,
3865 "A class constant must not be called 'class'; it is reserved for class name fetching");
3866 }
3867
3868 if (Z_TYPE_P(value) == IS_STRING && !ZSTR_IS_INTERNED(Z_STR_P(value))) {
3869 zval_make_interned_string(value);
3870 }
3871
3872 if (ce->type == ZEND_INTERNAL_CLASS) {
3873 c = pemalloc(sizeof(zend_class_constant), 1);
3874 } else {
3875 c = zend_arena_alloc(&CG(arena), sizeof(zend_class_constant));
3876 }
3877 ZVAL_COPY_VALUE(&c->value, value);
3878 Z_ACCESS_FLAGS(c->value) = access_type;
3879 c->doc_comment = doc_comment;
3880 c->ce = ce;
3881 if (Z_TYPE_P(value) == IS_CONSTANT_AST) {
3882 ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
3883 }
3884
3885 if (!zend_hash_add_ptr(&ce->constants_table, name, c)) {
3886 zend_error_noreturn(ce->type == ZEND_INTERNAL_CLASS ? E_CORE_ERROR : E_COMPILE_ERROR,
3887 "Cannot redefine class constant %s::%s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
3888 }
3889
3890 return SUCCESS;
3891 }
3892 /* }}} */
3893
zend_declare_class_constant(zend_class_entry * ce,const char * name,size_t name_length,zval * value)3894 ZEND_API int zend_declare_class_constant(zend_class_entry *ce, const char *name, size_t name_length, zval *value) /* {{{ */
3895 {
3896 int ret;
3897
3898 zend_string *key;
3899
3900 if (ce->type == ZEND_INTERNAL_CLASS) {
3901 key = zend_string_init_interned(name, name_length, 1);
3902 } else {
3903 key = zend_string_init(name, name_length, 0);
3904 }
3905 ret = zend_declare_class_constant_ex(ce, key, value, ZEND_ACC_PUBLIC, NULL);
3906 zend_string_release(key);
3907 return ret;
3908 }
3909 /* }}} */
3910
zend_declare_class_constant_null(zend_class_entry * ce,const char * name,size_t name_length)3911 ZEND_API int zend_declare_class_constant_null(zend_class_entry *ce, const char *name, size_t name_length) /* {{{ */
3912 {
3913 zval constant;
3914
3915 ZVAL_NULL(&constant);
3916 return zend_declare_class_constant(ce, name, name_length, &constant);
3917 }
3918 /* }}} */
3919
zend_declare_class_constant_long(zend_class_entry * ce,const char * name,size_t name_length,zend_long value)3920 ZEND_API int zend_declare_class_constant_long(zend_class_entry *ce, const char *name, size_t name_length, zend_long value) /* {{{ */
3921 {
3922 zval constant;
3923
3924 ZVAL_LONG(&constant, value);
3925 return zend_declare_class_constant(ce, name, name_length, &constant);
3926 }
3927 /* }}} */
3928
zend_declare_class_constant_bool(zend_class_entry * ce,const char * name,size_t name_length,zend_bool value)3929 ZEND_API int zend_declare_class_constant_bool(zend_class_entry *ce, const char *name, size_t name_length, zend_bool value) /* {{{ */
3930 {
3931 zval constant;
3932
3933 ZVAL_BOOL(&constant, value);
3934 return zend_declare_class_constant(ce, name, name_length, &constant);
3935 }
3936 /* }}} */
3937
zend_declare_class_constant_double(zend_class_entry * ce,const char * name,size_t name_length,double value)3938 ZEND_API int zend_declare_class_constant_double(zend_class_entry *ce, const char *name, size_t name_length, double value) /* {{{ */
3939 {
3940 zval constant;
3941
3942 ZVAL_DOUBLE(&constant, value);
3943 return zend_declare_class_constant(ce, name, name_length, &constant);
3944 }
3945 /* }}} */
3946
zend_declare_class_constant_stringl(zend_class_entry * ce,const char * name,size_t name_length,const char * value,size_t value_length)3947 ZEND_API int zend_declare_class_constant_stringl(zend_class_entry *ce, const char *name, size_t name_length, const char *value, size_t value_length) /* {{{ */
3948 {
3949 zval constant;
3950
3951 ZVAL_NEW_STR(&constant, zend_string_init(value, value_length, ce->type & ZEND_INTERNAL_CLASS));
3952 return zend_declare_class_constant(ce, name, name_length, &constant);
3953 }
3954 /* }}} */
3955
zend_declare_class_constant_string(zend_class_entry * ce,const char * name,size_t name_length,const char * value)3956 ZEND_API int zend_declare_class_constant_string(zend_class_entry *ce, const char *name, size_t name_length, const char *value) /* {{{ */
3957 {
3958 return zend_declare_class_constant_stringl(ce, name, name_length, value, strlen(value));
3959 }
3960 /* }}} */
3961
zend_update_property_ex(zend_class_entry * scope,zval * object,zend_string * name,zval * value)3962 ZEND_API void zend_update_property_ex(zend_class_entry *scope, zval *object, zend_string *name, zval *value) /* {{{ */
3963 {
3964 zval property;
3965 zend_class_entry *old_scope = EG(fake_scope);
3966
3967 EG(fake_scope) = scope;
3968
3969 if (!Z_OBJ_HT_P(object)->write_property) {
3970 zend_error_noreturn(E_CORE_ERROR, "Property %s of class %s cannot be updated", ZSTR_VAL(name), ZSTR_VAL(Z_OBJCE_P(object)->name));
3971 }
3972 ZVAL_STR(&property, name);
3973 Z_OBJ_HT_P(object)->write_property(object, &property, value, NULL);
3974
3975 EG(fake_scope) = old_scope;
3976 }
3977 /* }}} */
3978
zend_update_property(zend_class_entry * scope,zval * object,const char * name,size_t name_length,zval * value)3979 ZEND_API void zend_update_property(zend_class_entry *scope, zval *object, const char *name, size_t name_length, zval *value) /* {{{ */
3980 {
3981 zval property;
3982 zend_class_entry *old_scope = EG(fake_scope);
3983
3984 EG(fake_scope) = scope;
3985
3986 if (!Z_OBJ_HT_P(object)->write_property) {
3987 zend_error_noreturn(E_CORE_ERROR, "Property %s of class %s cannot be updated", name, ZSTR_VAL(Z_OBJCE_P(object)->name));
3988 }
3989 ZVAL_STRINGL(&property, name, name_length);
3990 Z_OBJ_HT_P(object)->write_property(object, &property, value, NULL);
3991 zval_ptr_dtor(&property);
3992
3993 EG(fake_scope) = old_scope;
3994 }
3995 /* }}} */
3996
zend_update_property_null(zend_class_entry * scope,zval * object,const char * name,size_t name_length)3997 ZEND_API void zend_update_property_null(zend_class_entry *scope, zval *object, const char *name, size_t name_length) /* {{{ */
3998 {
3999 zval tmp;
4000
4001 ZVAL_NULL(&tmp);
4002 zend_update_property(scope, object, name, name_length, &tmp);
4003 }
4004 /* }}} */
4005
zend_unset_property(zend_class_entry * scope,zval * object,const char * name,size_t name_length)4006 ZEND_API void zend_unset_property(zend_class_entry *scope, zval *object, const char *name, size_t name_length) /* {{{ */
4007 {
4008 zval property;
4009 zend_class_entry *old_scope = EG(fake_scope);
4010
4011 EG(fake_scope) = scope;
4012
4013 if (!Z_OBJ_HT_P(object)->unset_property) {
4014 zend_error_noreturn(E_CORE_ERROR, "Property %s of class %s cannot be unset", name, ZSTR_VAL(Z_OBJCE_P(object)->name));
4015 }
4016 ZVAL_STRINGL(&property, name, name_length);
4017 Z_OBJ_HT_P(object)->unset_property(object, &property, 0);
4018 zval_ptr_dtor(&property);
4019
4020 EG(fake_scope) = old_scope;
4021 }
4022 /* }}} */
4023
zend_update_property_bool(zend_class_entry * scope,zval * object,const char * name,size_t name_length,zend_long value)4024 ZEND_API void zend_update_property_bool(zend_class_entry *scope, zval *object, const char *name, size_t name_length, zend_long value) /* {{{ */
4025 {
4026 zval tmp;
4027
4028 ZVAL_BOOL(&tmp, value);
4029 zend_update_property(scope, object, name, name_length, &tmp);
4030 }
4031 /* }}} */
4032
zend_update_property_long(zend_class_entry * scope,zval * object,const char * name,size_t name_length,zend_long value)4033 ZEND_API void zend_update_property_long(zend_class_entry *scope, zval *object, const char *name, size_t name_length, zend_long value) /* {{{ */
4034 {
4035 zval tmp;
4036
4037 ZVAL_LONG(&tmp, value);
4038 zend_update_property(scope, object, name, name_length, &tmp);
4039 }
4040 /* }}} */
4041
zend_update_property_double(zend_class_entry * scope,zval * object,const char * name,size_t name_length,double value)4042 ZEND_API void zend_update_property_double(zend_class_entry *scope, zval *object, const char *name, size_t name_length, double value) /* {{{ */
4043 {
4044 zval tmp;
4045
4046 ZVAL_DOUBLE(&tmp, value);
4047 zend_update_property(scope, object, name, name_length, &tmp);
4048 }
4049 /* }}} */
4050
zend_update_property_str(zend_class_entry * scope,zval * object,const char * name,size_t name_length,zend_string * value)4051 ZEND_API void zend_update_property_str(zend_class_entry *scope, zval *object, const char *name, size_t name_length, zend_string *value) /* {{{ */
4052 {
4053 zval tmp;
4054
4055 ZVAL_STR(&tmp, value);
4056 zend_update_property(scope, object, name, name_length, &tmp);
4057 }
4058 /* }}} */
4059
zend_update_property_string(zend_class_entry * scope,zval * object,const char * name,size_t name_length,const char * value)4060 ZEND_API void zend_update_property_string(zend_class_entry *scope, zval *object, const char *name, size_t name_length, const char *value) /* {{{ */
4061 {
4062 zval tmp;
4063
4064 ZVAL_STRING(&tmp, value);
4065 Z_SET_REFCOUNT(tmp, 0);
4066 zend_update_property(scope, object, name, name_length, &tmp);
4067 }
4068 /* }}} */
4069
zend_update_property_stringl(zend_class_entry * scope,zval * object,const char * name,size_t name_length,const char * value,size_t value_len)4070 ZEND_API void zend_update_property_stringl(zend_class_entry *scope, zval *object, const char *name, size_t name_length, const char *value, size_t value_len) /* {{{ */
4071 {
4072 zval tmp;
4073
4074 ZVAL_STRINGL(&tmp, value, value_len);
4075 Z_SET_REFCOUNT(tmp, 0);
4076 zend_update_property(scope, object, name, name_length, &tmp);
4077 }
4078 /* }}} */
4079
zend_update_static_property_ex(zend_class_entry * scope,zend_string * name,zval * value)4080 ZEND_API int zend_update_static_property_ex(zend_class_entry *scope, zend_string *name, zval *value) /* {{{ */
4081 {
4082 zval *property;
4083 zend_class_entry *old_scope = EG(fake_scope);
4084
4085 if (UNEXPECTED(!(scope->ce_flags & ZEND_ACC_CONSTANTS_UPDATED))) {
4086 if (UNEXPECTED(zend_update_class_constants(scope)) != SUCCESS) {
4087 return FAILURE;
4088 }
4089 }
4090
4091 EG(fake_scope) = scope;
4092 property = zend_std_get_static_property(scope, name, 0);
4093 EG(fake_scope) = old_scope;
4094
4095 if (!property) {
4096 return FAILURE;
4097 }
4098
4099 if (property != value) {
4100 zval garbage;
4101 ZVAL_DEREF(property);
4102 ZVAL_DEREF(value);
4103 ZVAL_COPY_VALUE(&garbage, property);
4104 ZVAL_COPY(property, value);
4105 zval_ptr_dtor(&garbage);
4106 }
4107 return SUCCESS;
4108 }
4109 /* }}} */
4110
zend_update_static_property(zend_class_entry * scope,const char * name,size_t name_length,zval * value)4111 ZEND_API int zend_update_static_property(zend_class_entry *scope, const char *name, size_t name_length, zval *value) /* {{{ */
4112 {
4113 zend_string *key = zend_string_init(name, name_length, 0);
4114 int retval = zend_update_static_property_ex(scope, key, value);
4115 zend_string_efree(key);
4116 return retval;
4117 }
4118 /* }}} */
4119
zend_update_static_property_null(zend_class_entry * scope,const char * name,size_t name_length)4120 ZEND_API int zend_update_static_property_null(zend_class_entry *scope, const char *name, size_t name_length) /* {{{ */
4121 {
4122 zval tmp;
4123
4124 ZVAL_NULL(&tmp);
4125 return zend_update_static_property(scope, name, name_length, &tmp);
4126 }
4127 /* }}} */
4128
zend_update_static_property_bool(zend_class_entry * scope,const char * name,size_t name_length,zend_long value)4129 ZEND_API int zend_update_static_property_bool(zend_class_entry *scope, const char *name, size_t name_length, zend_long value) /* {{{ */
4130 {
4131 zval tmp;
4132
4133 ZVAL_BOOL(&tmp, value);
4134 return zend_update_static_property(scope, name, name_length, &tmp);
4135 }
4136 /* }}} */
4137
zend_update_static_property_long(zend_class_entry * scope,const char * name,size_t name_length,zend_long value)4138 ZEND_API int zend_update_static_property_long(zend_class_entry *scope, const char *name, size_t name_length, zend_long value) /* {{{ */
4139 {
4140 zval tmp;
4141
4142 ZVAL_LONG(&tmp, value);
4143 return zend_update_static_property(scope, name, name_length, &tmp);
4144 }
4145 /* }}} */
4146
zend_update_static_property_double(zend_class_entry * scope,const char * name,size_t name_length,double value)4147 ZEND_API int zend_update_static_property_double(zend_class_entry *scope, const char *name, size_t name_length, double value) /* {{{ */
4148 {
4149 zval tmp;
4150
4151 ZVAL_DOUBLE(&tmp, value);
4152 return zend_update_static_property(scope, name, name_length, &tmp);
4153 }
4154 /* }}} */
4155
zend_update_static_property_string(zend_class_entry * scope,const char * name,size_t name_length,const char * value)4156 ZEND_API int zend_update_static_property_string(zend_class_entry *scope, const char *name, size_t name_length, const char *value) /* {{{ */
4157 {
4158 zval tmp;
4159
4160 ZVAL_STRING(&tmp, value);
4161 Z_SET_REFCOUNT(tmp, 0);
4162 return zend_update_static_property(scope, name, name_length, &tmp);
4163 }
4164 /* }}} */
4165
zend_update_static_property_stringl(zend_class_entry * scope,const char * name,size_t name_length,const char * value,size_t value_len)4166 ZEND_API int zend_update_static_property_stringl(zend_class_entry *scope, const char *name, size_t name_length, const char *value, size_t value_len) /* {{{ */
4167 {
4168 zval tmp;
4169
4170 ZVAL_STRINGL(&tmp, value, value_len);
4171 Z_SET_REFCOUNT(tmp, 0);
4172 return zend_update_static_property(scope, name, name_length, &tmp);
4173 }
4174 /* }}} */
4175
zend_read_property_ex(zend_class_entry * scope,zval * object,zend_string * name,zend_bool silent,zval * rv)4176 ZEND_API zval *zend_read_property_ex(zend_class_entry *scope, zval *object, zend_string *name, zend_bool silent, zval *rv) /* {{{ */
4177 {
4178 zval property, *value;
4179 zend_class_entry *old_scope = EG(fake_scope);
4180
4181 EG(fake_scope) = scope;
4182
4183 if (!Z_OBJ_HT_P(object)->read_property) {
4184 zend_error_noreturn(E_CORE_ERROR, "Property %s of class %s cannot be read", ZSTR_VAL(name), ZSTR_VAL(Z_OBJCE_P(object)->name));
4185 }
4186
4187 ZVAL_STR(&property, name);
4188 value = Z_OBJ_HT_P(object)->read_property(object, &property, silent?BP_VAR_IS:BP_VAR_R, NULL, rv);
4189
4190 EG(fake_scope) = old_scope;
4191 return value;
4192 }
4193 /* }}} */
4194
zend_read_property(zend_class_entry * scope,zval * object,const char * name,size_t name_length,zend_bool silent,zval * rv)4195 ZEND_API zval *zend_read_property(zend_class_entry *scope, zval *object, const char *name, size_t name_length, zend_bool silent, zval *rv) /* {{{ */
4196 {
4197 zval *value;
4198 zend_string *str;
4199
4200 str = zend_string_init(name, name_length, 0);
4201 value = zend_read_property_ex(scope, object, str, silent, rv);
4202 zend_string_release_ex(str, 0);
4203 return value;
4204 }
4205 /* }}} */
4206
zend_read_static_property_ex(zend_class_entry * scope,zend_string * name,zend_bool silent)4207 ZEND_API zval *zend_read_static_property_ex(zend_class_entry *scope, zend_string *name, zend_bool silent) /* {{{ */
4208 {
4209 zval *property;
4210 zend_class_entry *old_scope = EG(fake_scope);
4211
4212 EG(fake_scope) = scope;
4213 property = zend_std_get_static_property(scope, name, silent);
4214 EG(fake_scope) = old_scope;
4215
4216 return property;
4217 }
4218 /* }}} */
4219
zend_read_static_property(zend_class_entry * scope,const char * name,size_t name_length,zend_bool silent)4220 ZEND_API zval *zend_read_static_property(zend_class_entry *scope, const char *name, size_t name_length, zend_bool silent) /* {{{ */
4221 {
4222 zend_string *key = zend_string_init(name, name_length, 0);
4223 zval *property = zend_read_static_property_ex(scope, key, silent);
4224 zend_string_efree(key);
4225 return property;
4226 }
4227 /* }}} */
4228
zend_save_error_handling(zend_error_handling * current)4229 ZEND_API void zend_save_error_handling(zend_error_handling *current) /* {{{ */
4230 {
4231 current->handling = EG(error_handling);
4232 current->exception = EG(exception_class);
4233 ZVAL_UNDEF(¤t->user_handler);
4234 }
4235 /* }}} */
4236
zend_replace_error_handling(zend_error_handling_t error_handling,zend_class_entry * exception_class,zend_error_handling * current)4237 ZEND_API void zend_replace_error_handling(zend_error_handling_t error_handling, zend_class_entry *exception_class, zend_error_handling *current) /* {{{ */
4238 {
4239 if (current) {
4240 zend_save_error_handling(current);
4241 }
4242 ZEND_ASSERT(error_handling == EH_THROW || exception_class == NULL);
4243 EG(error_handling) = error_handling;
4244 EG(exception_class) = exception_class;
4245 }
4246 /* }}} */
4247
zend_restore_error_handling(zend_error_handling * saved)4248 ZEND_API void zend_restore_error_handling(zend_error_handling *saved) /* {{{ */
4249 {
4250 EG(error_handling) = saved->handling;
4251 EG(exception_class) = saved->exception;
4252 }
4253 /* }}} */
4254
zend_find_alias_name(zend_class_entry * ce,zend_string * name)4255 ZEND_API zend_string* zend_find_alias_name(zend_class_entry *ce, zend_string *name) /* {{{ */
4256 {
4257 zend_trait_alias *alias, **alias_ptr;
4258
4259 if ((alias_ptr = ce->trait_aliases)) {
4260 alias = *alias_ptr;
4261 while (alias) {
4262 if (alias->alias && zend_string_equals_ci(alias->alias, name)) {
4263 return alias->alias;
4264 }
4265 alias_ptr++;
4266 alias = *alias_ptr;
4267 }
4268 }
4269
4270 return name;
4271 }
4272 /* }}} */
4273
zend_resolve_method_name(zend_class_entry * ce,zend_function * f)4274 ZEND_API zend_string *zend_resolve_method_name(zend_class_entry *ce, zend_function *f) /* {{{ */
4275 {
4276 zend_function *func;
4277 HashTable *function_table;
4278 zend_string *name;
4279
4280 if (f->common.type != ZEND_USER_FUNCTION ||
4281 (f->op_array.refcount && *(f->op_array.refcount) < 2) ||
4282 !f->common.scope ||
4283 !f->common.scope->trait_aliases) {
4284 return f->common.function_name;
4285 }
4286
4287 function_table = &ce->function_table;
4288 ZEND_HASH_FOREACH_STR_KEY_PTR(function_table, name, func) {
4289 if (func == f) {
4290 if (!name) {
4291 return f->common.function_name;
4292 }
4293 if (ZSTR_LEN(name) == ZSTR_LEN(f->common.function_name) &&
4294 !strncasecmp(ZSTR_VAL(name), ZSTR_VAL(f->common.function_name), ZSTR_LEN(f->common.function_name))) {
4295 return f->common.function_name;
4296 }
4297 return zend_find_alias_name(f->common.scope, name);
4298 }
4299 } ZEND_HASH_FOREACH_END();
4300 return f->common.function_name;
4301 }
4302 /* }}} */
4303
zend_get_object_type(const zend_class_entry * ce)4304 ZEND_API const char *zend_get_object_type(const zend_class_entry *ce) /* {{{ */
4305 {
4306 if(ce->ce_flags & ZEND_ACC_TRAIT) {
4307 return "trait";
4308 } else if (ce->ce_flags & ZEND_ACC_INTERFACE) {
4309 return "interface";
4310 } else {
4311 return "class";
4312 }
4313 }
4314 /* }}} */
4315
zend_is_iterable(zval * iterable)4316 ZEND_API zend_bool zend_is_iterable(zval *iterable) /* {{{ */
4317 {
4318 switch (Z_TYPE_P(iterable)) {
4319 case IS_ARRAY:
4320 return 1;
4321 case IS_OBJECT:
4322 return instanceof_function(Z_OBJCE_P(iterable), zend_ce_traversable);
4323 default:
4324 return 0;
4325 }
4326 }
4327 /* }}} */
4328
zend_is_countable(zval * countable)4329 ZEND_API zend_bool zend_is_countable(zval *countable) /* {{{ */
4330 {
4331 switch (Z_TYPE_P(countable)) {
4332 case IS_ARRAY:
4333 return 1;
4334 case IS_OBJECT:
4335 if (Z_OBJ_HT_P(countable)->count_elements) {
4336 return 1;
4337 }
4338
4339 return instanceof_function(Z_OBJCE_P(countable), zend_ce_countable);
4340 default:
4341 return 0;
4342 }
4343 }
4344 /* }}} */
4345
4346 /*
4347 * Local variables:
4348 * tab-width: 4
4349 * c-basic-offset: 4
4350 * indent-tabs-mode: t
4351 * End:
4352 * vim600: sw=4 ts=4 fdm=marker
4353 * vim<600: sw=4 ts=4
4354 */
4355