Coverage Report

Created: 2025-06-13 06:43

/src/php-src/Zend/zend_API.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
   +----------------------------------------------------------------------+
3
   | Zend Engine                                                          |
4
   +----------------------------------------------------------------------+
5
   | Copyright (c) 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_hash.h"
26
#include "zend_modules.h"
27
#include "zend_extensions.h"
28
#include "zend_constants.h"
29
#include "zend_interfaces.h"
30
#include "zend_exceptions.h"
31
#include "zend_closures.h"
32
#include "zend_inheritance.h"
33
#include "zend_ini.h"
34
#include "zend_enum.h"
35
#include "zend_object_handlers.h"
36
#include "zend_observer.h"
37
38
#include <stdarg.h>
39
40
/* these variables are true statics/globals, and have to be mutex'ed on every access */
41
ZEND_API HashTable module_registry;
42
43
static zend_module_entry **module_request_startup_handlers;
44
static zend_module_entry **module_request_shutdown_handlers;
45
static zend_module_entry **module_post_deactivate_handlers;
46
static zend_module_entry **modules_dl_loaded;
47
48
static zend_class_entry  **class_cleanup_handlers;
49
50
ZEND_API zend_result zend_get_parameters_array_ex(uint32_t param_count, zval *argument_array) /* {{{ */
51
0
{
52
0
  zval *param_ptr;
53
0
  uint32_t arg_count;
54
55
0
  param_ptr = ZEND_CALL_ARG(EG(current_execute_data), 1);
56
0
  arg_count = ZEND_CALL_NUM_ARGS(EG(current_execute_data));
57
58
0
  if (param_count>arg_count) {
59
0
    return FAILURE;
60
0
  }
61
62
0
  while (param_count-->0) {
63
0
    ZVAL_COPY_VALUE(argument_array, param_ptr);
64
0
    argument_array++;
65
0
    param_ptr++;
66
0
  }
67
68
0
  return SUCCESS;
69
0
}
70
/* }}} */
71
72
ZEND_API zend_result zend_copy_parameters_array(uint32_t param_count, zval *argument_array) /* {{{ */
73
130
{
74
130
  zval *param_ptr;
75
130
  uint32_t arg_count;
76
77
130
  param_ptr = ZEND_CALL_ARG(EG(current_execute_data), 1);
78
130
  arg_count = ZEND_CALL_NUM_ARGS(EG(current_execute_data));
79
80
130
  if (param_count>arg_count) {
81
0
    return FAILURE;
82
0
  }
83
84
444
  while (param_count-->0) {
85
314
    Z_TRY_ADDREF_P(param_ptr);
86
314
    zend_hash_next_index_insert_new(Z_ARRVAL_P(argument_array), param_ptr);
87
314
    param_ptr++;
88
314
  }
89
90
130
  return SUCCESS;
91
130
}
92
/* }}} */
93
94
ZEND_API ZEND_COLD void zend_wrong_param_count(void) /* {{{ */
95
0
{
96
0
  const char *space;
97
0
  const char *class_name = get_active_class_name(&space);
98
99
0
  zend_argument_count_error("Wrong parameter count for %s%s%s()", class_name, space, get_active_function_name());
100
0
}
101
/* }}} */
102
103
ZEND_API ZEND_COLD void zend_wrong_property_read(zval *object, zval *property)
104
29.0k
{
105
29.0k
  zend_string *tmp_property_name;
106
29.0k
  zend_string *property_name = zval_get_tmp_string(property, &tmp_property_name);
107
29.0k
  zend_error(E_WARNING, "Attempt to read property \"%s\" on %s", ZSTR_VAL(property_name), zend_zval_value_name(object));
108
29.0k
  zend_tmp_string_release(tmp_property_name);
109
29.0k
}
110
111
/* Argument parsing API -- andrei */
112
ZEND_API const char *zend_get_type_by_const(int type) /* {{{ */
113
30.6k
{
114
30.6k
  switch(type) {
115
707
    case IS_FALSE:
116
1.65k
    case IS_TRUE:
117
1.65k
    case _IS_BOOL:
118
1.65k
      return "bool";
119
2.06k
    case IS_LONG:
120
2.06k
      return "int";
121
553
    case IS_DOUBLE:
122
553
      return "float";
123
10.9k
    case IS_STRING:
124
10.9k
      return "string";
125
0
    case IS_OBJECT:
126
0
      return "object";
127
0
    case IS_RESOURCE:
128
0
      return "resource";
129
14.1k
    case IS_NULL:
130
14.1k
      return "null";
131
0
    case IS_CALLABLE:
132
0
      return "callable";
133
0
    case IS_ITERABLE:
134
0
      return "iterable";
135
1.33k
    case IS_ARRAY:
136
1.33k
      return "array";
137
0
    case IS_VOID:
138
0
      return "void";
139
0
    case IS_MIXED:
140
0
      return "mixed";
141
0
    case _IS_NUMBER:
142
0
      return "int|float";
143
30.6k
    EMPTY_SWITCH_DEFAULT_CASE()
144
30.6k
  }
145
30.6k
}
146
/* }}} */
147
148
ZEND_API const char *zend_zval_value_name(const zval *arg)
149
41.6k
{
150
41.6k
  ZVAL_DEREF(arg);
151
152
41.6k
  if (Z_ISUNDEF_P(arg)) {
153
24.2k
    return "null";
154
24.2k
  }
155
156
17.4k
  if (Z_TYPE_P(arg) == IS_OBJECT) {
157
1.31k
    return ZSTR_VAL(Z_OBJCE_P(arg)->name);
158
16.0k
  } else if (Z_TYPE_P(arg) == IS_FALSE) {
159
95
    return "false";
160
15.9k
  } else if  (Z_TYPE_P(arg) == IS_TRUE) {
161
134
    return "true";
162
134
  }
163
164
15.8k
  return zend_get_type_by_const(Z_TYPE_P(arg));
165
17.4k
}
166
167
ZEND_API const char *zend_zval_type_name(const zval *arg)
168
14.8k
{
169
14.8k
  ZVAL_DEREF(arg);
170
171
14.8k
  if (Z_ISUNDEF_P(arg)) {
172
0
    return "null";
173
0
  }
174
175
14.8k
  if (Z_TYPE_P(arg) == IS_OBJECT) {
176
1.06k
    return ZSTR_VAL(Z_OBJCE_P(arg)->name);
177
1.06k
  }
178
179
13.8k
  return zend_get_type_by_const(Z_TYPE_P(arg));
180
14.8k
}
181
182
/* This API exists *only* for use in gettype().
183
 * For anything else, you likely want zend_zval_type_name(). */
184
ZEND_API zend_string *zend_zval_get_legacy_type(const zval *arg) /* {{{ */
185
163
{
186
163
  switch (Z_TYPE_P(arg)) {
187
16
    case IS_NULL:
188
16
      return ZSTR_KNOWN(ZEND_STR_NULL);
189
0
    case IS_FALSE:
190
0
    case IS_TRUE:
191
0
      return ZSTR_KNOWN(ZEND_STR_BOOLEAN);
192
123
    case IS_LONG:
193
123
      return ZSTR_KNOWN(ZEND_STR_INTEGER);
194
0
    case IS_DOUBLE:
195
0
      return ZSTR_KNOWN(ZEND_STR_DOUBLE);
196
0
    case IS_STRING:
197
0
      return ZSTR_KNOWN(ZEND_STR_STRING);
198
24
    case IS_ARRAY:
199
24
      return ZSTR_KNOWN(ZEND_STR_ARRAY);
200
0
    case IS_OBJECT:
201
0
      return ZSTR_KNOWN(ZEND_STR_OBJECT);
202
0
    case IS_RESOURCE:
203
0
      if (zend_rsrc_list_get_rsrc_type(Z_RES_P(arg))) {
204
0
        return ZSTR_KNOWN(ZEND_STR_RESOURCE);
205
0
      } else {
206
0
        return ZSTR_KNOWN(ZEND_STR_CLOSED_RESOURCE);
207
0
      }
208
0
    default:
209
0
      return NULL;
210
163
  }
211
163
}
212
/* }}} */
213
214
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameters_none_error(void) /* {{{ */
215
426
{
216
426
  int num_args = ZEND_CALL_NUM_ARGS(EG(current_execute_data));
217
426
  zend_string *func_name = get_active_function_or_method_name();
218
219
426
  zend_argument_count_error("%s() expects exactly 0 arguments, %d given", ZSTR_VAL(func_name), num_args);
220
221
426
  zend_string_release(func_name);
222
426
}
223
/* }}} */
224
225
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameters_count_error(uint32_t min_num_args, uint32_t max_num_args) /* {{{ */
226
355
{
227
355
  uint32_t num_args = ZEND_CALL_NUM_ARGS(EG(current_execute_data));
228
355
  zend_string *func_name = get_active_function_or_method_name();
229
230
355
  zend_argument_count_error(
231
355
    "%s() expects %s %d argument%s, %d given",
232
355
    ZSTR_VAL(func_name),
233
355
    min_num_args == max_num_args ? "exactly" : num_args < min_num_args ? "at least" : "at most",
234
355
    num_args < min_num_args ? min_num_args : max_num_args,
235
355
    (num_args < min_num_args ? min_num_args : max_num_args) == 1 ? "" : "s",
236
355
    num_args
237
355
  );
238
239
355
  zend_string_release(func_name);
240
355
}
241
/* }}} */
242
243
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_error(int error_code, uint32_t num, char *name, zend_expected_type expected_type, zval *arg) /* {{{ */
244
765
{
245
765
  switch (error_code) {
246
41
    case ZPP_ERROR_WRONG_CALLBACK:
247
41
      zend_wrong_callback_error(num, name);
248
41
      break;
249
71
    case ZPP_ERROR_WRONG_CALLBACK_OR_NULL:
250
71
      zend_wrong_callback_or_null_error(num, name);
251
71
      break;
252
26
    case ZPP_ERROR_WRONG_CLASS:
253
26
      zend_wrong_parameter_class_error(num, name, arg);
254
26
      break;
255
10
    case ZPP_ERROR_WRONG_CLASS_OR_NULL:
256
10
      zend_wrong_parameter_class_or_null_error(num, name, arg);
257
10
      break;
258
0
    case ZPP_ERROR_WRONG_CLASS_OR_STRING:
259
0
      zend_wrong_parameter_class_or_string_error(num, name, arg);
260
0
      break;
261
0
    case ZPP_ERROR_WRONG_CLASS_OR_STRING_OR_NULL:
262
0
      zend_wrong_parameter_class_or_string_or_null_error(num, name, arg);
263
0
      break;
264
0
    case ZPP_ERROR_WRONG_CLASS_OR_LONG:
265
0
      zend_wrong_parameter_class_or_long_error(num, name, arg);
266
0
      break;
267
0
    case ZPP_ERROR_WRONG_CLASS_OR_LONG_OR_NULL:
268
0
      zend_wrong_parameter_class_or_long_or_null_error(num, name, arg);
269
0
      break;
270
257
    case ZPP_ERROR_WRONG_ARG:
271
257
      zend_wrong_parameter_type_error(num, expected_type, arg);
272
257
      break;
273
5
    case ZPP_ERROR_UNEXPECTED_EXTRA_NAMED:
274
5
      zend_unexpected_extra_named_error();
275
5
      break;
276
355
    case ZPP_ERROR_FAILURE:
277
355
      ZEND_ASSERT(EG(exception) && "Should have produced an error already");
278
355
      break;
279
765
    EMPTY_SWITCH_DEFAULT_CASE()
280
765
  }
281
765
}
282
/* }}} */
283
284
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_type_error(uint32_t num, zend_expected_type expected_type, zval *arg) /* {{{ */
285
257
{
286
257
  static const char * const expected_error[] = {
287
8.73k
    Z_EXPECTED_TYPES(Z_EXPECTED_TYPE_STR)
288
257
    NULL
289
257
  };
290
291
257
  if (EG(exception)) {
292
15
    return;
293
15
  }
294
295
242
  if ((expected_type == Z_EXPECTED_PATH || expected_type == Z_EXPECTED_PATH_OR_NULL)
296
242
      && Z_TYPE_P(arg) == IS_STRING) {
297
2
    zend_argument_value_error(num, "must not contain any null bytes");
298
2
    return;
299
2
  }
300
301
240
  zend_argument_type_error(num, "must be %s, %s given", expected_error[expected_type], zend_zval_value_name(arg));
302
240
}
303
/* }}} */
304
305
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_error(uint32_t num, const char *name, zval *arg) /* {{{ */
306
26
{
307
26
  if (EG(exception)) {
308
0
    return;
309
0
  }
310
311
26
  zend_argument_type_error(num, "must be of type %s, %s given", name, zend_zval_value_name(arg));
312
26
}
313
/* }}} */
314
315
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_or_null_error(uint32_t num, const char *name, zval *arg) /* {{{ */
316
10
{
317
10
  if (EG(exception)) {
318
0
    return;
319
0
  }
320
321
10
  zend_argument_type_error(num, "must be of type ?%s, %s given", name, zend_zval_value_name(arg));
322
10
}
323
/* }}} */
324
325
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_or_long_error(uint32_t num, const char *name, zval *arg) /* {{{ */
326
0
{
327
0
  if (EG(exception)) {
328
0
    return;
329
0
  }
330
331
0
  zend_argument_type_error(num, "must be of type %s|int, %s given", name, zend_zval_value_name(arg));
332
0
}
333
/* }}} */
334
335
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_or_long_or_null_error(uint32_t num, const char *name, zval *arg) /* {{{ */
336
0
{
337
0
  if (EG(exception)) {
338
0
    return;
339
0
  }
340
341
0
  zend_argument_type_error(num, "must be of type %s|int|null, %s given", name, zend_zval_value_name(arg));
342
0
}
343
/* }}} */
344
345
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_or_string_error(uint32_t num, const char *name, zval *arg) /* {{{ */
346
0
{
347
0
  if (EG(exception)) {
348
0
    return;
349
0
  }
350
351
0
  zend_argument_type_error(num, "must be of type %s|string, %s given", name, zend_zval_value_name(arg));
352
0
}
353
/* }}} */
354
355
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_or_string_or_null_error(uint32_t num, const char *name, zval *arg) /* {{{ */
356
0
{
357
0
  if (EG(exception)) {
358
0
    return;
359
0
  }
360
361
0
  zend_argument_type_error(num, "must be of type %s|string|null, %s given", name, zend_zval_value_name(arg));
362
0
}
363
/* }}} */
364
365
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_error(uint32_t num, char *error) /* {{{ */
366
41
{
367
41
  if (!EG(exception)) {
368
41
    zend_argument_type_error(num, "must be a valid callback, %s", error);
369
41
  }
370
41
  efree(error);
371
41
}
372
/* }}} */
373
374
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_or_null_error(uint32_t num, char *error) /* {{{ */
375
71
{
376
71
  if (!EG(exception)) {
377
61
    zend_argument_type_error(num, "must be a valid callback or null, %s", error);
378
61
  }
379
71
  efree(error);
380
71
}
381
/* }}} */
382
383
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_unexpected_extra_named_error(void)
384
10
{
385
10
  const char *space;
386
10
  const char *class_name = get_active_class_name(&space);
387
10
  zend_argument_count_error("%s%s%s() does not accept unknown named parameters",
388
10
    class_name, space, get_active_function_name());
389
10
}
390
391
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_argument_error_variadic(zend_class_entry *error_ce, uint32_t arg_num, const char *format, va_list va) /* {{{ */
392
1.54k
{
393
1.54k
  zend_string *func_name;
394
1.54k
  const char *arg_name;
395
1.54k
  char *message = NULL;
396
1.54k
  if (EG(exception)) {
397
5
    return;
398
5
  }
399
400
1.53k
  func_name = get_active_function_or_method_name();
401
1.53k
  arg_name = get_active_function_arg_name(arg_num);
402
403
1.53k
  zend_vspprintf(&message, 0, format, va);
404
1.53k
  zend_throw_error(error_ce, "%s(): Argument #%d%s%s%s %s",
405
1.53k
    ZSTR_VAL(func_name), arg_num,
406
1.53k
    arg_name ? " ($" : "", arg_name ? arg_name : "", arg_name ? ")" : "", message
407
1.53k
  );
408
1.53k
  efree(message);
409
1.53k
  zend_string_release(func_name);
410
1.53k
}
411
/* }}} */
412
413
ZEND_API ZEND_COLD void zend_argument_error(zend_class_entry *error_ce, uint32_t arg_num, const char *format, ...) /* {{{ */
414
86
{
415
86
  va_list va;
416
417
86
  va_start(va, format);
418
86
  zend_argument_error_variadic(error_ce, arg_num, format, va);
419
86
  va_end(va);
420
86
}
421
/* }}} */
422
423
ZEND_API ZEND_COLD void zend_argument_type_error(uint32_t arg_num, const char *format, ...) /* {{{ */
424
1.25k
{
425
1.25k
  va_list va;
426
427
1.25k
  va_start(va, format);
428
1.25k
  zend_argument_error_variadic(zend_ce_type_error, arg_num, format, va);
429
1.25k
  va_end(va);
430
1.25k
}
431
/* }}} */
432
433
ZEND_API ZEND_COLD void zend_argument_value_error(uint32_t arg_num, const char *format, ...) /* {{{ */
434
205
{
435
205
  va_list va;
436
437
205
  va_start(va, format);
438
205
  zend_argument_error_variadic(zend_ce_value_error, arg_num, format, va);
439
205
  va_end(va);
440
205
}
441
/* }}} */
442
443
ZEND_API ZEND_COLD void zend_argument_must_not_be_empty_error(uint32_t arg_num)
444
0
{
445
0
  zend_argument_value_error(arg_num, "must not be empty");
446
0
}
447
448
ZEND_API ZEND_COLD void zend_class_redeclaration_error_ex(int type, zend_string *new_name, zend_class_entry *old_ce)
449
162
{
450
162
  if (old_ce->type == ZEND_INTERNAL_CLASS) {
451
10
    zend_error(type, "Cannot redeclare %s %s",
452
10
      zend_get_object_type(old_ce),
453
10
      ZSTR_VAL(new_name));
454
152
  } else {
455
152
    zend_error(type, "Cannot redeclare %s %s (previously declared in %s:%d)",
456
152
      zend_get_object_type(old_ce),
457
152
      ZSTR_VAL(new_name),
458
152
      ZSTR_VAL(old_ce->info.user.filename),
459
152
      old_ce->info.user.line_start);
460
152
  }
461
162
}
462
463
ZEND_API ZEND_COLD void zend_class_redeclaration_error(int type, zend_class_entry *old_ce)
464
147
{
465
147
  zend_class_redeclaration_error_ex(type, old_ce->name, old_ce);
466
147
}
467
468
ZEND_API bool ZEND_FASTCALL zend_parse_arg_class(zval *arg, zend_class_entry **pce, uint32_t num, bool check_null) /* {{{ */
469
0
{
470
0
  zend_class_entry *ce_base = *pce;
471
472
0
  if (check_null && Z_TYPE_P(arg) == IS_NULL) {
473
0
    *pce = NULL;
474
0
    return 1;
475
0
  }
476
0
  if (!try_convert_to_string(arg)) {
477
0
    *pce = NULL;
478
0
    return 0;
479
0
  }
480
481
0
  *pce = zend_lookup_class(Z_STR_P(arg));
482
0
  if (ce_base) {
483
0
    if ((!*pce || !instanceof_function(*pce, ce_base))) {
484
0
      zend_argument_type_error(num, "must be a class name derived from %s, %s given", ZSTR_VAL(ce_base->name), Z_STRVAL_P(arg));
485
0
      *pce = NULL;
486
0
      return 0;
487
0
    }
488
0
  }
489
0
  if (!*pce) {
490
0
    zend_argument_type_error(num, "must be a valid class name, %s given", Z_STRVAL_P(arg));
491
0
    return 0;
492
0
  }
493
0
  return 1;
494
0
}
495
/* }}} */
496
497
5.15k
static ZEND_COLD bool zend_null_arg_deprecated(const char *fallback_type, uint32_t arg_num) {
498
5.15k
  zend_function *func = zend_active_function();
499
5.15k
  ZEND_ASSERT(arg_num > 0);
500
5.15k
  uint32_t arg_offset = arg_num - 1;
501
5.15k
  if (arg_offset >= func->common.num_args) {
502
0
    ZEND_ASSERT(func->common.fn_flags & ZEND_ACC_VARIADIC);
503
0
    arg_offset = func->common.num_args;
504
0
  }
505
506
5.15k
  zend_arg_info *arg_info = &func->common.arg_info[arg_offset];
507
5.15k
  zend_string *func_name = get_active_function_or_method_name();
508
5.15k
  const char *arg_name = get_active_function_arg_name(arg_num);
509
510
  /* If no type is specified in arginfo, use the specified fallback_type determined through
511
   * zend_parse_parameters instead. */
512
5.15k
  zend_string *type_str = zend_type_to_string(arg_info->type);
513
5.15k
  const char *type = type_str ? ZSTR_VAL(type_str) : fallback_type;
514
5.15k
  zend_error(E_DEPRECATED,
515
5.15k
    "%s(): Passing null to parameter #%" PRIu32 "%s%s%s of type %s is deprecated",
516
5.15k
    ZSTR_VAL(func_name), arg_num,
517
5.15k
    arg_name ? " ($" : "", arg_name ? arg_name : "", arg_name ? ")" : "",
518
5.15k
    type);
519
5.15k
  zend_string_release(func_name);
520
5.15k
  if (type_str) {
521
5.15k
    zend_string_release(type_str);
522
5.15k
  }
523
5.15k
  return !EG(exception);
524
5.15k
}
525
526
ZEND_API bool ZEND_FASTCALL zend_parse_arg_bool_weak(const zval *arg, bool *dest, uint32_t arg_num) /* {{{ */
527
2.56k
{
528
2.56k
  if (EXPECTED(Z_TYPE_P(arg) <= IS_STRING)) {
529
2.56k
    if (UNEXPECTED(Z_TYPE_P(arg) == IS_NULL) && !zend_null_arg_deprecated("bool", arg_num)) {
530
0
      return 0;
531
0
    }
532
2.56k
    *dest = zend_is_true(arg);
533
2.56k
  } else {
534
0
    return 0;
535
0
  }
536
2.56k
  return 1;
537
2.56k
}
538
/* }}} */
539
540
ZEND_API bool ZEND_FASTCALL zend_parse_arg_bool_slow(const zval *arg, bool *dest, uint32_t arg_num) /* {{{ */
541
1.36k
{
542
1.36k
  if (UNEXPECTED(ZEND_ARG_USES_STRICT_TYPES())) {
543
0
    return 0;
544
0
  }
545
1.36k
  return zend_parse_arg_bool_weak(arg, dest, arg_num);
546
1.36k
}
547
/* }}} */
548
549
ZEND_API bool ZEND_FASTCALL zend_flf_parse_arg_bool_slow(const zval *arg, bool *dest, uint32_t arg_num)
550
0
{
551
0
  if (UNEXPECTED(ZEND_FLF_ARG_USES_STRICT_TYPES())) {
552
0
    return 0;
553
0
  }
554
0
  return zend_parse_arg_bool_weak(arg, dest, arg_num);
555
0
}
556
557
ZEND_API bool ZEND_FASTCALL zend_parse_arg_long_weak(const zval *arg, zend_long *dest, uint32_t arg_num) /* {{{ */
558
2.26k
{
559
2.26k
  if (EXPECTED(Z_TYPE_P(arg) == IS_DOUBLE)) {
560
297
    if (UNEXPECTED(zend_isnan(Z_DVAL_P(arg)))) {
561
10
      return 0;
562
10
    }
563
287
    if (UNEXPECTED(!ZEND_DOUBLE_FITS_LONG(Z_DVAL_P(arg)))) {
564
85
      return 0;
565
202
    } else {
566
202
      zend_long lval = zend_dval_to_lval(Z_DVAL_P(arg));
567
202
      if (UNEXPECTED(!zend_is_long_compatible(Z_DVAL_P(arg), lval))) {
568
        /* Check arg_num is not (uint32_t)-1, as otherwise its called by
569
         * zend_verify_weak_scalar_type_hint_no_sideeffect() */
570
60
        if (arg_num != (uint32_t)-1) {
571
50
          zend_incompatible_double_to_long_error(Z_DVAL_P(arg));
572
50
        }
573
60
        if (UNEXPECTED(EG(exception))) {
574
5
          return 0;
575
5
        }
576
60
      }
577
197
      *dest = lval;
578
197
    }
579
1.96k
  } else if (EXPECTED(Z_TYPE_P(arg) == IS_STRING)) {
580
886
    double d;
581
886
    uint8_t type;
582
583
886
    if (UNEXPECTED((type = is_numeric_str_function(Z_STR_P(arg), dest, &d)) != IS_LONG)) {
584
420
      if (EXPECTED(type != 0)) {
585
182
        zend_long lval;
586
182
        if (UNEXPECTED(zend_isnan(d))) {
587
0
          return 0;
588
0
        }
589
182
        if (UNEXPECTED(!ZEND_DOUBLE_FITS_LONG(d))) {
590
38
          return 0;
591
38
        }
592
593
144
        lval = zend_dval_to_lval(d);
594
        /* This only checks for a fractional part as if doesn't fit it already throws a TypeError */
595
144
        if (UNEXPECTED(!zend_is_long_compatible(d, lval))) {
596
          /* Check arg_num is not (uint32_t)-1, as otherwise its called by
597
           * zend_verify_weak_scalar_type_hint_no_sideeffect() */
598
67
          if (arg_num != (uint32_t)-1) {
599
53
            zend_incompatible_string_to_long_error(Z_STR_P(arg));
600
53
          }
601
67
          if (UNEXPECTED(EG(exception))) {
602
0
            return 0;
603
0
          }
604
67
        }
605
144
        *dest = lval;
606
238
      } else {
607
238
        return 0;
608
238
      }
609
420
    }
610
610
    if (UNEXPECTED(EG(exception))) {
611
0
      return 0;
612
0
    }
613
1.08k
  } else if (EXPECTED(Z_TYPE_P(arg) < IS_TRUE)) {
614
853
    if (UNEXPECTED(Z_TYPE_P(arg) == IS_NULL) && !zend_null_arg_deprecated("int", arg_num)) {
615
0
      return 0;
616
0
    }
617
853
    *dest = 0;
618
853
  } else if (EXPECTED(Z_TYPE_P(arg) == IS_TRUE)) {
619
57
    *dest = 1;
620
173
  } else {
621
173
    return 0;
622
173
  }
623
1.71k
  return 1;
624
2.26k
}
625
/* }}} */
626
627
ZEND_API bool ZEND_FASTCALL zend_parse_arg_long_slow(const zval *arg, zend_long *dest, uint32_t arg_num) /* {{{ */
628
835
{
629
835
  if (UNEXPECTED(ZEND_ARG_USES_STRICT_TYPES())) {
630
3
    return 0;
631
3
  }
632
832
  return zend_parse_arg_long_weak(arg, dest, arg_num);
633
835
}
634
/* }}} */
635
636
ZEND_API bool ZEND_FASTCALL zend_flf_parse_arg_long_slow(const zval *arg, zend_long *dest, uint32_t arg_num)
637
0
{
638
0
  if (UNEXPECTED(ZEND_FLF_ARG_USES_STRICT_TYPES())) {
639
0
    return 0;
640
0
  }
641
0
  return zend_parse_arg_long_weak(arg, dest, arg_num);
642
0
}
643
644
ZEND_API bool ZEND_FASTCALL zend_parse_arg_double_weak(const zval *arg, double *dest, uint32_t arg_num) /* {{{ */
645
853
{
646
853
  if (EXPECTED(Z_TYPE_P(arg) == IS_LONG)) {
647
698
    *dest = (double)Z_LVAL_P(arg);
648
698
  } else if (EXPECTED(Z_TYPE_P(arg) == IS_STRING)) {
649
114
    zend_long l;
650
114
    uint8_t type;
651
652
114
    if (UNEXPECTED((type = is_numeric_str_function(Z_STR_P(arg), &l, dest)) != IS_DOUBLE)) {
653
103
      if (EXPECTED(type != 0)) {
654
68
        *dest = (double)(l);
655
68
      } else {
656
35
        return 0;
657
35
      }
658
103
    }
659
79
    if (UNEXPECTED(EG(exception))) {
660
0
      return 0;
661
0
    }
662
79
  } else if (EXPECTED(Z_TYPE_P(arg) < IS_TRUE)) {
663
0
    if (UNEXPECTED(Z_TYPE_P(arg) == IS_NULL) && !zend_null_arg_deprecated("float", arg_num)) {
664
0
      return 0;
665
0
    }
666
0
    *dest = 0.0;
667
41
  } else if (EXPECTED(Z_TYPE_P(arg) == IS_TRUE)) {
668
0
    *dest = 1.0;
669
41
  } else {
670
41
    return 0;
671
41
  }
672
777
  return 1;
673
853
}
674
/* }}} */
675
676
ZEND_API bool ZEND_FASTCALL zend_parse_arg_double_slow(const zval *arg, double *dest, uint32_t arg_num) /* {{{ */
677
300
{
678
300
  if (EXPECTED(Z_TYPE_P(arg) == IS_LONG)) {
679
    /* SSTH Exception: IS_LONG may be accepted instead as IS_DOUBLE */
680
300
    *dest = (double)Z_LVAL_P(arg);
681
300
  } else if (UNEXPECTED(ZEND_ARG_USES_STRICT_TYPES())) {
682
0
    return 0;
683
0
  }
684
300
  return zend_parse_arg_double_weak(arg, dest, arg_num);
685
300
}
686
/* }}} */
687
688
ZEND_API bool ZEND_FASTCALL zend_parse_arg_number_slow(zval *arg, zval **dest, uint32_t arg_num) /* {{{ */
689
0
{
690
0
  if (UNEXPECTED(ZEND_ARG_USES_STRICT_TYPES())) {
691
0
    return 0;
692
0
  }
693
0
  if (Z_TYPE_P(arg) == IS_STRING) {
694
0
    zend_string *str = Z_STR_P(arg);
695
0
    zend_long lval;
696
0
    double dval;
697
0
    uint8_t type = is_numeric_str_function(str, &lval, &dval);
698
0
    if (type == IS_LONG) {
699
0
      ZVAL_LONG(arg, lval);
700
0
    } else if (type == IS_DOUBLE) {
701
0
      ZVAL_DOUBLE(arg, dval);
702
0
    } else {
703
0
      return 0;
704
0
    }
705
0
    zend_string_release(str);
706
0
  } else if (Z_TYPE_P(arg) < IS_TRUE) {
707
0
    if (UNEXPECTED(Z_TYPE_P(arg) == IS_NULL) && !zend_null_arg_deprecated("int|float", arg_num)) {
708
0
      return 0;
709
0
    }
710
0
    ZVAL_LONG(arg, 0);
711
0
  } else if (Z_TYPE_P(arg) == IS_TRUE) {
712
0
    ZVAL_LONG(arg, 1);
713
0
  } else {
714
0
    return 0;
715
0
  }
716
0
  *dest = arg;
717
0
  return 1;
718
0
}
719
/* }}} */
720
721
722
ZEND_API bool ZEND_FASTCALL zend_parse_arg_number_or_str_slow(zval *arg, zval **dest, uint32_t arg_num) /* {{{ */
723
0
{
724
0
  if (UNEXPECTED(ZEND_ARG_USES_STRICT_TYPES())) {
725
0
    return false;
726
0
  }
727
0
  if (Z_TYPE_P(arg) < IS_TRUE) {
728
0
    if (UNEXPECTED(Z_TYPE_P(arg) == IS_NULL) && !zend_null_arg_deprecated("string|int|float", arg_num)) {
729
0
      return false;
730
0
    }
731
0
    ZVAL_LONG(arg, 0);
732
0
  } else if (Z_TYPE_P(arg) == IS_TRUE) {
733
0
    ZVAL_LONG(arg, 1);
734
0
  } else if (UNEXPECTED(Z_TYPE_P(arg) == IS_OBJECT)) {
735
0
    zend_object *zobj = Z_OBJ_P(arg);
736
0
    zval obj;
737
0
    if (zobj->handlers->cast_object(zobj, &obj, IS_STRING) == SUCCESS) {
738
0
      OBJ_RELEASE(zobj);
739
0
      ZVAL_COPY_VALUE(arg, &obj);
740
0
      *dest = arg;
741
0
      return true;
742
0
    }
743
0
    return false;
744
0
  } else {
745
0
    return false;
746
0
  }
747
0
  *dest = arg;
748
0
  return true;
749
0
}
750
751
ZEND_API bool ZEND_FASTCALL zend_parse_arg_str_weak(zval *arg, zend_string **dest, uint32_t arg_num) /* {{{ */
752
8.43k
{
753
8.43k
  if (EXPECTED(Z_TYPE_P(arg) < IS_STRING)) {
754
7.31k
    if (UNEXPECTED(Z_TYPE_P(arg) == IS_NULL) && !zend_null_arg_deprecated("string", arg_num)) {
755
0
      return 0;
756
0
    }
757
7.31k
    convert_to_string(arg);
758
7.31k
    *dest = Z_STR_P(arg);
759
7.31k
  } else if (UNEXPECTED(Z_TYPE_P(arg) == IS_OBJECT)) {
760
1.08k
    zend_object *zobj = Z_OBJ_P(arg);
761
1.08k
    zval obj;
762
1.08k
    if (zobj->handlers->cast_object(zobj, &obj, IS_STRING) == SUCCESS) {
763
951
      OBJ_RELEASE(zobj);
764
951
      ZVAL_COPY_VALUE(arg, &obj);
765
951
      *dest = Z_STR_P(arg);
766
951
      return 1;
767
951
    }
768
129
    return 0;
769
1.08k
  } else {
770
42
    return 0;
771
42
  }
772
7.31k
  return 1;
773
8.43k
}
774
/* }}} */
775
776
ZEND_API bool ZEND_FASTCALL zend_parse_arg_str_slow(zval *arg, zend_string **dest, uint32_t arg_num) /* {{{ */
777
7.84k
{
778
7.84k
  if (UNEXPECTED(ZEND_ARG_USES_STRICT_TYPES())) {
779
17
    return 0;
780
17
  }
781
7.83k
  return zend_parse_arg_str_weak(arg, dest, arg_num);
782
7.84k
}
783
/* }}} */
784
785
ZEND_API bool ZEND_FASTCALL zend_flf_parse_arg_str_slow(zval *arg, zend_string **dest, uint32_t arg_num)
786
0
{
787
0
  if (UNEXPECTED(ZEND_FLF_ARG_USES_STRICT_TYPES())) {
788
0
    return 0;
789
0
  }
790
0
  return zend_parse_arg_str_weak(arg, dest, arg_num);
791
0
}
792
793
ZEND_API bool ZEND_FASTCALL zend_parse_arg_str_or_long_slow(zval *arg, zend_string **dest_str, zend_long *dest_long, uint32_t arg_num) /* {{{ */
794
5
{
795
5
  if (UNEXPECTED(ZEND_ARG_USES_STRICT_TYPES())) {
796
0
    return 0;
797
0
  }
798
5
  if (zend_parse_arg_long_weak(arg, dest_long, arg_num)) {
799
0
    *dest_str = NULL;
800
0
    return 1;
801
5
  } else if (zend_parse_arg_str_weak(arg, dest_str, arg_num)) {
802
0
    *dest_long = 0;
803
0
    return 1;
804
5
  } else {
805
5
    return 0;
806
5
  }
807
5
}
808
/* }}} */
809
810
static const char *zend_parse_arg_impl(zval *arg, va_list *va, const char **spec, char **error, uint32_t arg_num) /* {{{ */
811
489k
{
812
489k
  const char *spec_walk = *spec;
813
489k
  char c = *spec_walk++;
814
489k
  bool check_null = 0;
815
489k
  bool separate = 0;
816
489k
  zval *real_arg = arg;
817
818
  /* scan through modifiers */
819
489k
  ZVAL_DEREF(arg);
820
490k
  while (1) {
821
490k
    if (*spec_walk == '/') {
822
0
      SEPARATE_ZVAL_NOREF(arg);
823
0
      real_arg = arg;
824
0
      separate = 1;
825
490k
    } else if (*spec_walk == '!') {
826
672
      check_null = 1;
827
489k
    } else {
828
489k
      break;
829
489k
    }
830
672
    spec_walk++;
831
672
  }
832
833
489k
  switch (c) {
834
2.09k
    case 'l':
835
2.09k
      {
836
2.09k
        zend_long *p = va_arg(*va, zend_long *);
837
2.09k
        bool *is_null = NULL;
838
839
2.09k
        if (check_null) {
840
149
          is_null = va_arg(*va, bool *);
841
149
        }
842
843
2.09k
        if (!zend_parse_arg_long(arg, p, is_null, check_null, arg_num)) {
844
9
          return check_null ? "?int" : "int";
845
9
        }
846
2.09k
      }
847
2.08k
      break;
848
849
2.08k
    case 'd':
850
0
      {
851
0
        double *p = va_arg(*va, double *);
852
0
        bool *is_null = NULL;
853
854
0
        if (check_null) {
855
0
          is_null = va_arg(*va, bool *);
856
0
        }
857
858
0
        if (!zend_parse_arg_double(arg, p, is_null, check_null, arg_num)) {
859
0
          return check_null ? "?float" : "float";
860
0
        }
861
0
      }
862
0
      break;
863
864
0
    case 'n':
865
0
      {
866
0
        zval **p = va_arg(*va, zval **);
867
868
0
        if (!zend_parse_arg_number(arg, p, check_null, arg_num)) {
869
0
          return check_null ? "int|float|null" : "int|float";
870
0
        }
871
0
      }
872
0
      break;
873
874
280k
    case 's':
875
280k
      {
876
280k
        char **p = va_arg(*va, char **);
877
280k
        size_t *pl = va_arg(*va, size_t *);
878
280k
        if (!zend_parse_arg_string(arg, p, pl, check_null, arg_num)) {
879
0
          return check_null ? "?string" : "string";
880
0
        }
881
280k
      }
882
280k
      break;
883
884
280k
    case 'p':
885
0
      {
886
0
        char **p = va_arg(*va, char **);
887
0
        size_t *pl = va_arg(*va, size_t *);
888
0
        if (!zend_parse_arg_path(arg, p, pl, check_null, arg_num)) {
889
0
          if (Z_TYPE_P(arg) == IS_STRING) {
890
0
            zend_spprintf(error, 0, "must not contain any null bytes");
891
0
            return "";
892
0
          } else {
893
0
            return check_null ? "?string" : "string";
894
0
          }
895
0
        }
896
0
      }
897
0
      break;
898
899
0
    case 'P':
900
0
      {
901
0
        zend_string **str = va_arg(*va, zend_string **);
902
0
        if (!zend_parse_arg_path_str(arg, str, check_null, arg_num)) {
903
0
          if (Z_TYPE_P(arg) == IS_STRING) {
904
0
            zend_spprintf(error, 0, "must not contain any null bytes");
905
0
            return "";
906
0
          } else {
907
0
            return check_null ? "?string" : "string";
908
0
          }
909
0
        }
910
0
      }
911
0
      break;
912
913
88.4k
    case 'S':
914
88.4k
      {
915
88.4k
        zend_string **str = va_arg(*va, zend_string **);
916
88.4k
        if (!zend_parse_arg_str(arg, str, check_null, arg_num)) {
917
22
          return check_null ? "?string" : "string";
918
22
        }
919
88.4k
      }
920
88.4k
      break;
921
922
88.4k
    case 'b':
923
81.1k
      {
924
81.1k
        bool *p = va_arg(*va, bool *);
925
81.1k
        bool *is_null = NULL;
926
927
81.1k
        if (check_null) {
928
0
          is_null = va_arg(*va, bool *);
929
0
        }
930
931
81.1k
        if (!zend_parse_arg_bool(arg, p, is_null, check_null, arg_num)) {
932
0
          return check_null ? "?bool" : "bool";
933
0
        }
934
81.1k
      }
935
81.1k
      break;
936
937
81.1k
    case 'r':
938
10
      {
939
10
        zval **p = va_arg(*va, zval **);
940
941
10
        if (!zend_parse_arg_resource(arg, p, check_null)) {
942
0
          return check_null ? "resource or null" : "resource";
943
0
        }
944
10
      }
945
10
      break;
946
947
250
    case 'A':
948
350
    case 'a':
949
350
      {
950
350
        zval **p = va_arg(*va, zval **);
951
952
350
        if (!zend_parse_arg_array(arg, p, check_null, c == 'A')) {
953
3
          return check_null ? "?array" : "array";
954
3
        }
955
350
      }
956
347
      break;
957
958
347
    case 'H':
959
31.3k
    case 'h':
960
31.3k
      {
961
31.3k
        HashTable **p = va_arg(*va, HashTable **);
962
963
31.3k
        if (!zend_parse_arg_array_ht(arg, p, check_null, c == 'H', separate)) {
964
2
          return check_null ? "?array" : "array";
965
2
        }
966
31.3k
      }
967
31.3k
      break;
968
969
31.3k
    case 'o':
970
120
      {
971
120
        zval **p = va_arg(*va, zval **);
972
973
120
        if (!zend_parse_arg_object(arg, p, NULL, check_null)) {
974
0
          return check_null ? "?object" : "object";
975
0
        }
976
120
      }
977
120
      break;
978
979
4.31k
    case 'O':
980
4.31k
      {
981
4.31k
        zval **p = va_arg(*va, zval **);
982
4.31k
        zend_class_entry *ce = va_arg(*va, zend_class_entry *);
983
984
4.31k
        if (!zend_parse_arg_object(arg, p, ce, check_null)) {
985
19
          if (ce) {
986
19
            if (check_null) {
987
2
              zend_spprintf(error, 0, "must be of type ?%s, %s given", ZSTR_VAL(ce->name), zend_zval_value_name(arg));
988
2
              return "";
989
17
            } else {
990
17
              return ZSTR_VAL(ce->name);
991
17
            }
992
19
          } else {
993
0
            return check_null ? "?object" : "object";
994
0
          }
995
19
        }
996
4.31k
      }
997
4.29k
      break;
998
999
4.29k
    case 'C':
1000
310
      {
1001
310
        zend_class_entry *lookup, **pce = va_arg(*va, zend_class_entry **);
1002
310
        zend_class_entry *ce_base = *pce;
1003
1004
310
        if (check_null && Z_TYPE_P(arg) == IS_NULL) {
1005
0
          *pce = NULL;
1006
0
          break;
1007
0
        }
1008
310
        if (!try_convert_to_string(arg)) {
1009
10
          *pce = NULL;
1010
10
          return ""; /* try_convert_to_string() throws an exception */
1011
10
        }
1012
1013
300
        if ((lookup = zend_lookup_class(Z_STR_P(arg))) == NULL) {
1014
10
          *pce = NULL;
1015
290
        } else {
1016
290
          *pce = lookup;
1017
290
        }
1018
300
        if (ce_base) {
1019
0
          if ((!*pce || !instanceof_function(*pce, ce_base))) {
1020
0
            zend_spprintf(error, 0, "must be a class name derived from %s%s, %s given",
1021
0
              ZSTR_VAL(ce_base->name), check_null ? " or null" : "", Z_STRVAL_P(arg));
1022
0
            *pce = NULL;
1023
0
            return "";
1024
0
          }
1025
0
        }
1026
300
        if (!*pce) {
1027
10
          zend_spprintf(error, 0, "must be a valid class name%s, %s given",
1028
10
            check_null ? " or null" : "", Z_STRVAL_P(arg));
1029
10
          return "";
1030
10
        }
1031
290
        break;
1032
1033
300
      }
1034
290
      break;
1035
1036
767
    case 'F':
1037
767
    case 'f':
1038
767
      {
1039
767
        zend_fcall_info *fci = va_arg(*va, zend_fcall_info *);
1040
767
        zend_fcall_info_cache *fcc = va_arg(*va, zend_fcall_info_cache *);
1041
767
        char *is_callable_error = NULL;
1042
1043
767
        if (check_null && Z_TYPE_P(arg) == IS_NULL) {
1044
0
          fci->size = 0;
1045
0
          fcc->function_handler = 0;
1046
0
          break;
1047
0
        }
1048
1049
767
        if (zend_fcall_info_init(arg, 0, fci, fcc, NULL, &is_callable_error) == SUCCESS) {
1050
759
          ZEND_ASSERT(!is_callable_error);
1051
759
          if (c == 'f') {
1052
            /* Release call trampolines: The function may not get called, in which case
1053
             * the trampoline will leak. Force it to be refetched during
1054
             * zend_call_function instead. */
1055
0
            zend_release_fcall_info_cache(fcc);
1056
0
          }
1057
759
          break;
1058
759
        }
1059
1060
8
        if (is_callable_error) {
1061
8
          zend_spprintf(error, 0, "must be a valid callback%s, %s", check_null ? " or null" : "", is_callable_error);
1062
8
          efree(is_callable_error);
1063
8
          return "";
1064
8
        } else {
1065
0
          return check_null ? "a valid callback or null" : "a valid callback";
1066
0
        }
1067
8
      }
1068
1069
451
    case 'z':
1070
451
      {
1071
451
        zval **p = va_arg(*va, zval **);
1072
1073
451
        zend_parse_arg_zval_deref(real_arg, p, check_null);
1074
451
      }
1075
451
      break;
1076
1077
0
    case 'Z': /* replace with 'z' */
1078
0
    case 'L': /* replace with 'l' */
1079
0
      ZEND_ASSERT(0 && "ZPP modifier no longer supported");
1080
0
      ZEND_FALLTHROUGH;
1081
0
    default:
1082
0
      return "unknown";
1083
489k
  }
1084
1085
489k
  *spec = spec_walk;
1086
1087
489k
  return NULL;
1088
489k
}
1089
/* }}} */
1090
1091
static zend_result zend_parse_arg(uint32_t arg_num, zval *arg, va_list *va, const char **spec, int flags) /* {{{ */
1092
489k
{
1093
489k
  const char *expected_type = NULL;
1094
489k
  char *error = NULL;
1095
1096
489k
  expected_type = zend_parse_arg_impl(arg, va, spec, &error, arg_num);
1097
489k
  if (expected_type) {
1098
83
    if (EG(exception)) {
1099
10
      return FAILURE;
1100
10
    }
1101
73
    if (!(flags & ZEND_PARSE_PARAMS_QUIET) && (*expected_type || error)) {
1102
67
      if (error) {
1103
20
        if (strcmp(error, "must not contain any null bytes") == 0) {
1104
0
          zend_argument_value_error(arg_num, "%s", error);
1105
20
        } else {
1106
20
          zend_argument_type_error(arg_num, "%s", error);
1107
20
        }
1108
20
        efree(error);
1109
47
      } else {
1110
47
        zend_argument_type_error(arg_num, "must be of type %s, %s given", expected_type, zend_zval_value_name(arg));
1111
47
      }
1112
67
    } else if (error) {
1113
0
      efree(error);
1114
0
    }
1115
1116
73
    return FAILURE;
1117
83
  }
1118
1119
489k
  return SUCCESS;
1120
489k
}
1121
/* }}} */
1122
1123
ZEND_API zend_result zend_parse_parameter(int flags, uint32_t arg_num, zval *arg, const char *spec, ...)
1124
0
{
1125
0
  va_list va;
1126
0
  zend_result ret;
1127
1128
0
  va_start(va, spec);
1129
0
  ret = zend_parse_arg(arg_num, arg, &va, &spec, flags);
1130
0
  va_end(va);
1131
1132
0
  return ret;
1133
0
}
1134
1135
0
static ZEND_COLD void zend_parse_parameters_debug_error(const char *msg) {
1136
0
  zend_function *active_function = EG(current_execute_data)->func;
1137
0
  const char *class_name = active_function->common.scope
1138
0
    ? ZSTR_VAL(active_function->common.scope->name) : "";
1139
0
  zend_error_noreturn(E_CORE_ERROR, "%s%s%s(): %s",
1140
0
    class_name, class_name[0] ? "::" : "",
1141
0
    ZSTR_VAL(active_function->common.function_name), msg);
1142
0
}
1143
1144
static zend_result zend_parse_va_args(uint32_t num_args, const char *type_spec, va_list *va, int flags) /* {{{ */
1145
408k
{
1146
408k
  const  char *spec_walk;
1147
408k
  char c;
1148
408k
  uint32_t i;
1149
408k
  uint32_t min_num_args = 0;
1150
408k
  uint32_t max_num_args = 0;
1151
408k
  uint32_t post_varargs = 0;
1152
408k
  zval *arg;
1153
408k
  bool have_varargs = 0;
1154
408k
  bool have_optional_args = 0;
1155
408k
  zval **varargs = NULL;
1156
408k
  uint32_t *n_varargs = NULL;
1157
1158
1.01M
  for (spec_walk = type_spec; *spec_walk; spec_walk++) {
1159
604k
    c = *spec_walk;
1160
604k
    switch (c) {
1161
10.2k
      case 'l': case 'd':
1162
373k
      case 's': case 'b':
1163
373k
      case 'r': case 'a':
1164
382k
      case 'o': case 'O':
1165
383k
      case 'z': case 'Z':
1166
415k
      case 'C': case 'h':
1167
416k
      case 'f': case 'F': case 'A':
1168
416k
      case 'H': case 'p':
1169
507k
      case 'S': case 'P':
1170
507k
      case 'L': case 'n':
1171
507k
        max_num_args++;
1172
507k
        break;
1173
1174
91.1k
      case '|':
1175
91.1k
        min_num_args = max_num_args;
1176
91.1k
        have_optional_args = 1;
1177
91.1k
        break;
1178
1179
0
      case '/':
1180
5.68k
      case '!':
1181
        /* Pass */
1182
5.68k
        break;
1183
1184
732
      case '*':
1185
737
      case '+':
1186
737
        if (have_varargs) {
1187
0
          zend_parse_parameters_debug_error(
1188
0
            "only one varargs specifier (* or +) is permitted");
1189
0
          return FAILURE;
1190
0
        }
1191
737
        have_varargs = 1;
1192
        /* we expect at least one parameter in varargs */
1193
737
        if (c == '+') {
1194
5
          max_num_args++;
1195
5
        }
1196
        /* mark the beginning of varargs */
1197
737
        post_varargs = max_num_args;
1198
1199
737
        if (ZEND_CALL_INFO(EG(current_execute_data)) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS) {
1200
5
          zend_unexpected_extra_named_error();
1201
5
          return FAILURE;
1202
5
        }
1203
732
        break;
1204
1205
732
      default:
1206
0
        zend_parse_parameters_debug_error("bad type specifier while parsing parameters");
1207
0
        return FAILURE;
1208
604k
    }
1209
604k
  }
1210
1211
  /* with no optional arguments the minimum number of arguments must be the same as the maximum */
1212
408k
  if (!have_optional_args) {
1213
316k
    min_num_args = max_num_args;
1214
316k
  }
1215
1216
408k
  if (have_varargs) {
1217
    /* calculate how many required args are at the end of the specifier list */
1218
732
    post_varargs = max_num_args - post_varargs;
1219
732
    max_num_args = UINT32_MAX;
1220
732
  }
1221
1222
408k
  if (num_args < min_num_args || num_args > max_num_args) {
1223
138
    if (!(flags & ZEND_PARSE_PARAMS_QUIET)) {
1224
112
      zend_string *func_name = get_active_function_or_method_name();
1225
1226
112
      zend_argument_count_error("%s() expects %s %d argument%s, %d given",
1227
112
        ZSTR_VAL(func_name),
1228
112
        min_num_args == max_num_args ? "exactly" : num_args < min_num_args ? "at least" : "at most",
1229
112
        num_args < min_num_args ? min_num_args : max_num_args,
1230
112
        (num_args < min_num_args ? min_num_args : max_num_args) == 1 ? "" : "s",
1231
112
        num_args
1232
112
      );
1233
1234
112
      zend_string_release(func_name);
1235
112
    }
1236
138
    return FAILURE;
1237
138
  }
1238
1239
407k
  if (num_args > ZEND_CALL_NUM_ARGS(EG(current_execute_data))) {
1240
0
    zend_parse_parameters_debug_error("could not obtain parameters for parsing");
1241
0
    return FAILURE;
1242
0
  }
1243
1244
407k
  i = 0;
1245
897k
  while (num_args-- > 0) {
1246
489k
    if (*type_spec == '|') {
1247
85.2k
      type_spec++;
1248
85.2k
    }
1249
1250
489k
    if (*type_spec == '*' || *type_spec == '+') {
1251
5
      uint32_t num_varargs = num_args + 1 - post_varargs;
1252
1253
      /* eat up the passed in storage even if it won't be filled in with varargs */
1254
5
      varargs = va_arg(*va, zval **);
1255
5
      n_varargs = va_arg(*va, uint32_t *);
1256
5
      type_spec++;
1257
1258
5
      if (num_varargs > 0) {
1259
5
        *n_varargs = num_varargs;
1260
5
        *varargs = ZEND_CALL_ARG(EG(current_execute_data), i + 1);
1261
        /* adjust how many args we have left and restart loop */
1262
5
        num_args += 1 - num_varargs;
1263
5
        i += num_varargs;
1264
5
        continue;
1265
5
      } else {
1266
0
        *varargs = NULL;
1267
0
        *n_varargs = 0;
1268
0
      }
1269
5
    }
1270
1271
489k
    arg = ZEND_CALL_ARG(EG(current_execute_data), i + 1);
1272
1273
489k
    if (zend_parse_arg(i+1, arg, va, &type_spec, flags) == FAILURE) {
1274
      /* clean up varargs array if it was used */
1275
83
      if (varargs && *varargs) {
1276
0
        *varargs = NULL;
1277
0
      }
1278
83
      return FAILURE;
1279
83
    }
1280
489k
    i++;
1281
489k
  }
1282
1283
407k
  return SUCCESS;
1284
407k
}
1285
/* }}} */
1286
1287
ZEND_API zend_result zend_parse_parameters_ex(int flags, uint32_t num_args, const char *type_spec, ...) /* {{{ */
1288
40
{
1289
40
  va_list va;
1290
40
  zend_result retval;
1291
1292
40
  va_start(va, type_spec);
1293
40
  retval = zend_parse_va_args(num_args, type_spec, &va, flags);
1294
40
  va_end(va);
1295
1296
40
  return retval;
1297
40
}
1298
/* }}} */
1299
1300
ZEND_API zend_result zend_parse_parameters(uint32_t num_args, const char *type_spec, ...) /* {{{ */
1301
408k
{
1302
408k
  va_list va;
1303
408k
  zend_result retval;
1304
408k
  int flags = 0;
1305
1306
408k
  va_start(va, type_spec);
1307
408k
  retval = zend_parse_va_args(num_args, type_spec, &va, flags);
1308
408k
  va_end(va);
1309
1310
408k
  return retval;
1311
408k
}
1312
/* }}} */
1313
1314
ZEND_API zend_result zend_parse_method_parameters(uint32_t num_args, zval *this_ptr, const char *type_spec, ...) /* {{{ */
1315
10
{
1316
10
  va_list va;
1317
10
  zend_result retval;
1318
10
  int flags = 0;
1319
10
  const char *p = type_spec;
1320
10
  zval **object;
1321
10
  zend_class_entry *ce;
1322
1323
  /* Just checking this_ptr is not enough, because fcall_common_helper does not set
1324
   * Z_OBJ(EG(This)) to NULL when calling an internal function with common.scope == NULL.
1325
   * In that case EG(This) would still be the $this from the calling code and we'd take the
1326
   * wrong branch here. */
1327
10
  bool is_method = EG(current_execute_data)->func->common.scope != NULL;
1328
1329
10
  if (!is_method || !this_ptr || Z_TYPE_P(this_ptr) != IS_OBJECT) {
1330
0
    va_start(va, type_spec);
1331
0
    retval = zend_parse_va_args(num_args, type_spec, &va, flags);
1332
0
    va_end(va);
1333
10
  } else {
1334
10
    p++;
1335
1336
10
    va_start(va, type_spec);
1337
1338
10
    object = va_arg(va, zval **);
1339
10
    ce = va_arg(va, zend_class_entry *);
1340
10
    *object = this_ptr;
1341
1342
10
    if (ce && !instanceof_function(Z_OBJCE_P(this_ptr), ce)) {
1343
0
      zend_error_noreturn(E_CORE_ERROR, "%s::%s() must be derived from %s::%s()",
1344
0
        ZSTR_VAL(Z_OBJCE_P(this_ptr)->name), get_active_function_name(), ZSTR_VAL(ce->name), get_active_function_name());
1345
0
    }
1346
1347
10
    retval = zend_parse_va_args(num_args, p, &va, flags);
1348
10
    va_end(va);
1349
10
  }
1350
10
  return retval;
1351
10
}
1352
/* }}} */
1353
1354
ZEND_API zend_result zend_parse_method_parameters_ex(int flags, uint32_t num_args, zval *this_ptr, const char *type_spec, ...) /* {{{ */
1355
0
{
1356
0
  va_list va;
1357
0
  zend_result retval;
1358
0
  const char *p = type_spec;
1359
0
  zval **object;
1360
0
  zend_class_entry *ce;
1361
1362
0
  if (!this_ptr) {
1363
0
    va_start(va, type_spec);
1364
0
    retval = zend_parse_va_args(num_args, type_spec, &va, flags);
1365
0
    va_end(va);
1366
0
  } else {
1367
0
    p++;
1368
0
    va_start(va, type_spec);
1369
1370
0
    object = va_arg(va, zval **);
1371
0
    ce = va_arg(va, zend_class_entry *);
1372
0
    *object = this_ptr;
1373
1374
0
    if (ce && !instanceof_function(Z_OBJCE_P(this_ptr), ce)) {
1375
0
      if (!(flags & ZEND_PARSE_PARAMS_QUIET)) {
1376
0
        zend_error_noreturn(E_CORE_ERROR, "%s::%s() must be derived from %s::%s()",
1377
0
          ZSTR_VAL(ce->name), get_active_function_name(), ZSTR_VAL(Z_OBJCE_P(this_ptr)->name), get_active_function_name());
1378
0
      }
1379
0
      va_end(va);
1380
0
      return FAILURE;
1381
0
    }
1382
1383
0
    retval = zend_parse_va_args(num_args, p, &va, flags);
1384
0
    va_end(va);
1385
0
  }
1386
0
  return retval;
1387
0
}
1388
/* }}} */
1389
1390
/* This function should be called after the constructor has been called
1391
 * because it may call __set from the uninitialized object otherwise. */
1392
ZEND_API void zend_merge_properties(zval *obj, HashTable *properties) /* {{{ */
1393
0
{
1394
0
  zend_object *zobj = Z_OBJ_P(obj);
1395
0
  zend_object_write_property_t write_property = zobj->handlers->write_property;
1396
0
  zend_class_entry *old_scope = EG(fake_scope);
1397
0
  zend_string *key;
1398
0
  zval *value;
1399
1400
0
  if (HT_IS_PACKED(properties)) {
1401
0
    return;
1402
0
  }
1403
0
  EG(fake_scope) = Z_OBJCE_P(obj);
1404
0
  ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(properties, key, value) {
1405
0
    if (key) {
1406
0
      write_property(zobj, key, value, NULL);
1407
0
    }
1408
0
  } ZEND_HASH_FOREACH_END();
1409
0
  EG(fake_scope) = old_scope;
1410
0
}
1411
/* }}} */
1412
1413
static zend_class_mutable_data *zend_allocate_mutable_data(zend_class_entry *class_type) /* {{{ */
1414
717
{
1415
717
  zend_class_mutable_data *mutable_data;
1416
1417
717
  ZEND_ASSERT(ZEND_MAP_PTR(class_type->mutable_data) != NULL);
1418
717
  ZEND_ASSERT(ZEND_MAP_PTR_GET_IMM(class_type->mutable_data) == NULL);
1419
1420
717
  mutable_data = zend_arena_alloc(&CG(arena), sizeof(zend_class_mutable_data));
1421
717
  memset(mutable_data, 0, sizeof(zend_class_mutable_data));
1422
717
  mutable_data->ce_flags = class_type->ce_flags;
1423
717
  ZEND_MAP_PTR_SET_IMM(class_type->mutable_data, mutable_data);
1424
1425
717
  return mutable_data;
1426
717
}
1427
/* }}} */
1428
1429
ZEND_API HashTable *zend_separate_class_constants_table(zend_class_entry *class_type) /* {{{ */
1430
435
{
1431
435
  zend_class_mutable_data *mutable_data;
1432
435
  HashTable *constants_table;
1433
435
  zend_string *key;
1434
435
  zend_class_constant *new_c, *c;
1435
1436
435
  constants_table = zend_arena_alloc(&CG(arena), sizeof(HashTable));
1437
435
  zend_hash_init(constants_table, zend_hash_num_elements(&class_type->constants_table), NULL, NULL, 0);
1438
435
  zend_hash_extend(constants_table, zend_hash_num_elements(&class_type->constants_table), 0);
1439
1440
2.88k
  ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&class_type->constants_table, key, c) {
1441
2.88k
    if (c->ce == class_type) {
1442
900
      if (Z_TYPE(c->value) == IS_CONSTANT_AST || (ZEND_CLASS_CONST_FLAGS(c) & ZEND_ACC_DEPRECATED)) {
1443
706
        new_c = zend_arena_alloc(&CG(arena), sizeof(zend_class_constant));
1444
706
        memcpy(new_c, c, sizeof(zend_class_constant));
1445
706
        c = new_c;
1446
706
      }
1447
900
      Z_TRY_ADDREF(c->value);
1448
900
    } else {
1449
105
      if (Z_TYPE(c->value) == IS_CONSTANT_AST) {
1450
95
        c = zend_hash_find_ptr(CE_CONSTANTS_TABLE(c->ce), key);
1451
95
        ZEND_ASSERT(c);
1452
95
      }
1453
105
    }
1454
1.00k
    _zend_hash_append_ptr(constants_table, key, c);
1455
1.00k
  } ZEND_HASH_FOREACH_END();
1456
1457
435
  ZEND_ASSERT(ZEND_MAP_PTR(class_type->mutable_data) != NULL);
1458
1459
435
  mutable_data = ZEND_MAP_PTR_GET_IMM(class_type->mutable_data);
1460
435
  if (!mutable_data) {
1461
362
    mutable_data = zend_allocate_mutable_data(class_type);
1462
362
  }
1463
1464
435
  mutable_data->constants_table = constants_table;
1465
1466
435
  return constants_table;
1467
435
}
1468
1469
641
static zend_result update_property(zval *val, zend_property_info *prop_info) {
1470
641
  if (ZEND_TYPE_IS_SET(prop_info->type)) {
1471
132
    zval tmp;
1472
1473
132
    ZVAL_COPY(&tmp, val);
1474
132
    if (UNEXPECTED(zval_update_constant_ex(&tmp, prop_info->ce) != SUCCESS)) {
1475
16
      zval_ptr_dtor(&tmp);
1476
16
      return FAILURE;
1477
16
    }
1478
116
    /* property initializers must always be evaluated with strict types */;
1479
116
    if (UNEXPECTED(!zend_verify_property_type(prop_info, &tmp, /* strict */ 1))) {
1480
16
      zval_ptr_dtor(&tmp);
1481
16
      return FAILURE;
1482
16
    }
1483
100
    zval_ptr_dtor(val);
1484
100
    ZVAL_COPY_VALUE(val, &tmp);
1485
100
    return SUCCESS;
1486
116
  }
1487
509
  return zval_update_constant_ex(val, prop_info->ce);
1488
641
}
1489
1490
ZEND_API zend_result zend_update_class_constant(zend_class_constant *c, const zend_string *name, zend_class_entry *scope)
1491
2.12k
{
1492
2.12k
  ZEND_ASSERT(Z_TYPE(c->value) == IS_CONSTANT_AST);
1493
1494
2.12k
  if (EXPECTED(!ZEND_TYPE_IS_SET(c->type) || ZEND_TYPE_PURE_MASK(c->type) == MAY_BE_ANY)) {
1495
1.86k
    return zval_update_constant_ex(&c->value, scope);
1496
1.86k
  }
1497
1498
263
  zval tmp;
1499
1500
263
  ZVAL_COPY(&tmp, &c->value);
1501
263
  zend_result result = zval_update_constant_ex(&tmp, scope);
1502
263
  if (result == FAILURE) {
1503
17
    zval_ptr_dtor(&tmp);
1504
17
    return FAILURE;
1505
17
  }
1506
1507
246
  if (UNEXPECTED(!zend_verify_class_constant_type(c, name, &tmp))) {
1508
58
    zval_ptr_dtor(&tmp);
1509
58
    return FAILURE;
1510
58
  }
1511
1512
188
  zval_ptr_dtor(&c->value);
1513
188
  ZVAL_COPY_VALUE(&c->value, &tmp);
1514
1515
188
  return SUCCESS;
1516
246
}
1517
1518
ZEND_API zend_result zend_update_class_constants(zend_class_entry *class_type) /* {{{ */
1519
1.05k
{
1520
1.05k
  zend_class_mutable_data *mutable_data = NULL;
1521
1.05k
  zval *default_properties_table = NULL;
1522
1.05k
  zval *static_members_table = NULL;
1523
1.05k
  zend_class_constant *c;
1524
1.05k
  zval *val;
1525
1.05k
  uint32_t ce_flags;
1526
1527
1.05k
  ce_flags = class_type->ce_flags;
1528
1529
1.05k
  if (ce_flags & ZEND_ACC_CONSTANTS_UPDATED) {
1530
22
    return SUCCESS;
1531
22
  }
1532
1533
1.03k
  bool uses_mutable_data = ZEND_MAP_PTR(class_type->mutable_data) != NULL;
1534
1.03k
  if (uses_mutable_data) {
1535
633
    mutable_data = ZEND_MAP_PTR_GET_IMM(class_type->mutable_data);
1536
633
    if (mutable_data) {
1537
278
      ce_flags = mutable_data->ce_flags;
1538
278
      if (ce_flags & ZEND_ACC_CONSTANTS_UPDATED) {
1539
235
        return SUCCESS;
1540
235
      }
1541
355
    } else {
1542
355
      mutable_data = zend_allocate_mutable_data(class_type);
1543
355
    }
1544
633
  }
1545
1546
796
  if (class_type->parent) {
1547
47
    if (UNEXPECTED(zend_update_class_constants(class_type->parent) != SUCCESS)) {
1548
7
      return FAILURE;
1549
7
    }
1550
47
  }
1551
1552
789
  if (ce_flags & ZEND_ACC_HAS_AST_CONSTANTS) {
1553
490
    HashTable *constants_table;
1554
1555
490
    if (uses_mutable_data) {
1556
101
      constants_table = mutable_data->constants_table;
1557
101
      if (!constants_table) {
1558
73
        constants_table = zend_separate_class_constants_table(class_type);
1559
73
      }
1560
389
    } else {
1561
389
      constants_table = &class_type->constants_table;
1562
389
    }
1563
1564
490
    zend_string *name;
1565
2.88k
    ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(constants_table, name, val) {
1566
2.88k
      c = Z_PTR_P(val);
1567
2.88k
      if (Z_TYPE(c->value) == IS_CONSTANT_AST) {
1568
720
        if (c->ce != class_type) {
1569
10
          Z_PTR_P(val) = c = zend_hash_find_ptr(CE_CONSTANTS_TABLE(c->ce), name);
1570
10
          if (Z_TYPE(c->value) != IS_CONSTANT_AST) {
1571
5
            continue;
1572
5
          }
1573
10
        }
1574
1575
715
        val = &c->value;
1576
715
        if (UNEXPECTED(zend_update_class_constant(c, name, c->ce) != SUCCESS)) {
1577
45
          return FAILURE;
1578
45
        }
1579
715
      }
1580
2.88k
    } ZEND_HASH_FOREACH_END();
1581
490
  }
1582
1583
744
  if (class_type->default_static_members_count) {
1584
133
    static_members_table = CE_STATIC_MEMBERS(class_type);
1585
133
    if (!static_members_table) {
1586
133
      zend_class_init_statics(class_type);
1587
133
      static_members_table = CE_STATIC_MEMBERS(class_type);
1588
133
    }
1589
133
  }
1590
1591
744
  default_properties_table = class_type->default_properties_table;
1592
744
  if (uses_mutable_data && (ce_flags & ZEND_ACC_HAS_AST_PROPERTIES)) {
1593
212
    zval *src, *dst, *end;
1594
1595
212
    default_properties_table = mutable_data->default_properties_table;
1596
212
    if (!default_properties_table) {
1597
197
      default_properties_table = zend_arena_alloc(&CG(arena), sizeof(zval) * class_type->default_properties_count);
1598
197
      src = class_type->default_properties_table;
1599
197
      dst = default_properties_table;
1600
197
      end = dst + class_type->default_properties_count;
1601
285
      do {
1602
285
        ZVAL_COPY_PROP(dst, src);
1603
285
        src++;
1604
285
        dst++;
1605
285
      } while (dst != end);
1606
197
      mutable_data->default_properties_table = default_properties_table;
1607
197
    }
1608
212
  }
1609
1610
744
  if (ce_flags & (ZEND_ACC_HAS_AST_PROPERTIES|ZEND_ACC_HAS_AST_STATICS)) {
1611
310
    zend_property_info *prop_info;
1612
1613
    /* Use the default properties table to also update initializers of private properties
1614
     * that have been shadowed in a child class. */
1615
556
    for (uint32_t i = 0; i < class_type->default_properties_count; i++) {
1616
292
      prop_info = class_type->properties_info_table[i];
1617
292
      if (!prop_info) {
1618
5
        continue;
1619
5
      }
1620
1621
287
      val = &default_properties_table[OBJ_PROP_TO_NUM(prop_info->offset)];
1622
287
      if (Z_TYPE_P(val) == IS_CONSTANT_AST
1623
287
          && UNEXPECTED(update_property(val, prop_info) != SUCCESS)) {
1624
46
        return FAILURE;
1625
46
      }
1626
287
    }
1627
1628
264
    if (class_type->default_static_members_count) {
1629
1.04k
      ZEND_HASH_MAP_FOREACH_PTR(&class_type->properties_info, prop_info) {
1630
1.04k
        if (prop_info->flags & ZEND_ACC_STATIC) {
1631
399
          val = static_members_table + prop_info->offset;
1632
399
          if (Z_TYPE_P(val) == IS_CONSTANT_AST
1633
399
              && UNEXPECTED(update_property(val, prop_info) != SUCCESS)) {
1634
33
            return FAILURE;
1635
33
          }
1636
399
        }
1637
1.04k
      } ZEND_HASH_FOREACH_END();
1638
110
    }
1639
264
  }
1640
1641
665
  if (class_type->type == ZEND_USER_CLASS && class_type->ce_flags & ZEND_ACC_ENUM && class_type->enum_backing_type != IS_UNDEF) {
1642
372
    if (zend_enum_build_backed_enum_table(class_type) == FAILURE) {
1643
101
      return FAILURE;
1644
101
    }
1645
372
  }
1646
1647
564
  ce_flags |= ZEND_ACC_CONSTANTS_UPDATED;
1648
564
  ce_flags &= ~ZEND_ACC_HAS_AST_CONSTANTS;
1649
564
  ce_flags &= ~ZEND_ACC_HAS_AST_PROPERTIES;
1650
564
  ce_flags &= ~ZEND_ACC_HAS_AST_STATICS;
1651
564
  if (uses_mutable_data) {
1652
279
    mutable_data->ce_flags = ce_flags;
1653
285
  } else {
1654
285
    class_type->ce_flags = ce_flags;
1655
285
  }
1656
1657
564
  return SUCCESS;
1658
665
}
1659
/* }}} */
1660
1661
static zend_always_inline void _object_properties_init(zend_object *object, zend_class_entry *class_type) /* {{{ */
1662
3.27M
{
1663
3.27M
  if (class_type->default_properties_count) {
1664
1.31M
    zval *src = CE_DEFAULT_PROPERTIES_TABLE(class_type);
1665
1.31M
    zval *dst = object->properties_table;
1666
1.31M
    zval *end = src + class_type->default_properties_count;
1667
1668
1.31M
    if (UNEXPECTED(class_type->type == ZEND_INTERNAL_CLASS)) {
1669
      /* We don't have to account for refcounting because
1670
       * zend_declare_typed_property() disallows refcounted defaults for internal classes. */
1671
9.04M
      do {
1672
9.04M
        ZEND_ASSERT(!Z_REFCOUNTED_P(src));
1673
9.04M
        ZVAL_COPY_VALUE_PROP(dst, src);
1674
9.04M
        src++;
1675
9.04M
        dst++;
1676
9.04M
      } while (src != end);
1677
1.29M
    } else {
1678
21.8k
      do {
1679
21.8k
        ZVAL_COPY_PROP(dst, src);
1680
21.8k
        src++;
1681
21.8k
        dst++;
1682
21.8k
      } while (src != end);
1683
14.4k
    }
1684
1.31M
  }
1685
3.27M
}
1686
/* }}} */
1687
1688
ZEND_API void object_properties_init(zend_object *object, zend_class_entry *class_type) /* {{{ */
1689
2.95M
{
1690
2.95M
  object->properties = NULL;
1691
2.95M
  _object_properties_init(object, class_type);
1692
2.95M
}
1693
/* }}} */
1694
1695
ZEND_API void object_properties_init_ex(zend_object *object, HashTable *properties) /* {{{ */
1696
0
{
1697
0
  object->properties = properties;
1698
0
  if (object->ce->default_properties_count) {
1699
0
    zval *prop;
1700
0
    zend_string *key;
1701
0
    zend_property_info *property_info;
1702
1703
0
    ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(properties, key, prop) {
1704
0
      property_info = zend_get_property_info(object->ce, key, 1);
1705
0
      if (property_info != ZEND_WRONG_PROPERTY_INFO &&
1706
0
          property_info &&
1707
0
          (property_info->flags & ZEND_ACC_STATIC) == 0) {
1708
0
        zval *slot = OBJ_PROP(object, property_info->offset);
1709
1710
0
        if (ZEND_TYPE_IS_SET(property_info->type)) {
1711
0
          zval tmp;
1712
1713
0
          ZVAL_COPY_VALUE(&tmp, prop);
1714
0
          if (UNEXPECTED(!zend_verify_property_type(property_info, &tmp, 0))) {
1715
0
            continue;
1716
0
          }
1717
0
          ZVAL_COPY_VALUE(slot, &tmp);
1718
0
        } else {
1719
0
          ZVAL_COPY_VALUE(slot, prop);
1720
0
        }
1721
0
        ZVAL_INDIRECT(prop, slot);
1722
0
      }
1723
0
    } ZEND_HASH_FOREACH_END();
1724
0
  }
1725
0
}
1726
/* }}} */
1727
1728
ZEND_API void object_properties_load(zend_object *object, HashTable *properties) /* {{{ */
1729
35.2k
{
1730
35.2k
  zval *prop, tmp;
1731
35.2k
  zend_string *key;
1732
35.2k
  zend_long h;
1733
35.2k
  zend_property_info *property_info;
1734
1735
165k
  ZEND_HASH_FOREACH_KEY_VAL(properties, h, key, prop) {
1736
165k
    if (key) {
1737
7.65k
      if (ZSTR_VAL(key)[0] == '\0') {
1738
4.63k
        const char *class_name, *prop_name;
1739
4.63k
        size_t prop_name_len;
1740
4.63k
        if (zend_unmangle_property_name_ex(key, &class_name, &prop_name, &prop_name_len) == SUCCESS) {
1741
4.11k
          zend_string *pname = zend_string_init(prop_name, prop_name_len, 0);
1742
4.11k
          zend_class_entry *prev_scope = EG(fake_scope);
1743
4.11k
          if (class_name && class_name[0] != '*') {
1744
3.87k
            zend_string *cname = zend_string_init(class_name, strlen(class_name), 0);
1745
3.87k
            EG(fake_scope) = zend_lookup_class(cname);
1746
3.87k
            zend_string_release_ex(cname, 0);
1747
3.87k
          }
1748
4.11k
          property_info = zend_get_property_info(object->ce, pname, 1);
1749
4.11k
          zend_string_release_ex(pname, 0);
1750
4.11k
          EG(fake_scope) = prev_scope;
1751
4.11k
        } else {
1752
516
          property_info = ZEND_WRONG_PROPERTY_INFO;
1753
516
        }
1754
4.63k
      } else {
1755
3.02k
        property_info = zend_get_property_info(object->ce, key, 1);
1756
3.02k
      }
1757
7.65k
      if (property_info != ZEND_WRONG_PROPERTY_INFO &&
1758
7.65k
        property_info &&
1759
7.65k
        (property_info->flags & ZEND_ACC_STATIC) == 0) {
1760
0
        zval *slot = OBJ_PROP(object, property_info->offset);
1761
0
        zval_ptr_dtor(slot);
1762
0
        ZVAL_COPY_VALUE(slot, prop);
1763
0
        zval_add_ref(slot);
1764
0
        if (object->properties) {
1765
0
          ZVAL_INDIRECT(&tmp, slot);
1766
0
          zend_hash_update(object->properties, key, &tmp);
1767
0
        }
1768
7.65k
      } else {
1769
7.65k
        if (UNEXPECTED(object->ce->ce_flags & ZEND_ACC_NO_DYNAMIC_PROPERTIES)) {
1770
0
          zend_throw_error(NULL, "Cannot create dynamic property %s::$%s",
1771
0
            ZSTR_VAL(object->ce->name), property_info != ZEND_WRONG_PROPERTY_INFO ? zend_get_unmangled_property_name(key): "");
1772
0
          return;
1773
7.65k
        } else if (!(object->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) {
1774
7.65k
          zend_error(E_DEPRECATED, "Creation of dynamic property %s::$%s is deprecated",
1775
7.65k
            ZSTR_VAL(object->ce->name), property_info != ZEND_WRONG_PROPERTY_INFO ? zend_get_unmangled_property_name(key): "");
1776
7.65k
        }
1777
1778
7.65k
        prop = zend_hash_update(zend_std_get_properties_ex(object), key, prop);
1779
7.65k
        zval_add_ref(prop);
1780
7.65k
      }
1781
57.3k
    } else {
1782
57.3k
      if (UNEXPECTED(object->ce->ce_flags & ZEND_ACC_NO_DYNAMIC_PROPERTIES)) {
1783
0
        zend_throw_error(NULL, "Cannot create dynamic property %s::$" ZEND_LONG_FMT, ZSTR_VAL(object->ce->name), h);
1784
0
        return;
1785
57.3k
      } else if (!(object->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) {
1786
57.3k
        zend_error(E_DEPRECATED, "Creation of dynamic property %s::$" ZEND_LONG_FMT " is deprecated",
1787
57.3k
          ZSTR_VAL(object->ce->name), h);
1788
57.3k
      }
1789
1790
57.3k
      prop = zend_hash_index_update(zend_std_get_properties_ex(object), h, prop);
1791
57.3k
      zval_add_ref(prop);
1792
57.3k
    }
1793
165k
  } ZEND_HASH_FOREACH_END();
1794
35.2k
}
1795
/* }}} */
1796
1797
/* This function requires 'properties' to contain all props declared in the
1798
 * class and all props being public. If only a subset is given or the class
1799
 * has protected members then you need to merge the properties separately by
1800
 * calling zend_merge_properties(). */
1801
static zend_always_inline zend_result _object_and_properties_init(zval *arg, zend_class_entry *class_type, HashTable *properties) /* {{{ */
1802
3.30M
{
1803
3.30M
  if (UNEXPECTED(class_type->ce_flags & ZEND_ACC_UNINSTANTIABLE)) {
1804
2.63k
    if (class_type->ce_flags & ZEND_ACC_INTERFACE) {
1805
6
      zend_throw_error(NULL, "Cannot instantiate interface %s", ZSTR_VAL(class_type->name));
1806
2.62k
    } else if (class_type->ce_flags & ZEND_ACC_TRAIT) {
1807
10
      zend_throw_error(NULL, "Cannot instantiate trait %s", ZSTR_VAL(class_type->name));
1808
2.61k
    } else if (class_type->ce_flags & ZEND_ACC_ENUM) {
1809
44
      zend_throw_error(NULL, "Cannot instantiate enum %s", ZSTR_VAL(class_type->name));
1810
2.57k
    } else {
1811
2.57k
      ZEND_ASSERT(class_type->ce_flags & (ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS));
1812
2.57k
      zend_throw_error(NULL, "Cannot instantiate abstract class %s", ZSTR_VAL(class_type->name));
1813
2.57k
    }
1814
2.63k
    ZVAL_NULL(arg);
1815
2.63k
    Z_OBJ_P(arg) = NULL;
1816
2.63k
    return FAILURE;
1817
2.63k
  }
1818
1819
3.29M
  if (UNEXPECTED(!(class_type->ce_flags & ZEND_ACC_CONSTANTS_UPDATED))) {
1820
272
    if (UNEXPECTED(zend_update_class_constants(class_type) != SUCCESS)) {
1821
79
      ZVAL_NULL(arg);
1822
79
      Z_OBJ_P(arg) = NULL;
1823
79
      return FAILURE;
1824
79
    }
1825
272
  }
1826
1827
3.29M
  if (class_type->create_object == NULL) {
1828
327k
    zend_object *obj = zend_objects_new(class_type);
1829
1830
327k
    ZVAL_OBJ(arg, obj);
1831
327k
    if (properties) {
1832
0
      object_properties_init_ex(obj, properties);
1833
327k
    } else {
1834
327k
      _object_properties_init(obj, class_type);
1835
327k
    }
1836
2.97M
  } else {
1837
2.97M
    ZVAL_OBJ(arg, class_type->create_object(class_type));
1838
2.97M
  }
1839
3.29M
  return SUCCESS;
1840
3.29M
}
1841
/* }}} */
1842
1843
ZEND_API zend_result object_and_properties_init(zval *arg, zend_class_entry *class_type, HashTable *properties) /* {{{ */
1844
0
{
1845
0
  return _object_and_properties_init(arg, class_type, properties);
1846
0
}
1847
/* }}} */
1848
1849
ZEND_API zend_result object_init_ex(zval *arg, zend_class_entry *class_type) /* {{{ */
1850
3.30M
{
1851
3.30M
  return _object_and_properties_init(arg, class_type, NULL);
1852
3.30M
}
1853
/* }}} */
1854
1855
ZEND_API zend_result object_init_with_constructor(zval *arg, zend_class_entry *class_type, uint32_t param_count, zval *params, HashTable *named_params) /* {{{ */
1856
569
{
1857
569
  zend_result status = _object_and_properties_init(arg, class_type, NULL);
1858
569
  if (UNEXPECTED(status == FAILURE)) {
1859
0
    ZVAL_UNDEF(arg);
1860
0
    return FAILURE;
1861
0
  }
1862
569
  zend_object *obj = Z_OBJ_P(arg);
1863
569
  zend_function *constructor = obj->handlers->get_constructor(obj);
1864
569
  if (constructor == NULL) {
1865
    /* The constructor can be NULL for 2 different reasons:
1866
     * - It is not defined
1867
     * - We are not allowed to call the constructor (e.g. private, or internal opaque class)
1868
     *   and an exception has been thrown
1869
     * in the former case, we are (mostly) done and the object is initialized,
1870
     * in the latter we need to destroy the object as initialization failed
1871
     */
1872
104
    if (UNEXPECTED(EG(exception))) {
1873
5
      zval_ptr_dtor(arg);
1874
5
      ZVAL_UNDEF(arg);
1875
5
      return FAILURE;
1876
5
    }
1877
1878
    /* Surprisingly, this is the only case where internal classes will allow to pass extra arguments
1879
     * However, if there are named arguments (and it is not empty),
1880
     * an Error must be thrown to be consistent with new ClassName() */
1881
99
    if (UNEXPECTED(named_params != NULL && zend_hash_num_elements(named_params) != 0)) {
1882
      /* Throw standard Error */
1883
5
      zend_string *arg_name = NULL;
1884
5
      zend_hash_get_current_key(named_params, &arg_name, /* num_index */ NULL);
1885
5
      ZEND_ASSERT(arg_name != NULL);
1886
5
      zend_throw_error(NULL, "Unknown named parameter $%s", ZSTR_VAL(arg_name));
1887
      /* Do not call destructor, free object, and set arg to IS_UNDEF */
1888
5
      zend_object_store_ctor_failed(obj);
1889
5
      zval_ptr_dtor(arg);
1890
5
      ZVAL_UNDEF(arg);
1891
5
      return FAILURE;
1892
94
    } else {
1893
94
      return SUCCESS;
1894
94
    }
1895
99
  }
1896
  /* A constructor should not return a value, however if an exception is thrown
1897
   * zend_call_known_function() will set the retval to IS_UNDEF */
1898
465
  zval retval;
1899
465
  zend_call_known_function(
1900
465
    constructor,
1901
465
    obj,
1902
465
    class_type,
1903
465
    &retval,
1904
465
    param_count,
1905
465
    params,
1906
465
    named_params
1907
465
  );
1908
465
  if (Z_TYPE(retval) == IS_UNDEF) {
1909
    /* Do not call destructor, free object, and set arg to IS_UNDEF */
1910
53
    zend_object_store_ctor_failed(obj);
1911
53
    zval_ptr_dtor(arg);
1912
53
    ZVAL_UNDEF(arg);
1913
53
    return FAILURE;
1914
412
  } else {
1915
    /* Unlikely, but user constructors may return any value they want */
1916
412
    zval_ptr_dtor(&retval);
1917
412
    return SUCCESS;
1918
412
  }
1919
465
}
1920
/* }}} */
1921
1922
ZEND_API void object_init(zval *arg) /* {{{ */
1923
2.09M
{
1924
2.09M
  ZVAL_OBJ(arg, zend_objects_new(zend_standard_class_def));
1925
2.09M
}
1926
/* }}} */
1927
1928
ZEND_API void add_assoc_long_ex(zval *arg, const char *key, size_t key_len, zend_long n) /* {{{ */
1929
36.6k
{
1930
36.6k
  zval tmp;
1931
1932
36.6k
  ZVAL_LONG(&tmp, n);
1933
36.6k
  zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1934
36.6k
}
1935
/* }}} */
1936
1937
ZEND_API void add_assoc_null_ex(zval *arg, const char *key, size_t key_len) /* {{{ */
1938
12.1k
{
1939
12.1k
  zval tmp;
1940
1941
12.1k
  ZVAL_NULL(&tmp);
1942
12.1k
  zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1943
12.1k
}
1944
/* }}} */
1945
1946
ZEND_API void add_assoc_bool_ex(zval *arg, const char *key, size_t key_len, bool b) /* {{{ */
1947
965
{
1948
965
  zval tmp;
1949
1950
965
  ZVAL_BOOL(&tmp, b);
1951
965
  zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1952
965
}
1953
/* }}} */
1954
1955
ZEND_API void add_assoc_resource_ex(zval *arg, const char *key, size_t key_len, zend_resource *r) /* {{{ */
1956
0
{
1957
0
  zval tmp;
1958
1959
0
  ZVAL_RES(&tmp, r);
1960
0
  zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1961
0
}
1962
/* }}} */
1963
1964
ZEND_API void add_assoc_double_ex(zval *arg, const char *key, size_t key_len, double d) /* {{{ */
1965
8.76k
{
1966
8.76k
  zval tmp;
1967
1968
8.76k
  ZVAL_DOUBLE(&tmp, d);
1969
8.76k
  zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1970
8.76k
}
1971
/* }}} */
1972
1973
ZEND_API void add_assoc_str_ex(zval *arg, const char *key, size_t key_len, zend_string *str) /* {{{ */
1974
17
{
1975
17
  zval tmp;
1976
1977
17
  ZVAL_STR(&tmp, str);
1978
17
  zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1979
17
}
1980
/* }}} */
1981
1982
ZEND_API void add_assoc_string_ex(zval *arg, const char *key, size_t key_len, const char *str) /* {{{ */
1983
20.4k
{
1984
20.4k
  zval tmp;
1985
1986
20.4k
  ZVAL_STRING(&tmp, str);
1987
20.4k
  zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1988
20.4k
}
1989
/* }}} */
1990
1991
ZEND_API void add_assoc_stringl_ex(zval *arg, const char *key, size_t key_len, const char *str, size_t length) /* {{{ */
1992
40.7k
{
1993
40.7k
  zval tmp;
1994
1995
40.7k
  ZVAL_STRINGL(&tmp, str, length);
1996
40.7k
  zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1997
40.7k
}
1998
/* }}} */
1999
2000
ZEND_API void add_assoc_array_ex(zval *arg, const char *key, size_t key_len, zend_array *arr) /* {{{ */
2001
0
{
2002
0
  zval tmp;
2003
2004
0
  ZVAL_ARR(&tmp, arr);
2005
0
  zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
2006
0
}
2007
/* }}} */
2008
2009
ZEND_API void add_assoc_object_ex(zval *arg, const char *key, size_t key_len, zend_object *obj) /* {{{ */
2010
286
{
2011
286
  zval tmp;
2012
2013
286
  ZVAL_OBJ(&tmp, obj);
2014
286
  zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
2015
286
}
2016
/* }}} */
2017
2018
ZEND_API void add_assoc_reference_ex(zval *arg, const char *key, size_t key_len, zend_reference *ref) /* {{{ */
2019
0
{
2020
0
  zval tmp;
2021
2022
0
  ZVAL_REF(&tmp, ref);
2023
0
  zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
2024
0
}
2025
/* }}} */
2026
2027
ZEND_API void add_assoc_zval_ex(zval *arg, const char *key, size_t key_len, zval *value) /* {{{ */
2028
41.8k
{
2029
41.8k
  zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, value);
2030
41.8k
}
2031
/* }}} */
2032
2033
ZEND_API void add_index_long(zval *arg, zend_ulong index, zend_long n) /* {{{ */
2034
3.25M
{
2035
3.25M
  zval tmp;
2036
2037
3.25M
  ZVAL_LONG(&tmp, n);
2038
3.25M
  zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
2039
3.25M
}
2040
/* }}} */
2041
2042
ZEND_API void add_index_null(zval *arg, zend_ulong index) /* {{{ */
2043
0
{
2044
0
  zval tmp;
2045
2046
0
  ZVAL_NULL(&tmp);
2047
0
  zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
2048
0
}
2049
/* }}} */
2050
2051
ZEND_API void add_index_bool(zval *arg, zend_ulong index, bool b) /* {{{ */
2052
0
{
2053
0
  zval tmp;
2054
2055
0
  ZVAL_BOOL(&tmp, b);
2056
0
  zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
2057
0
}
2058
/* }}} */
2059
2060
ZEND_API void add_index_resource(zval *arg, zend_ulong index, zend_resource *r) /* {{{ */
2061
0
{
2062
0
  zval tmp;
2063
2064
0
  ZVAL_RES(&tmp, r);
2065
0
  zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
2066
0
}
2067
/* }}} */
2068
2069
ZEND_API void add_index_double(zval *arg, zend_ulong index, double d) /* {{{ */
2070
378k
{
2071
378k
  zval tmp;
2072
2073
378k
  ZVAL_DOUBLE(&tmp, d);
2074
378k
  zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
2075
378k
}
2076
/* }}} */
2077
2078
ZEND_API void add_index_str(zval *arg, zend_ulong index, zend_string *str) /* {{{ */
2079
0
{
2080
0
  zval tmp;
2081
2082
0
  ZVAL_STR(&tmp, str);
2083
0
  zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
2084
0
}
2085
/* }}} */
2086
2087
ZEND_API void add_index_string(zval *arg, zend_ulong index, const char *str) /* {{{ */
2088
330k
{
2089
330k
  zval tmp;
2090
2091
330k
  ZVAL_STRING(&tmp, str);
2092
330k
  zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
2093
330k
}
2094
/* }}} */
2095
2096
ZEND_API void add_index_stringl(zval *arg, zend_ulong index, const char *str, size_t length) /* {{{ */
2097
0
{
2098
0
  zval tmp;
2099
2100
0
  ZVAL_STRINGL(&tmp, str, length);
2101
0
  zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
2102
0
}
2103
/* }}} */
2104
2105
ZEND_API void add_index_array(zval *arg, zend_ulong index, zend_array *arr) /* {{{ */
2106
0
{
2107
0
  zval tmp;
2108
2109
0
  ZVAL_ARR(&tmp, arr);
2110
0
  zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
2111
0
}
2112
/* }}} */
2113
2114
ZEND_API void add_index_object(zval *arg, zend_ulong index, zend_object *obj) /* {{{ */
2115
0
{
2116
0
  zval tmp;
2117
2118
0
  ZVAL_OBJ(&tmp, obj);
2119
0
  zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
2120
0
}
2121
/* }}} */
2122
2123
ZEND_API void add_index_reference(zval *arg, zend_ulong index, zend_reference *ref) /* {{{ */
2124
0
{
2125
0
  zval tmp;
2126
2127
0
  ZVAL_REF(&tmp, ref);
2128
0
  zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
2129
0
}
2130
/* }}} */
2131
2132
ZEND_API zend_result add_next_index_long(zval *arg, zend_long n) /* {{{ */
2133
0
{
2134
0
  zval tmp;
2135
2136
0
  ZVAL_LONG(&tmp, n);
2137
0
  return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
2138
0
}
2139
/* }}} */
2140
2141
ZEND_API zend_result add_next_index_null(zval *arg) /* {{{ */
2142
0
{
2143
0
  zval tmp;
2144
2145
0
  ZVAL_NULL(&tmp);
2146
0
  return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
2147
0
}
2148
/* }}} */
2149
2150
ZEND_API zend_result add_next_index_bool(zval *arg, bool b) /* {{{ */
2151
0
{
2152
0
  zval tmp;
2153
2154
0
  ZVAL_BOOL(&tmp, b);
2155
0
  return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
2156
0
}
2157
/* }}} */
2158
2159
ZEND_API zend_result add_next_index_resource(zval *arg, zend_resource *r) /* {{{ */
2160
0
{
2161
0
  zval tmp;
2162
2163
0
  ZVAL_RES(&tmp, r);
2164
0
  return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
2165
0
}
2166
/* }}} */
2167
2168
ZEND_API zend_result add_next_index_double(zval *arg, double d) /* {{{ */
2169
0
{
2170
0
  zval tmp;
2171
2172
0
  ZVAL_DOUBLE(&tmp, d);
2173
0
  return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
2174
0
}
2175
/* }}} */
2176
2177
ZEND_API zend_result add_next_index_str(zval *arg, zend_string *str) /* {{{ */
2178
26.2k
{
2179
26.2k
  zval tmp;
2180
2181
26.2k
  ZVAL_STR(&tmp, str);
2182
26.2k
  return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
2183
26.2k
}
2184
/* }}} */
2185
2186
ZEND_API zend_result add_next_index_string(zval *arg, const char *str) /* {{{ */
2187
2.09k
{
2188
2.09k
  zval tmp;
2189
2190
2.09k
  ZVAL_STRING(&tmp, str);
2191
2.09k
  return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
2192
2.09k
}
2193
/* }}} */
2194
2195
ZEND_API zend_result add_next_index_stringl(zval *arg, const char *str, size_t length) /* {{{ */
2196
0
{
2197
0
  zval tmp;
2198
2199
0
  ZVAL_STRINGL(&tmp, str, length);
2200
0
  return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
2201
0
}
2202
/* }}} */
2203
2204
ZEND_API zend_result add_next_index_array(zval *arg, zend_array *arr) /* {{{ */
2205
0
{
2206
0
  zval tmp;
2207
2208
0
  ZVAL_ARR(&tmp, arr);
2209
0
  return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
2210
0
}
2211
/* }}} */
2212
2213
ZEND_API zend_result add_next_index_object(zval *arg, zend_object *obj) /* {{{ */
2214
0
{
2215
0
  zval tmp;
2216
2217
0
  ZVAL_OBJ(&tmp, obj);
2218
0
  return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
2219
0
}
2220
/* }}} */
2221
2222
ZEND_API zend_result add_next_index_reference(zval *arg, zend_reference *ref) /* {{{ */
2223
0
{
2224
0
  zval tmp;
2225
2226
0
  ZVAL_REF(&tmp, ref);
2227
0
  return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
2228
0
}
2229
/* }}} */
2230
2231
ZEND_API zend_result array_set_zval_key(HashTable *ht, zval *key, zval *value) /* {{{ */
2232
531
{
2233
531
  zval *result;
2234
2235
531
  switch (Z_TYPE_P(key)) {
2236
62
    case IS_STRING:
2237
62
      result = zend_symtable_update(ht, Z_STR_P(key), value);
2238
62
      break;
2239
15
    case IS_NULL:
2240
15
      result = zend_hash_update(ht, ZSTR_EMPTY_ALLOC(), value);
2241
15
      break;
2242
0
    case IS_RESOURCE:
2243
0
      zend_use_resource_as_offset(key);
2244
0
      result = zend_hash_index_update(ht, Z_RES_HANDLE_P(key), value);
2245
0
      break;
2246
12
    case IS_FALSE:
2247
12
      result = zend_hash_index_update(ht, 0, value);
2248
12
      break;
2249
9
    case IS_TRUE:
2250
9
      result = zend_hash_index_update(ht, 1, value);
2251
9
      break;
2252
405
    case IS_LONG:
2253
405
      result = zend_hash_index_update(ht, Z_LVAL_P(key), value);
2254
405
      break;
2255
18
    case IS_DOUBLE:
2256
18
      result = zend_hash_index_update(ht, zend_dval_to_lval_safe(Z_DVAL_P(key)), value);
2257
18
      break;
2258
10
    default:
2259
10
      zend_illegal_container_offset(ZSTR_KNOWN(ZEND_STR_ARRAY), key, BP_VAR_W);
2260
10
      result = NULL;
2261
531
  }
2262
2263
531
  if (result) {
2264
521
    Z_TRY_ADDREF_P(result);
2265
521
    return SUCCESS;
2266
521
  } else {
2267
10
    return FAILURE;
2268
10
  }
2269
531
}
2270
/* }}} */
2271
2272
ZEND_API void add_property_long_ex(zval *arg, const char *key, size_t key_len, zend_long n) /* {{{ */
2273
0
{
2274
0
  zval tmp;
2275
2276
0
  ZVAL_LONG(&tmp, n);
2277
0
  add_property_zval_ex(arg, key, key_len, &tmp);
2278
0
}
2279
/* }}} */
2280
2281
ZEND_API void add_property_bool_ex(zval *arg, const char *key, size_t key_len, zend_long b) /* {{{ */
2282
0
{
2283
0
  zval tmp;
2284
2285
0
  ZVAL_BOOL(&tmp, b);
2286
0
  add_property_zval_ex(arg, key, key_len, &tmp);
2287
0
}
2288
/* }}} */
2289
2290
ZEND_API void add_property_null_ex(zval *arg, const char *key, size_t key_len) /* {{{ */
2291
113
{
2292
113
  zval tmp;
2293
2294
113
  ZVAL_NULL(&tmp);
2295
113
  add_property_zval_ex(arg, key, key_len, &tmp);
2296
113
}
2297
/* }}} */
2298
2299
ZEND_API void add_property_resource_ex(zval *arg, const char *key, size_t key_len, zend_resource *r) /* {{{ */
2300
60
{
2301
60
  zval tmp;
2302
2303
60
  ZVAL_RES(&tmp, r);
2304
60
  add_property_zval_ex(arg, key, key_len, &tmp);
2305
60
  zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
2306
60
}
2307
/* }}} */
2308
2309
ZEND_API void add_property_double_ex(zval *arg, const char *key, size_t key_len, double d) /* {{{ */
2310
0
{
2311
0
  zval tmp;
2312
2313
0
  ZVAL_DOUBLE(&tmp, d);
2314
0
  add_property_zval_ex(arg, key, key_len, &tmp);
2315
0
}
2316
/* }}} */
2317
2318
ZEND_API void add_property_str_ex(zval *arg, const char *key, size_t key_len, zend_string *str) /* {{{ */
2319
0
{
2320
0
  zval tmp;
2321
2322
0
  ZVAL_STR(&tmp, str);
2323
0
  add_property_zval_ex(arg, key, key_len, &tmp);
2324
0
  zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
2325
0
}
2326
/* }}} */
2327
2328
ZEND_API void add_property_string_ex(zval *arg, const char *key, size_t key_len, const char *str) /* {{{ */
2329
16
{
2330
16
  zval tmp;
2331
2332
16
  ZVAL_STRING(&tmp, str);
2333
16
  add_property_zval_ex(arg, key, key_len, &tmp);
2334
16
  zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
2335
16
}
2336
/* }}} */
2337
2338
ZEND_API void add_property_stringl_ex(zval *arg, const char *key, size_t key_len, const char *str, size_t length) /* {{{ */
2339
0
{
2340
0
  zval tmp;
2341
2342
0
  ZVAL_STRINGL(&tmp, str, length);
2343
0
  add_property_zval_ex(arg, key, key_len, &tmp);
2344
0
  zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
2345
0
}
2346
/* }}} */
2347
2348
ZEND_API void add_property_array_ex(zval *arg, const char *key, size_t key_len, zend_array *arr) /* {{{ */
2349
0
{
2350
0
  zval tmp;
2351
2352
0
  ZVAL_ARR(&tmp, arr);
2353
0
  add_property_zval_ex(arg, key, key_len, &tmp);
2354
0
  zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
2355
0
}
2356
/* }}} */
2357
2358
ZEND_API void add_property_object_ex(zval *arg, const char *key, size_t key_len, zend_object *obj) /* {{{ */
2359
0
{
2360
0
  zval tmp;
2361
2362
0
  ZVAL_OBJ(&tmp, obj);
2363
0
  add_property_zval_ex(arg, key, key_len, &tmp);
2364
0
  zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
2365
0
}
2366
/* }}} */
2367
2368
ZEND_API void add_property_reference_ex(zval *arg, const char *key, size_t key_len, zend_reference *ref) /* {{{ */
2369
0
{
2370
0
  zval tmp;
2371
2372
0
  ZVAL_REF(&tmp, ref);
2373
0
  add_property_zval_ex(arg, key, key_len, &tmp);
2374
0
  zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
2375
0
}
2376
/* }}} */
2377
2378
ZEND_API void add_property_zval_ex(zval *arg, const char *key, size_t key_len, zval *value) /* {{{ */
2379
189
{
2380
189
  zend_string *str;
2381
2382
189
  str = zend_string_init(key, key_len, 0);
2383
189
  Z_OBJ_HANDLER_P(arg, write_property)(Z_OBJ_P(arg), str, value, NULL);
2384
189
  zend_string_release_ex(str, 0);
2385
189
}
2386
/* }}} */
2387
2388
ZEND_API zend_result zend_startup_module_ex(zend_module_entry *module) /* {{{ */
2389
196
{
2390
196
  size_t name_len;
2391
196
  zend_string *lcname;
2392
2393
196
  if (module->module_started) {
2394
0
    return SUCCESS;
2395
0
  }
2396
196
  module->module_started = 1;
2397
2398
  /* Check module dependencies */
2399
196
  if (module->deps) {
2400
64
    const zend_module_dep *dep = module->deps;
2401
2402
144
    while (dep->name) {
2403
80
      if (dep->type == MODULE_DEP_REQUIRED) {
2404
48
        zend_module_entry *req_mod;
2405
2406
48
        name_len = strlen(dep->name);
2407
48
        lcname = zend_string_alloc(name_len, 0);
2408
48
        zend_str_tolower_copy(ZSTR_VAL(lcname), dep->name, name_len);
2409
2410
48
        if ((req_mod = zend_hash_find_ptr(&module_registry, lcname)) == NULL || !req_mod->module_started) {
2411
0
          zend_string_efree(lcname);
2412
          /* TODO: Check version relationship */
2413
0
          zend_error(E_CORE_WARNING, "Cannot load module \"%s\" because required module \"%s\" is not loaded", module->name, dep->name);
2414
0
          module->module_started = 0;
2415
0
          return FAILURE;
2416
0
        }
2417
48
        zend_string_efree(lcname);
2418
48
      }
2419
80
      ++dep;
2420
80
    }
2421
64
  }
2422
2423
  /* Initialize module globals */
2424
196
  if (module->globals_size) {
2425
#ifdef ZTS
2426
    ts_allocate_id(module->globals_id_ptr, module->globals_size, (ts_allocate_ctor) module->globals_ctor, (ts_allocate_dtor) module->globals_dtor);
2427
#else
2428
96
    if (module->globals_ctor) {
2429
80
      module->globals_ctor(module->globals_ptr);
2430
80
    }
2431
96
#endif
2432
96
  }
2433
196
  if (module->module_startup_func) {
2434
196
    EG(current_module) = module;
2435
196
    if (module->module_startup_func(module->type, module->module_number)==FAILURE) {
2436
0
      zend_error_noreturn(E_CORE_ERROR,"Unable to start %s module", module->name);
2437
0
      EG(current_module) = NULL;
2438
0
      return FAILURE;
2439
0
    }
2440
196
    EG(current_module) = NULL;
2441
196
  }
2442
196
  return SUCCESS;
2443
196
}
2444
/* }}} */
2445
2446
static int zend_startup_module_zval(zval *zv) /* {{{ */
2447
192
{
2448
192
  zend_module_entry *module = Z_PTR_P(zv);
2449
2450
192
  return (zend_startup_module_ex(module) == SUCCESS) ? ZEND_HASH_APPLY_KEEP : ZEND_HASH_APPLY_REMOVE;
2451
192
}
2452
/* }}} */
2453
2454
static void zend_sort_modules(void *base, size_t count, size_t siz, compare_func_t compare, swap_func_t swp) /* {{{ */
2455
16
{
2456
16
  Bucket *b1 = base;
2457
16
  Bucket *b2;
2458
16
  Bucket *end = b1 + count;
2459
16
  Bucket tmp;
2460
16
  zend_module_entry *m, *r;
2461
2462
208
  while (b1 < end) {
2463
208
try_again:
2464
208
    m = (zend_module_entry*)Z_PTR(b1->val);
2465
208
    if (!m->module_started && m->deps) {
2466
80
      const zend_module_dep *dep = m->deps;
2467
160
      while (dep->name) {
2468
96
        if (dep->type == MODULE_DEP_REQUIRED || dep->type == MODULE_DEP_OPTIONAL) {
2469
96
          b2 = b1 + 1;
2470
384
          while (b2 < end) {
2471
304
            r = (zend_module_entry*)Z_PTR(b2->val);
2472
304
            if (strcasecmp(dep->name, r->name) == 0) {
2473
16
              tmp = *b1;
2474
16
              *b1 = *b2;
2475
16
              *b2 = tmp;
2476
16
              goto try_again;
2477
16
            }
2478
288
            b2++;
2479
288
          }
2480
96
        }
2481
80
        dep++;
2482
80
      }
2483
80
    }
2484
192
    b1++;
2485
192
  }
2486
16
}
2487
/* }}} */
2488
2489
ZEND_API void zend_collect_module_handlers(void) /* {{{ */
2490
16
{
2491
16
  zend_module_entry *module;
2492
16
  int startup_count = 0;
2493
16
  int shutdown_count = 0;
2494
16
  int post_deactivate_count = 0;
2495
16
  int dl_loaded_count = 0;
2496
16
  zend_class_entry *ce;
2497
16
  int class_count = 0;
2498
2499
  /* Collect extensions with request startup/shutdown handlers */
2500
424
  ZEND_HASH_MAP_FOREACH_PTR(&module_registry, module) {
2501
424
    if (module->request_startup_func) {
2502
116
      startup_count++;
2503
116
    }
2504
424
    if (module->request_shutdown_func) {
2505
80
      shutdown_count++;
2506
80
    }
2507
424
    if (module->post_deactivate_func) {
2508
20
      post_deactivate_count++;
2509
20
    }
2510
424
    if (module->handle) {
2511
0
      dl_loaded_count++;
2512
0
    }
2513
424
  } ZEND_HASH_FOREACH_END();
2514
16
  module_request_startup_handlers = (zend_module_entry**)realloc(
2515
16
    module_request_startup_handlers,
2516
16
      sizeof(zend_module_entry*) *
2517
16
    (startup_count + 1 +
2518
16
     shutdown_count + 1 +
2519
16
     post_deactivate_count + 1));
2520
16
  module_request_startup_handlers[startup_count] = NULL;
2521
16
  module_request_shutdown_handlers = module_request_startup_handlers + startup_count + 1;
2522
16
  module_request_shutdown_handlers[shutdown_count] = NULL;
2523
16
  module_post_deactivate_handlers = module_request_shutdown_handlers + shutdown_count + 1;
2524
16
  module_post_deactivate_handlers[post_deactivate_count] = NULL;
2525
  /* Cannot reuse module_request_startup_handlers because it is freed in zend_destroy_modules, which happens before zend_unload_modules. */
2526
16
  modules_dl_loaded = realloc(modules_dl_loaded, sizeof(zend_module_entry*) * (dl_loaded_count + 1));
2527
16
  modules_dl_loaded[dl_loaded_count] = NULL;
2528
16
  startup_count = 0;
2529
2530
424
  ZEND_HASH_MAP_FOREACH_PTR(&module_registry, module) {
2531
424
    if (module->request_startup_func) {
2532
116
      module_request_startup_handlers[startup_count++] = module;
2533
116
    }
2534
424
    if (module->request_shutdown_func) {
2535
80
      module_request_shutdown_handlers[--shutdown_count] = module;
2536
80
    }
2537
424
    if (module->post_deactivate_func) {
2538
20
      module_post_deactivate_handlers[--post_deactivate_count] = module;
2539
20
    }
2540
424
    if (module->handle) {
2541
0
      modules_dl_loaded[--dl_loaded_count] = module;
2542
0
    }
2543
424
  } ZEND_HASH_FOREACH_END();
2544
2545
  /* Collect internal classes with static members */
2546
5.21k
  ZEND_HASH_MAP_FOREACH_PTR(CG(class_table), ce) {
2547
5.21k
    if (ce->type == ZEND_INTERNAL_CLASS &&
2548
2.59k
        ce->default_static_members_count > 0) {
2549
0
        class_count++;
2550
0
    }
2551
5.21k
  } ZEND_HASH_FOREACH_END();
2552
2553
16
  class_cleanup_handlers = (zend_class_entry**)realloc(
2554
16
    class_cleanup_handlers,
2555
16
    sizeof(zend_class_entry*) *
2556
16
    (class_count + 1));
2557
16
  class_cleanup_handlers[class_count] = NULL;
2558
2559
16
  if (class_count) {
2560
0
    ZEND_HASH_MAP_FOREACH_PTR(CG(class_table), ce) {
2561
0
      if (ce->type == ZEND_INTERNAL_CLASS &&
2562
0
          ce->default_static_members_count > 0) {
2563
0
          class_cleanup_handlers[--class_count] = ce;
2564
0
      }
2565
0
    } ZEND_HASH_FOREACH_END();
2566
0
  }
2567
16
}
2568
/* }}} */
2569
2570
ZEND_API void zend_startup_modules(void) /* {{{ */
2571
16
{
2572
16
  zend_hash_sort_ex(&module_registry, zend_sort_modules, NULL, 0);
2573
16
  zend_hash_apply(&module_registry, zend_startup_module_zval);
2574
16
}
2575
/* }}} */
2576
2577
ZEND_API void zend_destroy_modules(void) /* {{{ */
2578
0
{
2579
0
  free(class_cleanup_handlers);
2580
0
  class_cleanup_handlers = NULL;
2581
0
  free(module_request_startup_handlers);
2582
0
  module_request_startup_handlers = NULL;
2583
0
  zend_hash_graceful_reverse_destroy(&module_registry);
2584
0
}
2585
/* }}} */
2586
2587
ZEND_API zend_module_entry* zend_register_module_ex(zend_module_entry *module, int module_type) /* {{{ */
2588
196
{
2589
196
  size_t name_len;
2590
196
  zend_string *lcname;
2591
196
  zend_module_entry *module_ptr;
2592
2593
196
  if (!module) {
2594
0
    return NULL;
2595
0
  }
2596
2597
#if 0
2598
  zend_printf("%s: Registering module %d\n", module->name, module->module_number);
2599
#endif
2600
2601
  /* Check module dependencies */
2602
196
  if (module->deps) {
2603
64
    const zend_module_dep *dep = module->deps;
2604
2605
144
    while (dep->name) {
2606
80
      if (dep->type == MODULE_DEP_CONFLICTS) {
2607
0
        name_len = strlen(dep->name);
2608
0
        lcname = zend_string_alloc(name_len, 0);
2609
0
        zend_str_tolower_copy(ZSTR_VAL(lcname), dep->name, name_len);
2610
2611
0
        if (zend_hash_exists(&module_registry, lcname) || zend_get_extension(dep->name)) {
2612
0
          zend_string_efree(lcname);
2613
          /* TODO: Check version relationship */
2614
0
          zend_error(E_CORE_WARNING, "Cannot load module \"%s\" because conflicting module \"%s\" is already loaded", module->name, dep->name);
2615
0
          return NULL;
2616
0
        }
2617
0
        zend_string_efree(lcname);
2618
0
      }
2619
80
      ++dep;
2620
80
    }
2621
64
  }
2622
2623
196
  name_len = strlen(module->name);
2624
196
  lcname = zend_string_alloc(name_len, module_type == MODULE_PERSISTENT);
2625
196
  zend_str_tolower_copy(ZSTR_VAL(lcname), module->name, name_len);
2626
2627
196
  int module_number = zend_next_free_module();
2628
2629
196
  lcname = zend_new_interned_string(lcname);
2630
196
  if ((module_ptr = zend_hash_add_ptr(&module_registry, lcname, module)) == NULL) {
2631
0
    zend_error(E_CORE_WARNING, "Module \"%s\" is already loaded", module->name);
2632
0
    zend_string_release(lcname);
2633
0
    return NULL;
2634
0
  }
2635
196
  module = module_ptr;
2636
196
  EG(current_module) = module;
2637
2638
196
  module->module_number = module_number;
2639
196
  module->type = module_type;
2640
2641
196
  if (module->functions && zend_register_functions(NULL, module->functions, NULL, module_type)==FAILURE) {
2642
0
    zend_hash_del(&module_registry, lcname);
2643
0
    zend_string_release(lcname);
2644
0
    EG(current_module) = NULL;
2645
0
    zend_error(E_CORE_WARNING,"%s: Unable to register functions, unable to load", module->name);
2646
0
    return NULL;
2647
0
  }
2648
2649
196
  EG(current_module) = NULL;
2650
196
  zend_string_release(lcname);
2651
196
  return module;
2652
196
}
2653
/* }}} */
2654
2655
ZEND_API zend_module_entry* zend_register_internal_module(zend_module_entry *module) /* {{{ */
2656
180
{
2657
180
  return zend_register_module_ex(module, MODULE_PERSISTENT);
2658
180
}
2659
/* }}} */
2660
2661
static void zend_check_magic_method_args(
2662
    uint32_t num_args, const zend_class_entry *ce, const zend_function *fptr, int error_type)
2663
10.3k
{
2664
10.3k
  if (fptr->common.num_args != num_args) {
2665
51
    if (num_args == 0) {
2666
37
      zend_error(error_type, "Method %s::%s() cannot take arguments",
2667
37
        ZSTR_VAL(ce->name), ZSTR_VAL(fptr->common.function_name));
2668
37
    } else if (num_args == 1) {
2669
7
      zend_error(error_type, "Method %s::%s() must take exactly 1 argument",
2670
7
        ZSTR_VAL(ce->name), ZSTR_VAL(fptr->common.function_name));
2671
7
    } else {
2672
7
      zend_error(error_type, "Method %s::%s() must take exactly %" PRIu32 " arguments",
2673
7
        ZSTR_VAL(ce->name), ZSTR_VAL(fptr->common.function_name), num_args);
2674
7
    }
2675
51
    return;
2676
51
  }
2677
15.8k
  for (uint32_t i = 0; i < num_args; i++) {
2678
5.59k
    if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(fptr, i + 1)) {
2679
6
      zend_error(error_type, "Method %s::%s() cannot take arguments by reference",
2680
6
        ZSTR_VAL(ce->name), ZSTR_VAL(fptr->common.function_name));
2681
6
      return;
2682
6
    }
2683
5.59k
  }
2684
10.2k
}
2685
2686
static void zend_check_magic_method_arg_type(uint32_t arg_num, const zend_class_entry *ce, const zend_function *fptr, int error_type, int arg_type)
2687
5.01k
{
2688
5.01k
    if (
2689
5.01k
      ZEND_TYPE_IS_SET(fptr->common.arg_info[arg_num].type)
2690
5.01k
       && !(ZEND_TYPE_FULL_MASK(fptr->common.arg_info[arg_num].type) & arg_type)
2691
5.01k
    ) {
2692
50
      zend_error(error_type, "%s::%s(): Parameter #%d ($%s) must be of type %s when declared",
2693
50
        ZSTR_VAL(ce->name), ZSTR_VAL(fptr->common.function_name),
2694
50
        arg_num + 1, ZSTR_VAL(fptr->common.arg_info[arg_num].name),
2695
50
        ZSTR_VAL(zend_type_to_string((zend_type) ZEND_TYPE_INIT_MASK(arg_type))));
2696
50
    }
2697
5.01k
}
2698
2699
static void zend_check_magic_method_return_type(const zend_class_entry *ce, const zend_function *fptr, int error_type, int return_type)
2700
4.33k
{
2701
4.33k
  if (return_type == MAY_BE_VOID) {
2702
1.95k
    if (fptr->common.fn_flags & ZEND_ACC_NODISCARD) {
2703
6
      zend_error_noreturn(error_type, "Method %s::%s cannot be #[\\NoDiscard]", ZSTR_VAL(ce->name), ZSTR_VAL(fptr->common.function_name));
2704
6
    }
2705
1.95k
  }
2706
2707
4.32k
  if (!(fptr->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE)) {
2708
    /* For backwards compatibility reasons, do not enforce the return type if it is not set. */
2709
1.11k
    return;
2710
1.11k
  }
2711
2712
3.20k
  if (ZEND_TYPE_PURE_MASK(fptr->common.arg_info[-1].type) & MAY_BE_NEVER) {
2713
    /* It is always legal to specify the never type. */
2714
80
    return;
2715
80
  }
2716
2717
3.12k
  bool is_complex_type = ZEND_TYPE_IS_COMPLEX(fptr->common.arg_info[-1].type);
2718
3.12k
  uint32_t extra_types = ZEND_TYPE_PURE_MASK(fptr->common.arg_info[-1].type) & ~return_type;
2719
3.12k
  if (extra_types & MAY_BE_STATIC) {
2720
44
    extra_types &= ~MAY_BE_STATIC;
2721
44
    is_complex_type = true;
2722
44
  }
2723
2724
3.12k
  if (extra_types || (is_complex_type && return_type != MAY_BE_OBJECT)) {
2725
71
    zend_error(error_type, "%s::%s(): Return type must be %s when declared",
2726
71
      ZSTR_VAL(ce->name), ZSTR_VAL(fptr->common.function_name),
2727
71
      ZSTR_VAL(zend_type_to_string((zend_type) ZEND_TYPE_INIT_MASK(return_type))));
2728
71
  }
2729
3.12k
}
2730
2731
static void zend_check_magic_method_non_static(
2732
    const zend_class_entry *ce, const zend_function *fptr, int error_type)
2733
14.4k
{
2734
14.4k
  if (fptr->common.fn_flags & ZEND_ACC_STATIC) {
2735
48
    zend_error(error_type, "Method %s::%s() cannot be static",
2736
48
      ZSTR_VAL(ce->name), ZSTR_VAL(fptr->common.function_name));
2737
48
  }
2738
14.4k
}
2739
2740
static void zend_check_magic_method_static(
2741
    const zend_class_entry *ce, const zend_function *fptr, int error_type)
2742
690
{
2743
690
  if (!(fptr->common.fn_flags & ZEND_ACC_STATIC)) {
2744
12
    zend_error(error_type, "Method %s::%s() must be static",
2745
12
      ZSTR_VAL(ce->name), ZSTR_VAL(fptr->common.function_name));
2746
12
  }
2747
690
}
2748
2749
static void zend_check_magic_method_public(
2750
    const zend_class_entry *ce, const zend_function *fptr, int error_type)
2751
6.51k
{
2752
  // TODO: Remove this warning after adding proper visibility handling.
2753
6.51k
  if (!(fptr->common.fn_flags & ZEND_ACC_PUBLIC)) {
2754
298
    zend_error(E_WARNING, "The magic method %s::%s() must have public visibility",
2755
298
      ZSTR_VAL(ce->name), ZSTR_VAL(fptr->common.function_name));
2756
298
  }
2757
6.51k
}
2758
2759
static void zend_check_magic_method_no_return_type(
2760
    const zend_class_entry *ce, const zend_function *fptr, int error_type)
2761
8.16k
{
2762
8.16k
  if (fptr->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
2763
12
    zend_error_noreturn(error_type, "Method %s::%s() cannot declare a return type",
2764
12
      ZSTR_VAL(ce->name), ZSTR_VAL(fptr->common.function_name));
2765
12
  }
2766
2767
8.15k
  if (fptr->common.fn_flags & ZEND_ACC_NODISCARD) {
2768
6
    zend_error_noreturn(error_type, "Method %s::%s cannot be #[\\NoDiscard]", ZSTR_VAL(ce->name), ZSTR_VAL(fptr->common.function_name));
2769
6
  }
2770
8.15k
}
2771
2772
ZEND_API void zend_check_magic_method_implementation(const zend_class_entry *ce, const zend_function *fptr, zend_string *lcname, int error_type) /* {{{ */
2773
47.3k
{
2774
47.3k
  if (ZSTR_VAL(lcname)[0] != '_'
2775
47.3k
   || ZSTR_VAL(lcname)[1] != '_') {
2776
30.3k
    return;
2777
30.3k
  }
2778
2779
17.0k
  if (zend_string_equals_literal(lcname, ZEND_CONSTRUCTOR_FUNC_NAME)) {
2780
4.67k
    zend_check_magic_method_non_static(ce, fptr, error_type);
2781
4.67k
    zend_check_magic_method_no_return_type(ce, fptr, error_type);
2782
12.3k
  } else if (zend_string_equals_literal(lcname, ZEND_DESTRUCTOR_FUNC_NAME)) {
2783
3.50k
    zend_check_magic_method_args(0, ce, fptr, error_type);
2784
3.50k
    zend_check_magic_method_non_static(ce, fptr, error_type);
2785
3.50k
    zend_check_magic_method_no_return_type(ce, fptr, error_type);
2786
8.82k
  } else if (zend_string_equals_literal(lcname, ZEND_CLONE_FUNC_NAME)) {
2787
454
    zend_check_magic_method_args(0, ce, fptr, error_type);
2788
454
    zend_check_magic_method_non_static(ce, fptr, error_type);
2789
454
    zend_check_magic_method_return_type(ce, fptr, error_type, MAY_BE_VOID);
2790
8.36k
  } else if (zend_string_equals_literal(lcname, ZEND_GET_FUNC_NAME)) {
2791
1.28k
    zend_check_magic_method_args(1, ce, fptr, error_type);
2792
1.28k
    zend_check_magic_method_non_static(ce, fptr, error_type);
2793
1.28k
    zend_check_magic_method_public(ce, fptr, error_type);
2794
1.28k
    zend_check_magic_method_arg_type(0, ce, fptr, error_type, MAY_BE_STRING);
2795
7.08k
  } else if (zend_string_equals_literal(lcname, ZEND_SET_FUNC_NAME)) {
2796
526
    zend_check_magic_method_args(2, ce, fptr, error_type);
2797
526
    zend_check_magic_method_non_static(ce, fptr, error_type);
2798
526
    zend_check_magic_method_public(ce, fptr, error_type);
2799
526
    zend_check_magic_method_arg_type(0, ce, fptr, error_type, MAY_BE_STRING);
2800
526
    zend_check_magic_method_return_type(ce, fptr, error_type, MAY_BE_VOID);
2801
6.56k
  } else if (zend_string_equals_literal(lcname, ZEND_UNSET_FUNC_NAME)) {
2802
300
    zend_check_magic_method_args(1, ce, fptr, error_type);
2803
300
    zend_check_magic_method_non_static(ce, fptr, error_type);
2804
300
    zend_check_magic_method_public(ce, fptr, error_type);
2805
300
    zend_check_magic_method_arg_type(0, ce, fptr, error_type, MAY_BE_STRING);
2806
300
    zend_check_magic_method_return_type(ce, fptr, error_type, MAY_BE_VOID);
2807
6.26k
  } else if (zend_string_equals_literal(lcname, ZEND_ISSET_FUNC_NAME)) {
2808
226
    zend_check_magic_method_args(1, ce, fptr, error_type);
2809
226
    zend_check_magic_method_non_static(ce, fptr, error_type);
2810
226
    zend_check_magic_method_public(ce, fptr, error_type);
2811
226
    zend_check_magic_method_arg_type(0, ce, fptr, error_type, MAY_BE_STRING);
2812
226
    zend_check_magic_method_return_type(ce, fptr, error_type, MAY_BE_BOOL);
2813
6.03k
  } else if (zend_string_equals_literal(lcname, ZEND_CALL_FUNC_NAME)) {
2814
597
    zend_check_magic_method_args(2, ce, fptr, error_type);
2815
597
    zend_check_magic_method_non_static(ce, fptr, error_type);
2816
597
    zend_check_magic_method_public(ce, fptr, error_type);
2817
597
    zend_check_magic_method_arg_type(0, ce, fptr, error_type, MAY_BE_STRING);
2818
597
    zend_check_magic_method_arg_type(1, ce, fptr, error_type, MAY_BE_ARRAY);
2819
5.43k
  } else if (zend_string_equals_literal(lcname, ZEND_CALLSTATIC_FUNC_NAME)) {
2820
490
    zend_check_magic_method_args(2, ce, fptr, error_type);
2821
490
    zend_check_magic_method_static(ce, fptr, error_type);
2822
490
    zend_check_magic_method_public(ce, fptr, error_type);
2823
490
    zend_check_magic_method_arg_type(0, ce, fptr, error_type, MAY_BE_STRING);
2824
490
    zend_check_magic_method_arg_type(1, ce, fptr, error_type, MAY_BE_ARRAY);
2825
4.94k
  } else if (zend_string_equals_literal(lcname, ZEND_TOSTRING_FUNC_NAME)) {
2826
886
    zend_check_magic_method_args(0, ce, fptr, error_type);
2827
886
    zend_check_magic_method_non_static(ce, fptr, error_type);
2828
886
    zend_check_magic_method_public(ce, fptr, error_type);
2829
886
    zend_check_magic_method_return_type(ce, fptr, error_type, MAY_BE_STRING);
2830
4.06k
  } else if (zend_string_equals_literal(lcname, ZEND_DEBUGINFO_FUNC_NAME)) {
2831
489
    zend_check_magic_method_args(0, ce, fptr, error_type);
2832
489
    zend_check_magic_method_non_static(ce, fptr, error_type);
2833
489
    zend_check_magic_method_public(ce, fptr, error_type);
2834
489
    zend_check_magic_method_return_type(ce, fptr, error_type, (MAY_BE_ARRAY | MAY_BE_NULL));
2835
3.57k
  } else if (zend_string_equals_literal(lcname, "__serialize")) {
2836
412
    zend_check_magic_method_args(0, ce, fptr, error_type);
2837
412
    zend_check_magic_method_non_static(ce, fptr, error_type);
2838
412
    zend_check_magic_method_public(ce, fptr, error_type);
2839
412
    zend_check_magic_method_return_type(ce, fptr, error_type, MAY_BE_ARRAY);
2840
3.16k
  } else if (zend_string_equals_literal(lcname, "__unserialize")) {
2841
383
    zend_check_magic_method_args(1, ce, fptr, error_type);
2842
383
    zend_check_magic_method_non_static(ce, fptr, error_type);
2843
383
    zend_check_magic_method_public(ce, fptr, error_type);
2844
383
    zend_check_magic_method_arg_type(0, ce, fptr, error_type, MAY_BE_ARRAY);
2845
383
    zend_check_magic_method_return_type(ce, fptr, error_type, MAY_BE_VOID);
2846
2.77k
  } else if (zend_string_equals_literal(lcname, "__set_state")) {
2847
201
    zend_check_magic_method_args(1, ce, fptr, error_type);
2848
201
    zend_check_magic_method_static(ce, fptr, error_type);
2849
201
    zend_check_magic_method_public(ce, fptr, error_type);
2850
201
    zend_check_magic_method_arg_type(0, ce, fptr, error_type, MAY_BE_ARRAY);
2851
201
    zend_check_magic_method_return_type(ce, fptr, error_type, MAY_BE_OBJECT);
2852
2.57k
  } else if (zend_string_equals(lcname, ZSTR_KNOWN(ZEND_STR_MAGIC_INVOKE))) {
2853
246
    zend_check_magic_method_non_static(ce, fptr, error_type);
2854
246
    zend_check_magic_method_public(ce, fptr, error_type);
2855
2.33k
  } else if (zend_string_equals(lcname, ZSTR_KNOWN(ZEND_STR_SLEEP))) {
2856
208
    zend_check_magic_method_args(0, ce, fptr, error_type);
2857
208
    zend_check_magic_method_non_static(ce, fptr, error_type);
2858
208
    zend_check_magic_method_public(ce, fptr, error_type);
2859
208
    zend_check_magic_method_return_type(ce, fptr, error_type, MAY_BE_ARRAY);
2860
2.12k
  } else if (zend_string_equals(lcname, ZSTR_KNOWN(ZEND_STR_WAKEUP))) {
2861
353
    zend_check_magic_method_args(0, ce, fptr, error_type);
2862
353
    zend_check_magic_method_non_static(ce, fptr, error_type);
2863
353
    zend_check_magic_method_public(ce, fptr, error_type);
2864
353
    zend_check_magic_method_return_type(ce, fptr, error_type, MAY_BE_VOID);
2865
353
  }
2866
17.0k
}
2867
/* }}} */
2868
2869
ZEND_API void zend_add_magic_method(zend_class_entry *ce, zend_function *fptr, zend_string *lcname)
2870
49.0k
{
2871
49.0k
  if (ZSTR_VAL(lcname)[0] != '_' || ZSTR_VAL(lcname)[1] != '_') {
2872
    /* pass */
2873
31.8k
  } else if (zend_string_equals_literal(lcname, ZEND_CLONE_FUNC_NAME)) {
2874
473
    ce->clone = fptr;
2875
16.7k
  } else if (zend_string_equals_literal(lcname, ZEND_CONSTRUCTOR_FUNC_NAME)) {
2876
4.78k
    ce->constructor = fptr;
2877
4.78k
    ce->constructor->common.fn_flags |= ZEND_ACC_CTOR;
2878
11.9k
  } else if (zend_string_equals_literal(lcname, ZEND_DESTRUCTOR_FUNC_NAME)) {
2879
3.51k
    ce->destructor = fptr;
2880
8.46k
  } else if (zend_string_equals_literal(lcname, ZEND_GET_FUNC_NAME)) {
2881
1.29k
    ce->__get = fptr;
2882
1.29k
    ce->ce_flags |= ZEND_ACC_USE_GUARDS;
2883
7.16k
  } else if (zend_string_equals_literal(lcname, ZEND_SET_FUNC_NAME)) {
2884
530
    ce->__set = fptr;
2885
530
    ce->ce_flags |= ZEND_ACC_USE_GUARDS;
2886
6.63k
  } else if (zend_string_equals_literal(lcname, ZEND_CALL_FUNC_NAME)) {
2887
597
    ce->__call = fptr;
2888
6.04k
  } else if (zend_string_equals_literal(lcname, ZEND_UNSET_FUNC_NAME)) {
2889
300
    ce->__unset = fptr;
2890
300
    ce->ce_flags |= ZEND_ACC_USE_GUARDS;
2891
5.74k
  } else if (zend_string_equals_literal(lcname, ZEND_ISSET_FUNC_NAME)) {
2892
238
    ce->__isset = fptr;
2893
238
    ce->ce_flags |= ZEND_ACC_USE_GUARDS;
2894
5.50k
  } else if (zend_string_equals_literal(lcname, ZEND_CALLSTATIC_FUNC_NAME)) {
2895
502
    ce->__callstatic = fptr;
2896
5.00k
  } else if (zend_string_equals_literal(lcname, ZEND_TOSTRING_FUNC_NAME)) {
2897
908
    ce->__tostring = fptr;
2898
4.09k
  } else if (zend_string_equals_literal(lcname, ZEND_DEBUGINFO_FUNC_NAME)) {
2899
489
    ce->__debugInfo = fptr;
2900
489
    ce->ce_flags |= ZEND_ACC_USE_GUARDS;
2901
3.60k
  } else if (zend_string_equals_literal(lcname, "__serialize")) {
2902
412
    ce->__serialize = fptr;
2903
3.19k
  } else if (zend_string_equals_literal(lcname, "__unserialize")) {
2904
383
    ce->__unserialize = fptr;
2905
383
  }
2906
49.0k
}
2907
2908
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arg_info_toString, 0, 0, IS_STRING, 0)
2909
ZEND_END_ARG_INFO()
2910
2911
54.5k
static zend_always_inline void zend_normalize_internal_type(zend_type *type) {
2912
54.5k
  ZEND_ASSERT(!ZEND_TYPE_HAS_LITERAL_NAME(*type));
2913
54.5k
  if (ZEND_TYPE_PURE_MASK(*type) != MAY_BE_ANY) {
2914
51.1k
    ZEND_ASSERT(!ZEND_TYPE_CONTAINS_CODE(*type, IS_RESOURCE) && "resource is not allowed in a zend_type");
2915
51.1k
  }
2916
54.5k
  zend_type *current;
2917
109k
  ZEND_TYPE_FOREACH_MUTABLE(*type, current) {
2918
109k
    if (ZEND_TYPE_HAS_NAME(*current)) {
2919
3.78k
      zend_string *name = zend_new_interned_string(ZEND_TYPE_NAME(*current));
2920
3.78k
      zend_alloc_ce_cache(name);
2921
3.78k
      ZEND_TYPE_SET_PTR(*current, name);
2922
50.7k
    } else if (ZEND_TYPE_HAS_LIST(*current)) {
2923
0
      zend_type *inner;
2924
0
      ZEND_TYPE_FOREACH_MUTABLE(*current, inner) {
2925
0
        ZEND_ASSERT(!ZEND_TYPE_HAS_LITERAL_NAME(*inner) && !ZEND_TYPE_HAS_LIST(*inner));
2926
0
        if (ZEND_TYPE_HAS_NAME(*inner)) {
2927
0
          zend_string *name = zend_new_interned_string(ZEND_TYPE_NAME(*inner));
2928
0
          zend_alloc_ce_cache(name);
2929
0
          ZEND_TYPE_SET_PTR(*inner, name);
2930
0
        }
2931
0
      } ZEND_TYPE_FOREACH_END();
2932
0
    }
2933
109k
  } ZEND_TYPE_FOREACH_END();
2934
54.5k
}
2935
2936
/* registers all functions in *library_functions in the function hash */
2937
ZEND_API zend_result zend_register_functions(zend_class_entry *scope, const zend_function_entry *functions, HashTable *function_table, int type) /* {{{ */
2938
1.98k
{
2939
1.98k
  const zend_function_entry *ptr = functions;
2940
1.98k
  zend_function function;
2941
1.98k
  zend_internal_function *reg_function, *internal_function = (zend_internal_function *)&function;
2942
1.98k
  int count=0, unload=0;
2943
1.98k
  HashTable *target_function_table = function_table;
2944
1.98k
  int error_type;
2945
1.98k
  zend_string *lowercase_name;
2946
1.98k
  size_t fname_len;
2947
2948
1.98k
  if (type==MODULE_PERSISTENT) {
2949
1.98k
    error_type = E_CORE_WARNING;
2950
1.98k
  } else {
2951
0
    error_type = E_WARNING;
2952
0
  }
2953
2954
1.98k
  if (!target_function_table) {
2955
148
    target_function_table = CG(function_table);
2956
148
  }
2957
1.98k
  internal_function->type = ZEND_INTERNAL_FUNCTION;
2958
1.98k
  internal_function->module = EG(current_module);
2959
1.98k
  if (EG(active) && ZEND_OBSERVER_ENABLED) {
2960
    /* Add an observer temporary to store previous observed frames. This is
2961
     * normally handled by zend_observer_post_startup(), except for
2962
     * functions registered at runtime (EG(active)). */
2963
0
    internal_function->T = 1;
2964
1.98k
  } else {
2965
1.98k
    internal_function->T = 0;
2966
1.98k
  }
2967
1.98k
  memset(internal_function->reserved, 0, ZEND_MAX_RESERVED_RESOURCES * sizeof(void*));
2968
2969
27.9k
  while (ptr->fname) {
2970
25.9k
    fname_len = strlen(ptr->fname);
2971
25.9k
    internal_function->handler = ptr->handler;
2972
25.9k
    internal_function->doc_comment = ptr->doc_comment ? zend_string_init_interned(ptr->doc_comment, strlen(ptr->doc_comment), 1) : NULL;
2973
25.9k
    internal_function->function_name = zend_string_init_interned(ptr->fname, fname_len, 1);
2974
25.9k
    internal_function->scope = scope;
2975
25.9k
    internal_function->prototype = NULL;
2976
25.9k
    internal_function->prop_info = NULL;
2977
25.9k
    internal_function->attributes = NULL;
2978
25.9k
    internal_function->frameless_function_infos = ptr->frameless_function_infos;
2979
25.9k
    if (EG(active)) { // at run-time: this ought to only happen if registered with dl() or somehow temporarily at runtime
2980
0
      ZEND_MAP_PTR_INIT(internal_function->run_time_cache, zend_arena_calloc(&CG(arena), 1, zend_internal_run_time_cache_reserved_size()));
2981
25.9k
    } else {
2982
#ifdef ZTS
2983
      ZEND_MAP_PTR_NEW_STATIC(internal_function->run_time_cache);
2984
#else
2985
25.9k
      ZEND_MAP_PTR_INIT(internal_function->run_time_cache, NULL);
2986
25.9k
#endif
2987
25.9k
    }
2988
25.9k
    if (ptr->flags) {
2989
17.5k
      if (!(ptr->flags & ZEND_ACC_PPP_MASK)) {
2990
2.92k
        if (ptr->flags != ZEND_ACC_DEPRECATED && scope) {
2991
0
          zend_error(error_type, "Invalid access level for %s::%s() - access must be exactly one of public, protected or private", ZSTR_VAL(scope->name), ptr->fname);
2992
0
        }
2993
2.92k
        internal_function->fn_flags = ZEND_ACC_PUBLIC | ptr->flags;
2994
14.5k
      } else {
2995
14.5k
        internal_function->fn_flags = ptr->flags;
2996
14.5k
      }
2997
17.5k
    } else {
2998
8.46k
      internal_function->fn_flags = ZEND_ACC_PUBLIC;
2999
8.46k
    }
3000
3001
25.9k
    if (ptr->arg_info) {
3002
25.9k
      zend_internal_function_info *info = (zend_internal_function_info*)ptr->arg_info;
3003
25.9k
      internal_function->arg_info = (zend_internal_arg_info*)ptr->arg_info+1;
3004
25.9k
      internal_function->num_args = ptr->num_args;
3005
      /* Currently you cannot denote that the function can accept less arguments than num_args */
3006
25.9k
      if (info->required_num_args == (uintptr_t)-1) {
3007
0
        internal_function->required_num_args = ptr->num_args;
3008
25.9k
      } else {
3009
25.9k
        internal_function->required_num_args = info->required_num_args;
3010
25.9k
      }
3011
25.9k
      if (ZEND_ARG_SEND_MODE(info)) {
3012
0
        internal_function->fn_flags |= ZEND_ACC_RETURN_REFERENCE;
3013
0
      }
3014
25.9k
      if (ZEND_ARG_IS_VARIADIC(&ptr->arg_info[ptr->num_args])) {
3015
736
        internal_function->fn_flags |= ZEND_ACC_VARIADIC;
3016
        /* Don't count the variadic argument */
3017
736
        internal_function->num_args--;
3018
736
      }
3019
25.9k
      if (ZEND_TYPE_IS_SET(info->type)) {
3020
24.4k
        if (ZEND_TYPE_HAS_NAME(info->type)) {
3021
0
          const char *type_name = ZEND_TYPE_LITERAL_NAME(info->type);
3022
0
          if (!scope && (!strcasecmp(type_name, "self") || !strcasecmp(type_name, "parent"))) {
3023
0
            zend_error_noreturn(E_CORE_ERROR, "Cannot declare a return type of %s outside of a class scope", type_name);
3024
0
          }
3025
0
        }
3026
3027
24.4k
        internal_function->fn_flags |= ZEND_ACC_HAS_RETURN_TYPE;
3028
24.4k
      }
3029
25.9k
    } else {
3030
0
      zend_error(E_CORE_WARNING, "Missing arginfo for %s%s%s()",
3031
0
         scope ? ZSTR_VAL(scope->name) : "", scope ? "::" : "", ptr->fname);
3032
3033
0
      internal_function->arg_info = NULL;
3034
0
      internal_function->num_args = 0;
3035
0
      internal_function->required_num_args = 0;
3036
0
    }
3037
3038
    /* If not specified, add __toString() return type for compatibility with Stringable
3039
     * interface. */
3040
25.9k
    if (scope && zend_string_equals_literal_ci(internal_function->function_name, "__tostring") &&
3041
25.9k
        !(internal_function->fn_flags & ZEND_ACC_HAS_RETURN_TYPE)) {
3042
0
      zend_error(E_CORE_WARNING, "%s::__toString() implemented without string return type",
3043
0
        ZSTR_VAL(scope->name));
3044
0
      internal_function->arg_info = (zend_internal_arg_info *) arg_info_toString + 1;
3045
0
      internal_function->fn_flags |= ZEND_ACC_HAS_RETURN_TYPE;
3046
0
      internal_function->num_args = internal_function->required_num_args = 0;
3047
0
    }
3048
3049
3050
25.9k
    zend_set_function_arg_flags((zend_function*)internal_function);
3051
25.9k
    if (ptr->flags & ZEND_ACC_ABSTRACT) {
3052
720
      if (scope) {
3053
        /* This is a class that must be abstract itself. Here we set the check info. */
3054
720
        scope->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
3055
720
        if (!(scope->ce_flags & ZEND_ACC_INTERFACE)) {
3056
          /* Since the class is not an interface it needs to be declared as a abstract class. */
3057
          /* Since here we are handling internal functions only we can add the keyword flag. */
3058
          /* This time we set the flag for the keyword 'abstract'. */
3059
32
          scope->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;
3060
32
        }
3061
720
      }
3062
720
      if ((ptr->flags & ZEND_ACC_STATIC) && (!scope || !(scope->ce_flags & ZEND_ACC_INTERFACE))) {
3063
0
        zend_error(error_type, "Static function %s%s%s() cannot be abstract", scope ? ZSTR_VAL(scope->name) : "", scope ? "::" : "", ptr->fname);
3064
0
      }
3065
25.2k
    } else {
3066
25.2k
      if (scope && (scope->ce_flags & ZEND_ACC_INTERFACE)) {
3067
0
        zend_error(error_type, "Interface %s cannot contain non abstract method %s()", ZSTR_VAL(scope->name), ptr->fname);
3068
0
        return FAILURE;
3069
0
      }
3070
25.2k
      if (!internal_function->handler) {
3071
0
        zend_error(error_type, "Method %s%s%s() cannot be a NULL function", scope ? ZSTR_VAL(scope->name) : "", scope ? "::" : "", ptr->fname);
3072
0
        zend_unregister_functions(functions, count, target_function_table);
3073
0
        return FAILURE;
3074
0
      }
3075
25.2k
    }
3076
25.9k
    lowercase_name = zend_string_tolower_ex(internal_function->function_name, type == MODULE_PERSISTENT);
3077
25.9k
    lowercase_name = zend_new_interned_string(lowercase_name);
3078
25.9k
    reg_function = malloc(sizeof(zend_internal_function));
3079
25.9k
    memcpy(reg_function, &function, sizeof(zend_internal_function));
3080
25.9k
    if (zend_hash_add_ptr(target_function_table, lowercase_name, reg_function) == NULL) {
3081
0
      unload=1;
3082
0
      free(reg_function);
3083
0
      zend_string_release(lowercase_name);
3084
0
      break;
3085
0
    }
3086
25.9k
    if (reg_function->frameless_function_infos) {
3087
304
      const zend_frameless_function_info *flf_info = reg_function->frameless_function_infos;
3088
752
      while (flf_info->handler) {
3089
448
        if (zend_flf_count == zend_flf_capacity) {
3090
48
          if (!zend_flf_capacity) {
3091
16
            zend_flf_capacity = 8;
3092
32
          } else {
3093
32
            zend_flf_capacity *= 2;
3094
32
          }
3095
          /* +1 for NULL terminator */
3096
48
          zend_flf_handlers = realloc(zend_flf_handlers, (zend_flf_capacity + 1) * sizeof(void *));
3097
48
          zend_flf_functions = realloc(zend_flf_functions, (zend_flf_capacity + 1) * sizeof(zend_function *));
3098
48
        }
3099
448
        zend_flf_handlers[zend_flf_count] = flf_info->handler;
3100
448
        zend_flf_functions[zend_flf_count] = (zend_function *)reg_function;
3101
448
        zend_flf_count++;
3102
448
        flf_info++;
3103
448
      }
3104
304
      zend_flf_handlers[zend_flf_count] = NULL;
3105
304
      zend_flf_functions[zend_flf_count] = NULL;
3106
304
    }
3107
3108
    /* Get parameter count including variadic parameter. */
3109
25.9k
    uint32_t num_args = reg_function->num_args;
3110
25.9k
    if (reg_function->fn_flags & ZEND_ACC_VARIADIC) {
3111
736
      num_args++;
3112
736
    }
3113
3114
    /* If types of arguments have to be checked */
3115
25.9k
    if (reg_function->arg_info && num_args) {
3116
15.3k
      uint32_t i;
3117
43.2k
      for (i = 0; i < num_args; i++) {
3118
27.9k
        zend_internal_arg_info *arg_info = &reg_function->arg_info[i];
3119
27.9k
        ZEND_ASSERT(arg_info->name && "Parameter must have a name");
3120
27.9k
        if (ZEND_TYPE_IS_SET(arg_info->type)) {
3121
24.9k
            reg_function->fn_flags |= ZEND_ACC_HAS_TYPE_HINTS;
3122
24.9k
        }
3123
27.9k
#if ZEND_DEBUG
3124
48.5k
        for (uint32_t j = 0; j < i; j++) {
3125
20.6k
          if (!strcmp(arg_info->name, reg_function->arg_info[j].name)) {
3126
0
            zend_error_noreturn(E_CORE_ERROR,
3127
0
              "Duplicate parameter name $%s for function %s%s%s()", arg_info->name,
3128
0
              scope ? ZSTR_VAL(scope->name) : "", scope ? "::" : "", ptr->fname);
3129
0
          }
3130
20.6k
        }
3131
27.9k
#endif
3132
27.9k
      }
3133
15.3k
    }
3134
3135
    /* Rebuild arginfos if parameter/property types and/or a return type are used */
3136
25.9k
    if (reg_function->arg_info &&
3137
25.9k
        (reg_function->fn_flags & (ZEND_ACC_HAS_RETURN_TYPE|ZEND_ACC_HAS_TYPE_HINTS))) {
3138
      /* convert "const char*" class type names into "zend_string*" */
3139
25.6k
      uint32_t i;
3140
25.6k
      zend_internal_arg_info *arg_info = reg_function->arg_info - 1;
3141
25.6k
      zend_internal_arg_info *new_arg_info;
3142
3143
      /* Treat return type as an extra argument */
3144
25.6k
      num_args++;
3145
25.6k
      new_arg_info = malloc(sizeof(zend_internal_arg_info) * num_args);
3146
25.6k
      memcpy(new_arg_info, arg_info, sizeof(zend_internal_arg_info) * num_args);
3147
25.6k
      reg_function->arg_info = new_arg_info + 1;
3148
79.2k
      for (i = 0; i < num_args; i++) {
3149
53.5k
        if (ZEND_TYPE_HAS_LITERAL_NAME(new_arg_info[i].type)) {
3150
          // gen_stubs.php does not support codegen for DNF types in arg infos.
3151
          // As a temporary workaround, we split the type name on `|` characters,
3152
          // converting it to an union type if necessary.
3153
3.62k
          const char *class_name = ZEND_TYPE_LITERAL_NAME(new_arg_info[i].type);
3154
3.62k
          new_arg_info[i].type.type_mask &= ~_ZEND_TYPE_LITERAL_NAME_BIT;
3155
3156
3.62k
          size_t num_types = 1;
3157
3.62k
          const char *p = class_name;
3158
3.65k
          while ((p = strchr(p, '|'))) {
3159
32
            num_types++;
3160
32
            p++;
3161
32
          }
3162
3163
3.62k
          if (num_types == 1) {
3164
            /* Simple class type */
3165
3.58k
            zend_string *str = zend_string_init_interned(class_name, strlen(class_name), 1);
3166
3.58k
            zend_alloc_ce_cache(str);
3167
3.58k
            ZEND_TYPE_SET_PTR(new_arg_info[i].type, str);
3168
3.58k
            new_arg_info[i].type.type_mask |= _ZEND_TYPE_NAME_BIT;
3169
3.58k
          } else {
3170
            /* Union type */
3171
32
            zend_type_list *list = malloc(ZEND_TYPE_LIST_SIZE(num_types));
3172
32
            list->num_types = num_types;
3173
32
            ZEND_TYPE_SET_LIST(new_arg_info[i].type, list);
3174
32
            ZEND_TYPE_FULL_MASK(new_arg_info[i].type) |= _ZEND_TYPE_UNION_BIT;
3175
3176
32
            const char *start = class_name;
3177
32
            uint32_t j = 0;
3178
64
            while (true) {
3179
64
              const char *end = strchr(start, '|');
3180
64
              zend_string *str = zend_string_init_interned(start, end ? end - start : strlen(start), 1);
3181
64
              zend_alloc_ce_cache(str);
3182
64
              list->types[j] = (zend_type) ZEND_TYPE_INIT_CLASS(str, 0, 0);
3183
64
              if (!end) {
3184
32
                break;
3185
32
              }
3186
32
              start = end + 1;
3187
32
              j++;
3188
32
            }
3189
32
          }
3190
3.62k
        }
3191
53.5k
        if (ZEND_TYPE_IS_ITERABLE_FALLBACK(new_arg_info[i].type)) {
3192
          /* Warning generated an extension load warning which is emitted for every test
3193
          zend_error(E_CORE_WARNING, "iterable type is now a compile time alias for array|Traversable,"
3194
            " regenerate the argument info via the php-src gen_stub build script");
3195
          */
3196
0
          zend_type legacy_iterable = ZEND_TYPE_INIT_CLASS_MASK(
3197
0
            ZSTR_KNOWN(ZEND_STR_TRAVERSABLE),
3198
0
            (new_arg_info[i].type.type_mask | MAY_BE_ARRAY)
3199
0
          );
3200
0
          new_arg_info[i].type = legacy_iterable;
3201
0
        }
3202
3203
53.5k
        zend_normalize_internal_type(&new_arg_info[i].type);
3204
53.5k
      }
3205
25.6k
    }
3206
3207
25.9k
    if (scope) {
3208
14.5k
      zend_check_magic_method_implementation(
3209
14.5k
        scope, (zend_function *)reg_function, lowercase_name, E_CORE_ERROR);
3210
14.5k
      zend_add_magic_method(scope, (zend_function *)reg_function, lowercase_name);
3211
14.5k
    }
3212
25.9k
    ptr++;
3213
25.9k
    count++;
3214
25.9k
    zend_string_release(lowercase_name);
3215
25.9k
  }
3216
1.98k
  if (unload) { /* before unloading, display all remaining bad function in the module */
3217
0
    while (ptr->fname) {
3218
0
      fname_len = strlen(ptr->fname);
3219
0
      lowercase_name = zend_string_alloc(fname_len, 0);
3220
0
      zend_str_tolower_copy(ZSTR_VAL(lowercase_name), ptr->fname, fname_len);
3221
0
      if (zend_hash_exists(target_function_table, lowercase_name)) {
3222
0
        zend_error(error_type, "Function registration failed - duplicate name - %s%s%s", scope ? ZSTR_VAL(scope->name) : "", scope ? "::" : "", ptr->fname);
3223
0
      }
3224
0
      zend_string_efree(lowercase_name);
3225
0
      ptr++;
3226
0
    }
3227
0
    zend_unregister_functions(functions, count, target_function_table);
3228
0
    return FAILURE;
3229
0
  }
3230
1.98k
  return SUCCESS;
3231
1.98k
}
3232
/* }}} */
3233
3234
/* count=-1 means erase all functions, otherwise,
3235
 * erase the first count functions
3236
 */
3237
ZEND_API void zend_unregister_functions(const zend_function_entry *functions, int count, HashTable *function_table) /* {{{ */
3238
0
{
3239
0
  const zend_function_entry *ptr = functions;
3240
0
  int i=0;
3241
0
  HashTable *target_function_table = function_table;
3242
0
  zend_string *lowercase_name;
3243
0
  size_t fname_len;
3244
3245
0
  if (!target_function_table) {
3246
0
    target_function_table = CG(function_table);
3247
0
  }
3248
0
  while (ptr->fname) {
3249
0
    if (count!=-1 && i>=count) {
3250
0
      break;
3251
0
    }
3252
0
    fname_len = strlen(ptr->fname);
3253
0
    lowercase_name = zend_string_alloc(fname_len, 0);
3254
0
    zend_str_tolower_copy(ZSTR_VAL(lowercase_name), ptr->fname, fname_len);
3255
0
    zend_hash_del(target_function_table, lowercase_name);
3256
0
    zend_string_efree(lowercase_name);
3257
0
    ptr++;
3258
0
    i++;
3259
0
  }
3260
0
}
3261
/* }}} */
3262
3263
ZEND_API zend_result zend_startup_module(zend_module_entry *module) /* {{{ */
3264
4
{
3265
4
  if ((module = zend_register_internal_module(module)) != NULL && zend_startup_module_ex(module) == SUCCESS) {
3266
4
    return SUCCESS;
3267
4
  }
3268
0
  return FAILURE;
3269
4
}
3270
/* }}} */
3271
3272
ZEND_API zend_result zend_get_module_started(const char *module_name) /* {{{ */
3273
0
{
3274
0
  zend_module_entry *module;
3275
3276
0
  module = zend_hash_str_find_ptr(&module_registry, module_name, strlen(module_name));
3277
0
  return (module && module->module_started) ? SUCCESS : FAILURE;
3278
0
}
3279
/* }}} */
3280
3281
static void clean_module_classes(int module_number) /* {{{ */
3282
0
{
3283
  /* Child classes may reuse structures from parent classes, so destroy in reverse order. */
3284
0
  Bucket *bucket;
3285
0
  ZEND_HASH_REVERSE_FOREACH_BUCKET(EG(class_table), bucket) {
3286
0
    zend_class_entry *ce = Z_CE(bucket->val);
3287
0
    if (ce->type == ZEND_INTERNAL_CLASS && ce->info.internal.module->module_number == module_number) {
3288
0
      zend_hash_del_bucket(EG(class_table), bucket);
3289
0
    }
3290
0
  } ZEND_HASH_FOREACH_END();
3291
3292
0
}
3293
/* }}} */
3294
3295
static int clean_module_function(zval *el, void *arg) /* {{{ */
3296
0
{
3297
0
  zend_function *fe = (zend_function *) Z_PTR_P(el);
3298
0
  zend_module_entry *module = (zend_module_entry *) arg;
3299
0
  if (fe->common.type == ZEND_INTERNAL_FUNCTION && fe->internal_function.module == module) {
3300
0
    return ZEND_HASH_APPLY_REMOVE;
3301
0
  } else {
3302
0
    return ZEND_HASH_APPLY_KEEP;
3303
0
  }
3304
0
}
3305
/* }}} */
3306
3307
static void clean_module_functions(zend_module_entry *module) /* {{{ */
3308
0
{
3309
0
  zend_hash_apply_with_argument(CG(function_table), clean_module_function, module);
3310
0
}
3311
/* }}} */
3312
3313
void module_destructor(zend_module_entry *module) /* {{{ */
3314
0
{
3315
#if ZEND_RC_DEBUG
3316
  bool orig_rc_debug = zend_rc_debug;
3317
#endif
3318
3319
0
  if (module->type == MODULE_TEMPORARY) {
3320
#if ZEND_RC_DEBUG
3321
    /* FIXME: Loading extensions during the request breaks some invariants.
3322
     * In particular, it will create persistent interned strings, which is
3323
     * not allowed at this stage. */
3324
    zend_rc_debug = false;
3325
#endif
3326
0
    zend_clean_module_rsrc_dtors(module->module_number);
3327
0
    clean_module_constants(module->module_number);
3328
0
    clean_module_classes(module->module_number);
3329
0
  }
3330
3331
0
  if (module->module_started && module->module_shutdown_func) {
3332
#if 0
3333
    zend_printf("%s: Module shutdown\n", module->name);
3334
#endif
3335
0
    module->module_shutdown_func(module->type, module->module_number);
3336
0
  }
3337
3338
0
  if (module->module_started
3339
0
   && !module->module_shutdown_func
3340
0
   && module->type == MODULE_TEMPORARY) {
3341
0
    zend_unregister_ini_entries_ex(module->module_number, module->type);
3342
0
  }
3343
3344
  /* Deinitialize module globals */
3345
0
  if (module->globals_size) {
3346
#ifdef ZTS
3347
    if (*module->globals_id_ptr) {
3348
      ts_free_id(*module->globals_id_ptr);
3349
    }
3350
#else
3351
0
    if (module->globals_dtor) {
3352
0
      module->globals_dtor(module->globals_ptr);
3353
0
    }
3354
0
#endif
3355
0
  }
3356
3357
0
  module->module_started=0;
3358
0
  if (module->type == MODULE_TEMPORARY && module->functions) {
3359
0
    zend_unregister_functions(module->functions, -1, NULL);
3360
    /* Clean functions registered separately from module->functions */
3361
0
    clean_module_functions(module);
3362
0
  }
3363
3364
#if ZEND_RC_DEBUG
3365
  zend_rc_debug = orig_rc_debug;
3366
#endif
3367
0
}
3368
/* }}} */
3369
3370
void module_registry_unload(const zend_module_entry *module)
3371
0
{
3372
0
#ifdef HAVE_LIBDL
3373
0
  if (!getenv("ZEND_DONT_UNLOAD_MODULES")) {
3374
0
    DL_UNLOAD(module->handle);
3375
0
  }
3376
#else
3377
  ZEND_IGNORE_VALUE(module);
3378
#endif
3379
0
}
3380
3381
ZEND_API void zend_activate_modules(void) /* {{{ */
3382
300k
{
3383
300k
  zend_module_entry **p = module_request_startup_handlers;
3384
3385
2.50M
  while (*p) {
3386
2.20M
    zend_module_entry *module = *p;
3387
3388
2.20M
    if (module->request_startup_func(module->type, module->module_number)==FAILURE) {
3389
0
      zend_error(E_WARNING, "request_startup() for %s module failed", module->name);
3390
0
      exit(1);
3391
0
    }
3392
2.20M
    p++;
3393
2.20M
  }
3394
300k
}
3395
/* }}} */
3396
3397
ZEND_API void zend_deactivate_modules(void) /* {{{ */
3398
300k
{
3399
300k
  EG(current_execute_data) = NULL; /* we're no longer executing anything */
3400
3401
300k
  if (EG(full_tables_cleanup)) {
3402
0
    zend_module_entry *module;
3403
3404
0
    ZEND_HASH_MAP_REVERSE_FOREACH_PTR(&module_registry, module) {
3405
0
      if (module->request_shutdown_func) {
3406
0
        zend_try {
3407
0
          module->request_shutdown_func(module->type, module->module_number);
3408
0
        } zend_end_try();
3409
0
      }
3410
0
    } ZEND_HASH_FOREACH_END();
3411
300k
  } else {
3412
300k
    zend_module_entry **p = module_request_shutdown_handlers;
3413
3414
1.80M
    while (*p) {
3415
1.50M
      zend_module_entry *module = *p;
3416
1.50M
      zend_try {
3417
1.50M
        module->request_shutdown_func(module->type, module->module_number);
3418
1.50M
      } zend_end_try();
3419
1.50M
      p++;
3420
1.50M
    }
3421
300k
  }
3422
300k
}
3423
/* }}} */
3424
3425
void zend_unload_modules(void) /* {{{ */
3426
0
{
3427
0
  zend_module_entry **modules = modules_dl_loaded;
3428
0
  while (*modules) {
3429
0
    module_registry_unload(*modules);
3430
0
    modules++;
3431
0
  }
3432
0
  free(modules_dl_loaded);
3433
0
  modules_dl_loaded = NULL;
3434
0
}
3435
/* }}} */
3436
3437
ZEND_API void zend_post_deactivate_modules(void) /* {{{ */
3438
300k
{
3439
300k
  if (EG(full_tables_cleanup)) {
3440
0
    zend_module_entry *module;
3441
0
    zval *zv;
3442
0
    zend_string *key;
3443
3444
0
    ZEND_HASH_MAP_FOREACH_PTR(&module_registry, module) {
3445
0
      if (module->post_deactivate_func) {
3446
0
        module->post_deactivate_func();
3447
0
      }
3448
0
    } ZEND_HASH_FOREACH_END();
3449
0
    ZEND_HASH_MAP_REVERSE_FOREACH_STR_KEY_VAL(&module_registry, key, zv) {
3450
0
      module = Z_PTR_P(zv);
3451
0
      if (module->type != MODULE_TEMPORARY) {
3452
0
        break;
3453
0
      }
3454
0
      module_destructor(module);
3455
0
      if (module->handle) {
3456
0
        module_registry_unload(module);
3457
0
      }
3458
0
      zend_string_release_ex(key, 0);
3459
0
    } ZEND_HASH_MAP_FOREACH_END_DEL();
3460
300k
  } else {
3461
300k
    zend_module_entry **p = module_post_deactivate_handlers;
3462
3463
699k
    while (*p) {
3464
398k
      zend_module_entry *module = *p;
3465
3466
398k
      module->post_deactivate_func();
3467
398k
      p++;
3468
398k
    }
3469
300k
  }
3470
300k
}
3471
/* }}} */
3472
3473
/* return the next free module number */
3474
ZEND_API int zend_next_free_module(void) /* {{{ */
3475
196
{
3476
196
  return zend_hash_num_elements(&module_registry);
3477
196
}
3478
/* }}} */
3479
3480
static zend_class_entry *do_register_internal_class(zend_class_entry *orig_class_entry, uint32_t ce_flags) /* {{{ */
3481
2.59k
{
3482
2.59k
  zend_class_entry *class_entry = malloc(sizeof(zend_class_entry));
3483
2.59k
  zend_string *lowercase_name;
3484
2.59k
  *class_entry = *orig_class_entry;
3485
3486
2.59k
  class_entry->type = ZEND_INTERNAL_CLASS;
3487
2.59k
  zend_initialize_class_data(class_entry, 0);
3488
2.59k
  zend_alloc_ce_cache(class_entry->name);
3489
2.59k
  class_entry->ce_flags = orig_class_entry->ce_flags | ce_flags | ZEND_ACC_CONSTANTS_UPDATED | ZEND_ACC_LINKED | ZEND_ACC_RESOLVED_PARENT | ZEND_ACC_RESOLVED_INTERFACES;
3490
2.59k
  class_entry->info.internal.module = EG(current_module);
3491
3492
2.59k
  if (class_entry->info.internal.builtin_functions) {
3493
1.76k
    zend_register_functions(class_entry, class_entry->info.internal.builtin_functions, &class_entry->function_table, EG(current_module)->type);
3494
1.76k
  }
3495
3496
2.59k
  lowercase_name = zend_string_tolower_ex(orig_class_entry->name, EG(current_module)->type == MODULE_PERSISTENT);
3497
2.59k
  lowercase_name = zend_new_interned_string(lowercase_name);
3498
2.59k
  zend_hash_update_ptr(CG(class_table), lowercase_name, class_entry);
3499
2.59k
  zend_string_release_ex(lowercase_name, 1);
3500
3501
2.59k
  if (class_entry->__tostring && !zend_string_equals_literal(class_entry->name, "Stringable")
3502
2.59k
      && !(class_entry->ce_flags & ZEND_ACC_TRAIT)) {
3503
272
    ZEND_ASSERT(zend_ce_stringable
3504
272
      && "Should be registered before first class using __toString()");
3505
272
    zend_do_implement_interface(class_entry, zend_ce_stringable);
3506
272
  }
3507
2.59k
  return class_entry;
3508
2.59k
}
3509
/* }}} */
3510
3511
/* If parent_ce is not NULL then it inherits from parent_ce
3512
 * If parent_ce is NULL and parent_name isn't then it looks for the parent and inherits from it
3513
 * If both parent_ce and parent_name are NULL it does a regular class registration
3514
 * If parent_name is specified but not found NULL is returned
3515
 */
3516
ZEND_API zend_class_entry *zend_register_internal_class_ex(zend_class_entry *class_entry, zend_class_entry *parent_ce) /* {{{ */
3517
0
{
3518
0
  return zend_register_internal_class_with_flags(class_entry, parent_ce, 0);
3519
0
}
3520
/* }}} */
3521
3522
ZEND_API zend_class_entry *zend_register_internal_class_with_flags(
3523
  zend_class_entry *class_entry,
3524
  zend_class_entry *parent_ce,
3525
  uint32_t ce_flags
3526
2.19k
) {
3527
2.19k
  zend_class_entry *register_class = do_register_internal_class(class_entry, ce_flags);
3528
3529
2.19k
  if (parent_ce) {
3530
1.23k
    zend_do_inheritance(register_class, parent_ce);
3531
1.23k
    zend_build_properties_info_table(register_class);
3532
1.23k
  }
3533
3534
2.19k
  return register_class;
3535
2.19k
}
3536
3537
ZEND_API void zend_class_implements(zend_class_entry *class_entry, int num_interfaces, ...) /* {{{ */
3538
928
{
3539
928
  zend_class_entry *interface_entry;
3540
928
  va_list interface_list;
3541
928
  va_start(interface_list, num_interfaces);
3542
3543
2.20k
  while (num_interfaces--) {
3544
1.28k
    interface_entry = va_arg(interface_list, zend_class_entry *);
3545
1.28k
    if (interface_entry == zend_ce_stringable
3546
1.28k
        && zend_class_implements_interface(class_entry, zend_ce_stringable)) {
3547
      /* Stringable is implemented automatically,
3548
       * silently ignore an explicit implementation. */
3549
48
      continue;
3550
48
    }
3551
3552
1.23k
    zend_do_implement_interface(class_entry, interface_entry);
3553
1.23k
  }
3554
3555
928
  va_end(interface_list);
3556
928
}
3557
/* }}} */
3558
3559
/* A class that contains at least one abstract method automatically becomes an abstract class.
3560
 */
3561
ZEND_API zend_class_entry *zend_register_internal_class(zend_class_entry *orig_class_entry) /* {{{ */
3562
80
{
3563
80
  return do_register_internal_class(orig_class_entry, 0);
3564
80
}
3565
/* }}} */
3566
3567
ZEND_API zend_class_entry *zend_register_internal_interface(zend_class_entry *orig_class_entry) /* {{{ */
3568
320
{
3569
320
  return do_register_internal_class(orig_class_entry, ZEND_ACC_INTERFACE);
3570
320
}
3571
/* }}} */
3572
3573
ZEND_API zend_result zend_register_class_alias_ex(const char *name, size_t name_len, zend_class_entry *ce, bool persistent) /* {{{ */
3574
222
{
3575
222
  zend_string *lcname;
3576
222
  zval zv, *ret;
3577
3578
  /* TODO: Move this out of here in 7.4. */
3579
222
  if (persistent && EG(current_module) && EG(current_module)->type == MODULE_TEMPORARY) {
3580
0
    persistent = 0;
3581
0
  }
3582
3583
222
  if (name[0] == '\\') {
3584
0
    lcname = zend_string_alloc(name_len-1, persistent);
3585
0
    zend_str_tolower_copy(ZSTR_VAL(lcname), name+1, name_len-1);
3586
222
  } else {
3587
222
    lcname = zend_string_alloc(name_len, persistent);
3588
222
    zend_str_tolower_copy(ZSTR_VAL(lcname), name, name_len);
3589
222
  }
3590
3591
222
  zend_assert_valid_class_name(lcname, "a class alias");
3592
3593
222
  lcname = zend_new_interned_string(lcname);
3594
3595
  /* We cannot increase the refcount of an internal class during request time.
3596
   * Instead of having to deal with differentiating between class types and lifetimes,
3597
   * we simply don't increase the refcount of a class entry for aliases.
3598
   */
3599
222
  ZVAL_ALIAS_PTR(&zv, ce);
3600
3601
222
  ret = zend_hash_add(CG(class_table), lcname, &zv);
3602
222
  zend_string_release_ex(lcname, 0);
3603
222
  if (ret) {
3604
    // avoid notifying at MINIT time
3605
175
    if (ce->type == ZEND_USER_CLASS) {
3606
165
      zend_observer_class_linked_notify(ce, lcname);
3607
165
    }
3608
175
    return SUCCESS;
3609
175
  }
3610
47
  return FAILURE;
3611
222
}
3612
/* }}} */
3613
3614
// TODO num_symbol_tables as unsigned int?
3615
ZEND_API zend_result zend_set_hash_symbol(zval *symbol, const char *name, size_t name_length, bool is_ref, int num_symbol_tables, ...) /* {{{ */
3616
0
{
3617
0
  HashTable *symbol_table;
3618
0
  va_list symbol_table_list;
3619
3620
0
  if (num_symbol_tables <= 0) return FAILURE;
3621
3622
0
  if (is_ref) {
3623
0
    ZVAL_MAKE_REF(symbol);
3624
0
  }
3625
3626
0
  va_start(symbol_table_list, num_symbol_tables);
3627
0
  while (num_symbol_tables-- > 0) {
3628
0
    symbol_table = va_arg(symbol_table_list, HashTable *);
3629
0
    zend_hash_str_update(symbol_table, name, name_length, symbol);
3630
0
    Z_TRY_ADDREF_P(symbol);
3631
0
  }
3632
0
  va_end(symbol_table_list);
3633
0
  return SUCCESS;
3634
0
}
3635
/* }}} */
3636
3637
/* Disabled functions support */
3638
3639
static void zend_disable_function(const char *function_name, size_t function_name_length)
3640
560
{
3641
560
  if (UNEXPECTED(
3642
560
    (function_name_length == strlen("exit") && !memcmp(function_name, "exit", strlen("exit")))
3643
560
    || (function_name_length == strlen("die") && !memcmp(function_name, "die", strlen("die")))
3644
560
  )) {
3645
0
    zend_error(E_WARNING, "Cannot disable function %s()", function_name);
3646
0
    return;
3647
0
  }
3648
560
  zend_hash_str_del(CG(function_table), function_name, function_name_length);
3649
560
}
3650
3651
ZEND_API void zend_disable_functions(const char *function_list) /* {{{ */
3652
16
{
3653
16
  if (!function_list || !*function_list) {
3654
0
    return;
3655
0
  }
3656
3657
16
  const char *s = NULL, *e = function_list;
3658
5.05k
  while (*e) {
3659
5.04k
    switch (*e) {
3660
0
      case ' ':
3661
544
      case ',':
3662
544
        if (s) {
3663
544
          zend_disable_function(s, e - s);
3664
544
          s = NULL;
3665
544
        }
3666
544
        break;
3667
4.49k
      default:
3668
4.49k
        if (!s) {
3669
560
          s = e;
3670
560
        }
3671
4.49k
        break;
3672
5.04k
    }
3673
5.04k
    e++;
3674
5.04k
  }
3675
16
  if (s) {
3676
16
    zend_disable_function(s, e - s);
3677
16
  }
3678
3679
  /* Rehash the function table after deleting functions. This ensures that all internal
3680
   * functions are contiguous, which means we don't need to perform full table cleanup
3681
   * on shutdown. */
3682
16
  zend_hash_rehash(CG(function_table));
3683
16
}
3684
/* }}} */
3685
3686
#ifdef ZEND_WIN32
3687
#pragma optimize("", off)
3688
#endif
3689
static ZEND_COLD zend_object *display_disabled_class(zend_class_entry *class_type) /* {{{ */
3690
14
{
3691
14
  zend_object *intern;
3692
3693
14
  intern = zend_objects_new(class_type);
3694
3695
  /* Initialize default properties */
3696
14
  if (EXPECTED(class_type->default_properties_count != 0)) {
3697
0
    zval *p = intern->properties_table;
3698
0
    zval *end = p + class_type->default_properties_count;
3699
0
    do {
3700
0
      ZVAL_UNDEF(p);
3701
0
      p++;
3702
0
    } while (p != end);
3703
0
  }
3704
3705
14
  zend_error(E_WARNING, "%s() has been disabled for security reasons", ZSTR_VAL(class_type->name));
3706
14
  return intern;
3707
14
}
3708
#ifdef ZEND_WIN32
3709
#pragma optimize("", on)
3710
#endif
3711
/* }}} */
3712
3713
static const zend_function_entry disabled_class_new[] = {
3714
  ZEND_FE_END
3715
};
3716
3717
ZEND_API zend_result zend_disable_class(const char *class_name, size_t class_name_length) /* {{{ */
3718
16
{
3719
16
  zend_class_entry *disabled_class;
3720
16
  zend_string *key;
3721
16
  zend_function *fn;
3722
16
  zend_property_info *prop;
3723
3724
16
  key = zend_string_alloc(class_name_length, 0);
3725
16
  zend_str_tolower_copy(ZSTR_VAL(key), class_name, class_name_length);
3726
16
  disabled_class = zend_hash_find_ptr(CG(class_table), key);
3727
16
  zend_string_release_ex(key, 0);
3728
16
  if (!disabled_class) {
3729
0
    return FAILURE;
3730
0
  }
3731
3732
  /* Will be reset by INIT_CLASS_ENTRY. */
3733
16
  free(disabled_class->interfaces);
3734
3735
16
  INIT_CLASS_ENTRY_INIT_METHODS((*disabled_class), disabled_class_new);
3736
16
  disabled_class->create_object = display_disabled_class;
3737
3738
256
  ZEND_HASH_MAP_FOREACH_PTR(&disabled_class->function_table, fn) {
3739
256
    if ((fn->common.fn_flags & (ZEND_ACC_HAS_RETURN_TYPE|ZEND_ACC_HAS_TYPE_HINTS)) &&
3740
112
      fn->common.scope == disabled_class) {
3741
32
      zend_free_internal_arg_info(&fn->internal_function);
3742
32
    }
3743
256
  } ZEND_HASH_FOREACH_END();
3744
16
  zend_hash_clean(&disabled_class->function_table);
3745
32
  ZEND_HASH_MAP_FOREACH_PTR(&disabled_class->properties_info, prop) {
3746
32
    if (prop->ce == disabled_class) {
3747
0
      zend_string_release(prop->name);
3748
0
      zend_type_release(prop->type, /* persistent */ 1);
3749
0
      free(prop);
3750
0
    }
3751
32
  } ZEND_HASH_FOREACH_END();
3752
16
  zend_hash_clean(&disabled_class->properties_info);
3753
16
  return SUCCESS;
3754
16
}
3755
/* }}} */
3756
3757
static zend_always_inline zend_class_entry *get_scope(zend_execute_data *frame)
3758
3.35k
{
3759
3.35k
  return frame && frame->func ? frame->func->common.scope : NULL;
3760
3.35k
}
3761
3762
static bool zend_is_callable_check_class(zend_string *name, zend_class_entry *scope, zend_execute_data *frame, zend_fcall_info_cache *fcc, bool *strict_class, char **error, bool suppress_deprecation) /* {{{ */
3763
1.64k
{
3764
1.64k
  bool ret = 0;
3765
1.64k
  zend_class_entry *ce;
3766
1.64k
  size_t name_len = ZSTR_LEN(name);
3767
1.64k
  zend_string *lcname;
3768
1.64k
  ALLOCA_FLAG(use_heap);
3769
3770
1.64k
  ZSTR_ALLOCA_ALLOC(lcname, name_len, use_heap);
3771
1.64k
  zend_str_tolower_copy(ZSTR_VAL(lcname), ZSTR_VAL(name), name_len);
3772
3773
1.64k
  *strict_class = 0;
3774
1.64k
  if (zend_string_equals(lcname, ZSTR_KNOWN(ZEND_STR_SELF))) {
3775
235
    if (!scope) {
3776
7
      if (error) *error = estrdup("cannot access \"self\" when no class scope is active");
3777
228
    } else {
3778
228
      if (!suppress_deprecation) {
3779
104
        zend_error(E_DEPRECATED, "Use of \"self\" in callables is deprecated");
3780
104
      }
3781
228
      fcc->called_scope = zend_get_called_scope(frame);
3782
228
      if (!fcc->called_scope || !instanceof_function(fcc->called_scope, scope)) {
3783
0
        fcc->called_scope = scope;
3784
0
      }
3785
228
      fcc->calling_scope = scope;
3786
228
      if (!fcc->object) {
3787
123
        fcc->object = zend_get_this_object(frame);
3788
123
      }
3789
228
      ret = 1;
3790
228
    }
3791
1.40k
  } else if (zend_string_equals(lcname, ZSTR_KNOWN(ZEND_STR_PARENT))) {
3792
288
    if (!scope) {
3793
0
      if (error) *error = estrdup("cannot access \"parent\" when no class scope is active");
3794
288
    } else if (!scope->parent) {
3795
5
      if (error) *error = estrdup("cannot access \"parent\" when current class scope has no parent");
3796
283
    } else {
3797
283
      if (!suppress_deprecation) {
3798
134
        zend_error(E_DEPRECATED, "Use of \"parent\" in callables is deprecated");
3799
134
      }
3800
283
      fcc->called_scope = zend_get_called_scope(frame);
3801
283
      if (!fcc->called_scope || !instanceof_function(fcc->called_scope, scope->parent)) {
3802
10
        fcc->called_scope = scope->parent;
3803
10
      }
3804
283
      fcc->calling_scope = scope->parent;
3805
283
      if (!fcc->object) {
3806
158
        fcc->object = zend_get_this_object(frame);
3807
158
      }
3808
283
      *strict_class = 1;
3809
283
      ret = 1;
3810
283
    }
3811
1.12k
  } else if (zend_string_equals(lcname, ZSTR_KNOWN(ZEND_STR_STATIC))) {
3812
245
    zend_class_entry *called_scope = zend_get_called_scope(frame);
3813
3814
245
    if (!called_scope) {
3815
0
      if (error) *error = estrdup("cannot access \"static\" when no class scope is active");
3816
245
    } else {
3817
245
      if (!suppress_deprecation) {
3818
142
        zend_error(E_DEPRECATED, "Use of \"static\" in callables is deprecated");
3819
142
      }
3820
245
      fcc->called_scope = called_scope;
3821
245
      fcc->calling_scope = called_scope;
3822
245
      if (!fcc->object) {
3823
156
        fcc->object = zend_get_this_object(frame);
3824
156
      }
3825
245
      *strict_class = 1;
3826
245
      ret = 1;
3827
245
    }
3828
875
  } else if ((ce = zend_lookup_class(name)) != NULL) {
3829
673
    zend_class_entry *scope = get_scope(frame);
3830
673
    fcc->calling_scope = ce;
3831
673
    if (scope && !fcc->object) {
3832
317
      zend_object *object = zend_get_this_object(frame);
3833
3834
317
      if (object &&
3835
317
          instanceof_function(object->ce, scope) &&
3836
317
          instanceof_function(scope, ce)) {
3837
252
        fcc->object = object;
3838
252
        fcc->called_scope = object->ce;
3839
252
      } else {
3840
65
        fcc->called_scope = ce;
3841
65
      }
3842
356
    } else {
3843
356
      fcc->called_scope = fcc->object ? fcc->object->ce : ce;
3844
356
    }
3845
673
    *strict_class = 1;
3846
673
    ret = 1;
3847
673
  } else {
3848
202
    if (error) zend_spprintf(error, 0, "class \"%.*s\" not found", (int)name_len, ZSTR_VAL(name));
3849
202
  }
3850
1.64k
  ZSTR_ALLOCA_FREE(lcname, use_heap);
3851
1.64k
  return ret;
3852
1.64k
}
3853
/* }}} */
3854
3855
19.1k
ZEND_API void zend_release_fcall_info_cache(zend_fcall_info_cache *fcc) {
3856
19.1k
  if (fcc->function_handler &&
3857
19.1k
    (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
3858
237
    if (fcc->function_handler->common.function_name) {
3859
237
      zend_string_release_ex(fcc->function_handler->common.function_name, 0);
3860
237
    }
3861
237
    zend_free_trampoline(fcc->function_handler);
3862
237
    fcc->function_handler = NULL;
3863
237
  }
3864
19.1k
}
3865
3866
static zend_always_inline bool zend_is_callable_check_func(zval *callable, zend_execute_data *frame, zend_fcall_info_cache *fcc, bool strict_class, char **error, bool suppress_deprecation) /* {{{ */
3867
104k
{
3868
104k
  zend_class_entry *ce_org = fcc->calling_scope;
3869
104k
  bool retval = 0;
3870
104k
  zend_string *mname, *cname;
3871
104k
  zend_string *lmname;
3872
104k
  const char *colon;
3873
104k
  size_t clen;
3874
104k
  HashTable *ftable;
3875
104k
  int call_via_handler = 0;
3876
104k
  zend_class_entry *scope;
3877
104k
  zval *zv;
3878
104k
  ALLOCA_FLAG(use_heap)
3879
3880
104k
  fcc->calling_scope = NULL;
3881
3882
104k
  if (!ce_org) {
3883
95.5k
    zend_function *func;
3884
95.5k
    zend_string *lmname;
3885
3886
    /* Check if function with given name exists.
3887
     * This may be a compound name that includes namespace name */
3888
95.5k
    if (UNEXPECTED(Z_STRVAL_P(callable)[0] == '\\')) {
3889
      /* Skip leading \ */
3890
55
      ZSTR_ALLOCA_ALLOC(lmname, Z_STRLEN_P(callable) - 1, use_heap);
3891
55
      zend_str_tolower_copy(ZSTR_VAL(lmname), Z_STRVAL_P(callable) + 1, Z_STRLEN_P(callable) - 1);
3892
55
      func = zend_fetch_function(lmname);
3893
55
      ZSTR_ALLOCA_FREE(lmname, use_heap);
3894
95.5k
    } else {
3895
95.5k
      lmname = Z_STR_P(callable);
3896
95.5k
      func = zend_fetch_function(lmname);
3897
95.5k
      if (!func) {
3898
2.03k
        ZSTR_ALLOCA_ALLOC(lmname, Z_STRLEN_P(callable), use_heap);
3899
2.03k
        zend_str_tolower_copy(ZSTR_VAL(lmname), Z_STRVAL_P(callable), Z_STRLEN_P(callable));
3900
2.03k
        func = zend_fetch_function(lmname);
3901
2.03k
        ZSTR_ALLOCA_FREE(lmname, use_heap);
3902
2.03k
      }
3903
95.5k
    }
3904
95.5k
    if (EXPECTED(func != NULL)) {
3905
93.9k
      fcc->function_handler = func;
3906
93.9k
      return 1;
3907
93.9k
    }
3908
95.5k
  }
3909
3910
  /* Split name into class/namespace and method/function names */
3911
10.7k
  if ((colon = zend_memrchr(Z_STRVAL_P(callable), ':', Z_STRLEN_P(callable))) != NULL &&
3912
10.7k
    colon > Z_STRVAL_P(callable) &&
3913
10.7k
    *(colon-1) == ':'
3914
10.7k
  ) {
3915
1.82k
    size_t mlen;
3916
3917
1.82k
    colon--;
3918
1.82k
    clen = colon - Z_STRVAL_P(callable);
3919
1.82k
    mlen = Z_STRLEN_P(callable) - clen - 2;
3920
3921
1.82k
    if (colon == Z_STRVAL_P(callable)) {
3922
0
      if (error) *error = estrdup("invalid function name");
3923
0
      return 0;
3924
0
    }
3925
3926
    /* This is a compound name.
3927
     * Try to fetch class and then find static method. */
3928
1.82k
    if (ce_org) {
3929
423
      scope = ce_org;
3930
1.39k
    } else {
3931
1.39k
      scope = get_scope(frame);
3932
1.39k
    }
3933
3934
1.82k
    cname = zend_string_init_interned(Z_STRVAL_P(callable), clen, 0);
3935
1.82k
    if (ZSTR_HAS_CE_CACHE(cname) && ZSTR_GET_CE_CACHE(cname)) {
3936
1.14k
      fcc->calling_scope = ZSTR_GET_CE_CACHE(cname);
3937
1.14k
      if (scope && !fcc->object) {
3938
885
        zend_object *object = zend_get_this_object(frame);
3939
3940
885
        if (object &&
3941
885
            instanceof_function(object->ce, scope) &&
3942
885
            instanceof_function(scope, fcc->calling_scope)) {
3943
831
          fcc->object = object;
3944
831
          fcc->called_scope = object->ce;
3945
831
        } else {
3946
54
          fcc->called_scope = fcc->calling_scope;
3947
54
        }
3948
885
      } else {
3949
261
        fcc->called_scope = fcc->object ? fcc->object->ce : fcc->calling_scope;
3950
261
      }
3951
1.14k
      strict_class = 1;
3952
1.14k
    } else if (!zend_is_callable_check_class(cname, scope, frame, fcc, &strict_class, error, suppress_deprecation || ce_org != NULL)) {
3953
105
      zend_string_release_ex(cname, 0);
3954
105
      return 0;
3955
105
    }
3956
1.71k
    zend_string_release_ex(cname, 0);
3957
3958
1.71k
    ftable = &fcc->calling_scope->function_table;
3959
1.71k
    if (ce_org && !instanceof_function(ce_org, fcc->calling_scope)) {
3960
0
      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));
3961
0
      return 0;
3962
0
    }
3963
1.71k
    if (ce_org && !suppress_deprecation) {
3964
367
      zend_error(E_DEPRECATED,
3965
367
        "Callables of the form [\"%s\", \"%s\"] are deprecated",
3966
367
        ZSTR_VAL(ce_org->name), Z_STRVAL_P(callable));
3967
367
    }
3968
1.71k
    mname = zend_string_init(Z_STRVAL_P(callable) + clen + 2, mlen, 0);
3969
8.95k
  } else if (ce_org) {
3970
    /* Try to fetch find static method of given class. */
3971
8.72k
    mname = Z_STR_P(callable);
3972
8.72k
    zend_string_addref(mname);
3973
8.72k
    ftable = &ce_org->function_table;
3974
8.72k
    fcc->calling_scope = ce_org;
3975
8.72k
  } else {
3976
    /* We already checked for plain function before. */
3977
227
    if (error) {
3978
96
      zend_spprintf(error, 0, "function \"%s\" not found or invalid function name", Z_STRVAL_P(callable));
3979
96
    }
3980
227
    return 0;
3981
227
  }
3982
3983
10.4k
  lmname = zend_string_tolower(mname);
3984
10.4k
  if (strict_class &&
3985
10.4k
      fcc->calling_scope &&
3986
10.4k
    zend_string_equals_literal(lmname, ZEND_CONSTRUCTOR_FUNC_NAME)) {
3987
802
    fcc->function_handler = fcc->calling_scope->constructor;
3988
802
    if (fcc->function_handler) {
3989
802
      retval = 1;
3990
802
    }
3991
9.63k
  } else if ((zv = zend_hash_find(ftable, lmname)) != NULL) {
3992
8.48k
    fcc->function_handler = Z_PTR_P(zv);
3993
8.48k
    retval = 1;
3994
8.48k
    if ((fcc->function_handler->op_array.fn_flags & ZEND_ACC_CHANGED) &&
3995
8.48k
        !strict_class) {
3996
13
      scope = get_scope(frame);
3997
13
      if (scope &&
3998
13
          instanceof_function(fcc->function_handler->common.scope, scope)) {
3999
4000
13
        zv = zend_hash_find(&scope->function_table, lmname);
4001
13
        if (zv != NULL) {
4002
13
          zend_function *priv_fbc = Z_PTR_P(zv);
4003
4004
13
          if ((priv_fbc->common.fn_flags & ZEND_ACC_PRIVATE)
4005
13
           && priv_fbc->common.scope == scope) {
4006
13
            fcc->function_handler = priv_fbc;
4007
13
          }
4008
13
        }
4009
13
      }
4010
13
    }
4011
8.48k
    if (!(fcc->function_handler->common.fn_flags & ZEND_ACC_PUBLIC) &&
4012
8.48k
        (fcc->calling_scope &&
4013
284
         ((fcc->object && fcc->calling_scope->__call) ||
4014
284
          (!fcc->object && fcc->calling_scope->__callstatic)))) {
4015
33
      scope = get_scope(frame);
4016
33
      if (fcc->function_handler->common.scope != scope) {
4017
20
        if ((fcc->function_handler->common.fn_flags & ZEND_ACC_PRIVATE)
4018
20
         || !zend_check_protected(zend_get_function_root_class(fcc->function_handler), scope)) {
4019
10
          retval = 0;
4020
10
          fcc->function_handler = NULL;
4021
10
          goto get_function_via_handler;
4022
10
        }
4023
20
      }
4024
33
    }
4025
8.48k
  } else {
4026
1.16k
get_function_via_handler:
4027
1.16k
    if (fcc->object && fcc->calling_scope == ce_org) {
4028
1.00k
      if (strict_class && ce_org->__call) {
4029
15
        fcc->function_handler = zend_get_call_trampoline_func(ce_org, mname, 0);
4030
15
        call_via_handler = 1;
4031
15
        retval = 1;
4032
994
      } else {
4033
994
        fcc->function_handler = fcc->object->handlers->get_method(&fcc->object, mname, NULL);
4034
994
        if (fcc->function_handler) {
4035
867
          if (strict_class &&
4036
867
              (!fcc->function_handler->common.scope ||
4037
10
               !instanceof_function(ce_org, fcc->function_handler->common.scope))) {
4038
10
            zend_release_fcall_info_cache(fcc);
4039
857
          } else {
4040
857
            retval = 1;
4041
857
            call_via_handler = (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) != 0;
4042
857
          }
4043
867
        }
4044
994
      }
4045
1.00k
    } else if (fcc->calling_scope) {
4046
154
      if (fcc->calling_scope->get_static_method) {
4047
0
        fcc->function_handler = fcc->calling_scope->get_static_method(fcc->calling_scope, mname);
4048
154
      } else {
4049
154
        fcc->function_handler = zend_std_get_static_method(fcc->calling_scope, mname, NULL);
4050
154
      }
4051
154
      if (fcc->function_handler) {
4052
80
        retval = 1;
4053
80
        call_via_handler = (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) != 0;
4054
80
        if (call_via_handler && !fcc->object) {
4055
61
          zend_object *object = zend_get_this_object(frame);
4056
61
          if (object &&
4057
61
              instanceof_function(object->ce, fcc->calling_scope)) {
4058
12
            fcc->object = object;
4059
12
          }
4060
61
        }
4061
80
      }
4062
154
    }
4063
1.16k
  }
4064
4065
10.4k
  if (retval) {
4066
10.2k
    if (fcc->calling_scope && !call_via_handler) {
4067
9.27k
      if (fcc->function_handler->common.fn_flags & ZEND_ACC_ABSTRACT) {
4068
41
        retval = 0;
4069
41
        if (error) {
4070
0
          zend_spprintf(error, 0, "cannot call abstract method %s::%s()", ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(fcc->function_handler->common.function_name));
4071
0
        }
4072
9.23k
      } else if (!fcc->object && !(fcc->function_handler->common.fn_flags & ZEND_ACC_STATIC)) {
4073
17
        retval = 0;
4074
17
        if (error) {
4075
5
          zend_spprintf(error, 0, "non-static method %s::%s() cannot be called statically", ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(fcc->function_handler->common.function_name));
4076
5
        }
4077
17
      }
4078
9.27k
      if (retval
4079
9.27k
       && !(fcc->function_handler->common.fn_flags & ZEND_ACC_PUBLIC)) {
4080
269
        scope = get_scope(frame);
4081
269
        if (fcc->function_handler->common.scope != scope) {
4082
147
          if ((fcc->function_handler->common.fn_flags & ZEND_ACC_PRIVATE)
4083
147
           || (!zend_check_protected(zend_get_function_root_class(fcc->function_handler), scope))) {
4084
112
            if (error) {
4085
18
              if (*error) {
4086
0
                efree(*error);
4087
0
              }
4088
18
              zend_spprintf(error, 0, "cannot access %s method %s::%s()", zend_visibility_string(fcc->function_handler->common.fn_flags), ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(fcc->function_handler->common.function_name));
4089
18
            }
4090
112
            retval = 0;
4091
112
          }
4092
147
        }
4093
269
      }
4094
9.27k
    }
4095
10.2k
  } else if (error) {
4096
43
    if (fcc->calling_scope) {
4097
43
      zend_spprintf(error, 0, "class %s does not have a method \"%s\"", ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(mname));
4098
43
    } else {
4099
0
      zend_spprintf(error, 0, "function %s() does not exist", ZSTR_VAL(mname));
4100
0
    }
4101
43
  }
4102
10.4k
  zend_string_release_ex(lmname, 0);
4103
10.4k
  zend_string_release_ex(mname, 0);
4104
4105
10.4k
  if (fcc->object) {
4106
9.67k
    fcc->called_scope = fcc->object->ce;
4107
9.67k
    if (fcc->function_handler
4108
9.67k
     && (fcc->function_handler->common.fn_flags & ZEND_ACC_STATIC)) {
4109
70
      fcc->object = NULL;
4110
70
    }
4111
9.67k
  }
4112
10.4k
  return retval;
4113
10.4k
}
4114
/* }}} */
4115
4116
ZEND_API zend_string *zend_get_callable_name_ex(zval *callable, zend_object *object) /* {{{ */
4117
112
{
4118
112
try_again:
4119
112
  switch (Z_TYPE_P(callable)) {
4120
7
    case IS_STRING:
4121
7
      if (object) {
4122
0
        return zend_create_member_string(object->ce->name, Z_STR_P(callable));
4123
0
      }
4124
7
      return zend_string_copy(Z_STR_P(callable));
4125
4126
20
    case IS_ARRAY:
4127
20
    {
4128
20
      zval *method = NULL;
4129
20
      zval *obj = NULL;
4130
4131
20
      if (zend_hash_num_elements(Z_ARRVAL_P(callable)) == 2) {
4132
20
        obj = zend_hash_index_find_deref(Z_ARRVAL_P(callable), 0);
4133
20
        method = zend_hash_index_find_deref(Z_ARRVAL_P(callable), 1);
4134
20
      }
4135
4136
20
      if (obj == NULL || method == NULL || Z_TYPE_P(method) != IS_STRING) {
4137
0
        return ZSTR_KNOWN(ZEND_STR_ARRAY_CAPITALIZED);
4138
0
      }
4139
4140
20
      if (Z_TYPE_P(obj) == IS_STRING) {
4141
0
        return zend_create_member_string(Z_STR_P(obj), Z_STR_P(method));
4142
20
      } else if (Z_TYPE_P(obj) == IS_OBJECT) {
4143
20
        return zend_create_member_string(Z_OBJCE_P(obj)->name, Z_STR_P(method));
4144
20
      } else {
4145
0
        return ZSTR_KNOWN(ZEND_STR_ARRAY_CAPITALIZED);
4146
0
      }
4147
20
    }
4148
85
    case IS_OBJECT:
4149
85
    {
4150
85
      zend_class_entry *ce = Z_OBJCE_P(callable);
4151
4152
85
      if (ce == zend_ce_closure) {
4153
73
        const zend_function *fn = zend_get_closure_method_def(Z_OBJ_P(callable));
4154
4155
73
        if (fn->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) {
4156
15
          if (fn->common.scope) {
4157
10
            return zend_create_member_string(fn->common.scope->name, fn->common.function_name);
4158
10
          } else {
4159
5
            return zend_string_copy(fn->common.function_name);
4160
5
          }
4161
15
        }
4162
73
      }
4163
4164
70
      return zend_string_concat2(
4165
70
        ZSTR_VAL(ce->name), ZSTR_LEN(ce->name),
4166
70
        "::__invoke", sizeof("::__invoke") - 1);
4167
85
    }
4168
0
    case IS_REFERENCE:
4169
0
      callable = Z_REFVAL_P(callable);
4170
0
      goto try_again;
4171
0
    default:
4172
0
      return zval_get_string_func(callable);
4173
112
  }
4174
112
}
4175
/* }}} */
4176
4177
ZEND_API zend_string *zend_get_callable_name(zval *callable) /* {{{ */
4178
0
{
4179
0
  return zend_get_callable_name_ex(callable, NULL);
4180
0
}
4181
/* }}} */
4182
4183
ZEND_API bool zend_is_callable_at_frame(
4184
    zval *callable, zend_object *object, zend_execute_data *frame,
4185
    uint32_t check_flags, zend_fcall_info_cache *fcc, char **error) /* {{{ */
4186
119k
{
4187
119k
  bool ret;
4188
119k
  zend_fcall_info_cache fcc_local;
4189
119k
  bool strict_class = 0;
4190
4191
119k
  if (fcc == NULL) {
4192
9.28k
    fcc = &fcc_local;
4193
9.28k
  }
4194
119k
  if (error) {
4195
109k
    *error = NULL;
4196
109k
  }
4197
4198
119k
  fcc->calling_scope = NULL;
4199
119k
  fcc->called_scope = NULL;
4200
119k
  fcc->function_handler = NULL;
4201
119k
  fcc->object = NULL;
4202
119k
  fcc->closure = NULL;
4203
4204
119k
again:
4205
119k
  switch (Z_TYPE_P(callable)) {
4206
101k
    case IS_STRING:
4207
101k
      if (object) {
4208
5.72k
        fcc->object = object;
4209
5.72k
        fcc->calling_scope = object->ce;
4210
5.72k
      }
4211
4212
101k
      if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) {
4213
0
        fcc->called_scope = fcc->calling_scope;
4214
0
        return 1;
4215
0
      }
4216
4217
104k
check_func:
4218
104k
      ret = zend_is_callable_check_func(callable, frame, fcc, strict_class, error, check_flags & IS_CALLABLE_SUPPRESS_DEPRECATIONS);
4219
104k
      if (fcc == &fcc_local) {
4220
3.13k
        zend_release_fcall_info_cache(fcc);
4221
3.13k
      }
4222
104k
      return ret;
4223
4224
3.58k
    case IS_ARRAY:
4225
3.58k
      {
4226
3.58k
        if (zend_hash_num_elements(Z_ARRVAL_P(callable)) != 2) {
4227
8
          if (error) *error = estrdup("array callback must have exactly two members");
4228
8
          return 0;
4229
8
        }
4230
4231
3.58k
        zval *obj = zend_hash_index_find(Z_ARRVAL_P(callable), 0);
4232
3.58k
        zval *method = zend_hash_index_find(Z_ARRVAL_P(callable), 1);
4233
3.58k
        if (!obj || !method) {
4234
0
          if (error) *error = estrdup("array callback has to contain indices 0 and 1");
4235
0
          return 0;
4236
0
        }
4237
4238
3.58k
        ZVAL_DEREF(obj);
4239
3.58k
        if (Z_TYPE_P(obj) != IS_STRING && Z_TYPE_P(obj) != IS_OBJECT) {
4240
35
          if (error) *error = estrdup("first array member is not a valid class name or object");
4241
35
          return 0;
4242
35
        }
4243
4244
3.54k
        ZVAL_DEREF(method);
4245
3.54k
        if (Z_TYPE_P(method) != IS_STRING) {
4246
2
          if (error) *error = estrdup("second array member is not a valid method");
4247
2
          return 0;
4248
2
        }
4249
4250
3.54k
        if (Z_TYPE_P(obj) == IS_STRING) {
4251
967
          if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) {
4252
0
            return 1;
4253
0
          }
4254
4255
967
          if (!zend_is_callable_check_class(Z_STR_P(obj), get_scope(frame), frame, fcc, &strict_class, error, check_flags & IS_CALLABLE_SUPPRESS_DEPRECATIONS)) {
4256
109
            return 0;
4257
109
          }
4258
2.57k
        } else {
4259
2.57k
          ZEND_ASSERT(Z_TYPE_P(obj) == IS_OBJECT);
4260
2.57k
          fcc->calling_scope = Z_OBJCE_P(obj); /* TBFixed: what if it's overloaded? */
4261
2.57k
          fcc->object = Z_OBJ_P(obj);
4262
4263
2.57k
          if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) {
4264
10
            fcc->called_scope = fcc->calling_scope;
4265
10
            return 1;
4266
10
          }
4267
2.57k
        }
4268
4269
3.42k
        callable = method;
4270
3.42k
        goto check_func;
4271
3.54k
      }
4272
0
      return 0;
4273
14.7k
    case IS_OBJECT:
4274
14.7k
      if (Z_OBJ_HANDLER_P(callable, get_closure) && Z_OBJ_HANDLER_P(callable, get_closure)(Z_OBJ_P(callable), &fcc->calling_scope, &fcc->function_handler, &fcc->object, 1) == SUCCESS) {
4275
14.7k
        fcc->called_scope = fcc->calling_scope;
4276
14.7k
        fcc->closure = Z_OBJ_P(callable);
4277
14.7k
        if (fcc == &fcc_local) {
4278
6.05k
          zend_release_fcall_info_cache(fcc);
4279
6.05k
        }
4280
14.7k
        return 1;
4281
14.7k
      }
4282
5
      if (error) *error = estrdup("no array or string given");
4283
5
      return 0;
4284
5
    case IS_REFERENCE:
4285
5
      callable = Z_REFVAL_P(callable);
4286
5
      goto again;
4287
50
    default:
4288
50
      if (error) *error = estrdup("no array or string given");
4289
50
      return 0;
4290
119k
  }
4291
119k
}
4292
/* }}} */
4293
4294
ZEND_API 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) /* {{{ */
4295
119k
{
4296
  /* Determine callability at the first parent user frame. */
4297
119k
  zend_execute_data *frame = EG(current_execute_data);
4298
146k
  while (frame && (!frame->func || !ZEND_USER_CODE(frame->func->type))) {
4299
26.7k
    frame = frame->prev_execute_data;
4300
26.7k
  }
4301
4302
119k
  bool ret = zend_is_callable_at_frame(callable, object, frame, check_flags, fcc, error);
4303
119k
  if (callable_name) {
4304
105
    *callable_name = zend_get_callable_name_ex(callable, object);
4305
105
  }
4306
119k
  return ret;
4307
119k
}
4308
4309
ZEND_API bool zend_is_callable(zval *callable, uint32_t check_flags, zend_string **callable_name) /* {{{ */
4310
8.66k
{
4311
8.66k
  return zend_is_callable_ex(callable, NULL, check_flags, callable_name, NULL, NULL);
4312
8.66k
}
4313
/* }}} */
4314
4315
ZEND_API bool zend_make_callable(zval *callable, zend_string **callable_name) /* {{{ */
4316
0
{
4317
0
  zend_fcall_info_cache fcc;
4318
4319
0
  if (zend_is_callable_ex(callable, NULL, IS_CALLABLE_SUPPRESS_DEPRECATIONS, callable_name, &fcc, NULL)) {
4320
0
    if (Z_TYPE_P(callable) == IS_STRING && fcc.calling_scope) {
4321
0
      zval_ptr_dtor_str(callable);
4322
0
      array_init(callable);
4323
0
      add_next_index_str(callable, zend_string_copy(fcc.calling_scope->name));
4324
0
      add_next_index_str(callable, zend_string_copy(fcc.function_handler->common.function_name));
4325
0
    }
4326
0
    zend_release_fcall_info_cache(&fcc);
4327
0
    return 1;
4328
0
  }
4329
0
  return 0;
4330
0
}
4331
/* }}} */
4332
4333
ZEND_API zend_result 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) /* {{{ */
4334
7.66k
{
4335
7.66k
  if (!zend_is_callable_ex(callable, NULL, check_flags, callable_name, fcc, error)) {
4336
120
    return FAILURE;
4337
120
  }
4338
4339
7.54k
  fci->size = sizeof(*fci);
4340
7.54k
  fci->object = fcc->object;
4341
7.54k
  ZVAL_COPY_VALUE(&fci->function_name, callable);
4342
7.54k
  fci->retval = NULL;
4343
7.54k
  fci->param_count = 0;
4344
7.54k
  fci->params = NULL;
4345
7.54k
  fci->named_params = NULL;
4346
4347
7.54k
  return SUCCESS;
4348
7.66k
}
4349
/* }}} */
4350
4351
ZEND_API void zend_fcall_info_args_clear(zend_fcall_info *fci, bool free_mem) /* {{{ */
4352
0
{
4353
0
  if (fci->params) {
4354
0
    zval *p = fci->params;
4355
0
    zval *end = p + fci->param_count;
4356
4357
0
    while (p != end) {
4358
0
      i_zval_ptr_dtor(p);
4359
0
      p++;
4360
0
    }
4361
0
    if (free_mem) {
4362
0
      efree(fci->params);
4363
0
      fci->params = NULL;
4364
0
    }
4365
0
  }
4366
0
  fci->param_count = 0;
4367
0
}
4368
/* }}} */
4369
4370
ZEND_API void zend_fcall_info_args_save(zend_fcall_info *fci, uint32_t *param_count, zval **params) /* {{{ */
4371
0
{
4372
0
  *param_count = fci->param_count;
4373
0
  *params = fci->params;
4374
0
  fci->param_count = 0;
4375
0
  fci->params = NULL;
4376
0
}
4377
/* }}} */
4378
4379
ZEND_API void zend_fcall_info_args_restore(zend_fcall_info *fci, uint32_t param_count, zval *params) /* {{{ */
4380
0
{
4381
0
  zend_fcall_info_args_clear(fci, 1);
4382
0
  fci->param_count = param_count;
4383
0
  fci->params = params;
4384
0
}
4385
/* }}} */
4386
4387
ZEND_API zend_result zend_fcall_info_args_ex(zend_fcall_info *fci, zend_function *func, zval *args) /* {{{ */
4388
0
{
4389
0
  zval *arg, *params;
4390
0
  uint32_t n = 1;
4391
4392
0
  zend_fcall_info_args_clear(fci, !args);
4393
4394
0
  if (!args) {
4395
0
    return SUCCESS;
4396
0
  }
4397
4398
0
  if (Z_TYPE_P(args) != IS_ARRAY) {
4399
0
    return FAILURE;
4400
0
  }
4401
4402
0
  fci->param_count = zend_hash_num_elements(Z_ARRVAL_P(args));
4403
0
  fci->params = params = (zval *) erealloc(fci->params, fci->param_count * sizeof(zval));
4404
4405
0
  ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(args), arg) {
4406
0
    if (func && !Z_ISREF_P(arg) && ARG_SHOULD_BE_SENT_BY_REF(func, n)) {
4407
0
      ZVAL_NEW_REF(params, arg);
4408
0
      Z_TRY_ADDREF_P(arg);
4409
0
    } else {
4410
0
      ZVAL_COPY(params, arg);
4411
0
    }
4412
0
    params++;
4413
0
    n++;
4414
0
  } ZEND_HASH_FOREACH_END();
4415
4416
0
  return SUCCESS;
4417
0
}
4418
/* }}} */
4419
4420
ZEND_API zend_result zend_fcall_info_args(zend_fcall_info *fci, zval *args) /* {{{ */
4421
0
{
4422
0
  return zend_fcall_info_args_ex(fci, NULL, args);
4423
0
}
4424
/* }}} */
4425
4426
ZEND_API void zend_fcall_info_argp(zend_fcall_info *fci, uint32_t argc, zval *argv) /* {{{ */
4427
0
{
4428
0
  zend_fcall_info_args_clear(fci, !argc);
4429
4430
0
  if (argc) {
4431
0
    fci->param_count = argc;
4432
0
    fci->params = (zval *) erealloc(fci->params, fci->param_count * sizeof(zval));
4433
4434
0
    for (uint32_t i = 0; i < argc; ++i) {
4435
0
      ZVAL_COPY(&fci->params[i], &argv[i]);
4436
0
    }
4437
0
  }
4438
0
}
4439
/* }}} */
4440
4441
ZEND_API void zend_fcall_info_argv(zend_fcall_info *fci, uint32_t argc, va_list *argv) /* {{{ */
4442
0
{
4443
0
  zend_fcall_info_args_clear(fci, !argc);
4444
4445
0
  if (argc) {
4446
0
    zval *arg;
4447
0
    fci->param_count = argc;
4448
0
    fci->params = (zval *) erealloc(fci->params, fci->param_count * sizeof(zval));
4449
4450
0
    for (uint32_t i = 0; i < argc; ++i) {
4451
0
      arg = va_arg(*argv, zval *);
4452
0
      ZVAL_COPY(&fci->params[i], arg);
4453
0
    }
4454
0
  }
4455
0
}
4456
/* }}} */
4457
4458
ZEND_API void zend_fcall_info_argn(zend_fcall_info *fci, uint32_t argc, ...) /* {{{ */
4459
0
{
4460
0
  va_list argv;
4461
4462
0
  va_start(argv, argc);
4463
0
  zend_fcall_info_argv(fci, argc, &argv);
4464
0
  va_end(argv);
4465
0
}
4466
/* }}} */
4467
4468
ZEND_API zend_result zend_fcall_info_call(zend_fcall_info *fci, zend_fcall_info_cache *fcc, zval *retval_ptr, zval *args) /* {{{ */
4469
0
{
4470
0
  zval retval, *org_params = NULL;
4471
0
  uint32_t org_count = 0;
4472
0
  zend_result result;
4473
4474
0
  fci->retval = retval_ptr ? retval_ptr : &retval;
4475
0
  if (args) {
4476
0
    zend_fcall_info_args_save(fci, &org_count, &org_params);
4477
0
    zend_fcall_info_args(fci, args);
4478
0
  }
4479
0
  result = zend_call_function(fci, fcc);
4480
4481
0
  if (!retval_ptr && Z_TYPE(retval) != IS_UNDEF) {
4482
0
    zval_ptr_dtor(&retval);
4483
0
  }
4484
0
  if (args) {
4485
0
    zend_fcall_info_args_restore(fci, org_count, org_params);
4486
0
  }
4487
0
  return result;
4488
0
}
4489
/* }}} */
4490
4491
ZEND_API void zend_get_callable_zval_from_fcc(const zend_fcall_info_cache *fcc, zval *callable)
4492
0
{
4493
0
  if (fcc->closure) {
4494
0
    ZVAL_OBJ_COPY(callable, fcc->closure);
4495
0
  } else if (fcc->function_handler->common.scope) {
4496
0
    array_init(callable);
4497
0
    if (fcc->object) {
4498
0
      GC_ADDREF(fcc->object);
4499
0
      add_next_index_object(callable, fcc->object);
4500
0
    } else {
4501
0
      add_next_index_str(callable, zend_string_copy(fcc->calling_scope->name));
4502
0
    }
4503
0
    add_next_index_str(callable, zend_string_copy(fcc->function_handler->common.function_name));
4504
0
  } else {
4505
0
    ZVAL_STR_COPY(callable, fcc->function_handler->common.function_name);
4506
0
  }
4507
0
}
4508
4509
ZEND_API const char *zend_get_module_version(const char *module_name) /* {{{ */
4510
0
{
4511
0
  zend_string *lname;
4512
0
  size_t name_len = strlen(module_name);
4513
0
  zend_module_entry *module;
4514
4515
0
  lname = zend_string_alloc(name_len, 0);
4516
0
  zend_str_tolower_copy(ZSTR_VAL(lname), module_name, name_len);
4517
0
  module = zend_hash_find_ptr(&module_registry, lname);
4518
0
  zend_string_efree(lname);
4519
0
  return module ? module->version : NULL;
4520
0
}
4521
/* }}} */
4522
4523
35.2k
static zend_always_inline bool is_persistent_class(zend_class_entry *ce) {
4524
35.2k
  return (ce->type & ZEND_INTERNAL_CLASS)
4525
35.2k
    && ce->info.internal.module->type == MODULE_PERSISTENT;
4526
35.2k
}
4527
4528
ZEND_API zend_property_info *zend_declare_typed_property(zend_class_entry *ce, zend_string *name, zval *property, int access_type, zend_string *doc_comment, zend_type type) /* {{{ */
4529
30.4k
{
4530
30.4k
  zend_property_info *property_info, *property_info_ptr;
4531
4532
30.4k
  if (ZEND_TYPE_IS_SET(type)) {
4533
17.4k
    ce->ce_flags |= ZEND_ACC_HAS_TYPE_HINTS;
4534
4535
17.4k
    if (access_type & ZEND_ACC_READONLY) {
4536
7.17k
      ce->ce_flags |= ZEND_ACC_HAS_READONLY_PROPS;
4537
7.17k
    }
4538
17.4k
  }
4539
4540
30.4k
  if (ce->type == ZEND_INTERNAL_CLASS) {
4541
960
    property_info = pemalloc(sizeof(zend_property_info), 1);
4542
29.4k
  } else {
4543
29.4k
    property_info = zend_arena_alloc(&CG(arena), sizeof(zend_property_info));
4544
29.4k
    if (Z_TYPE_P(property) == IS_CONSTANT_AST) {
4545
1.79k
      ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
4546
1.79k
      if (access_type & ZEND_ACC_STATIC) {
4547
767
        ce->ce_flags |= ZEND_ACC_HAS_AST_STATICS;
4548
1.02k
      } else {
4549
1.02k
        ce->ce_flags |= ZEND_ACC_HAS_AST_PROPERTIES;
4550
1.02k
      }
4551
1.79k
    }
4552
29.4k
  }
4553
4554
30.4k
  if (Z_TYPE_P(property) == IS_STRING && !ZSTR_IS_INTERNED(Z_STR_P(property))) {
4555
1.96k
    zval_make_interned_string(property);
4556
1.96k
  }
4557
4558
30.4k
  if (!(access_type & ZEND_ACC_PPP_MASK)) {
4559
2.08k
    access_type |= ZEND_ACC_PUBLIC;
4560
2.08k
  }
4561
  /* Add the protected(set) bit for public readonly properties with no set visibility. */
4562
30.4k
  if ((access_type & (ZEND_ACC_PUBLIC|ZEND_ACC_READONLY|ZEND_ACC_PPP_SET_MASK)) == (ZEND_ACC_PUBLIC|ZEND_ACC_READONLY)) {
4563
7.08k
    access_type |= ZEND_ACC_PROTECTED_SET;
4564
23.3k
  } else if (UNEXPECTED(access_type & ZEND_ACC_PPP_SET_MASK)) {
4565
747
    if (!ZEND_TYPE_IS_SET(type)) {
4566
14
      zend_error_noreturn(ce->type == ZEND_INTERNAL_CLASS ? E_CORE_ERROR : E_COMPILE_ERROR,
4567
14
        "Property with asymmetric visibility %s::$%s must have type",
4568
14
        ZSTR_VAL(ce->name), ZSTR_VAL(name));
4569
14
    }
4570
733
    uint32_t get_visibility = zend_visibility_to_set_visibility(access_type & ZEND_ACC_PPP_MASK);
4571
733
    uint32_t set_visibility = access_type & ZEND_ACC_PPP_SET_MASK;
4572
733
    if (get_visibility > set_visibility) {
4573
11
      zend_error_noreturn(ce->type == ZEND_INTERNAL_CLASS ? E_CORE_ERROR : E_COMPILE_ERROR,
4574
11
        "Visibility of property %s::$%s must not be weaker than set visibility",
4575
11
        ZSTR_VAL(ce->name), ZSTR_VAL(name));
4576
11
    }
4577
    /* Remove equivalent set visibility. */
4578
722
    if (((access_type & (ZEND_ACC_PUBLIC|ZEND_ACC_PUBLIC_SET)) == (ZEND_ACC_PUBLIC|ZEND_ACC_PUBLIC_SET))
4579
722
     || ((access_type & (ZEND_ACC_PROTECTED|ZEND_ACC_PROTECTED_SET)) == (ZEND_ACC_PROTECTED|ZEND_ACC_PROTECTED_SET))
4580
722
     || ((access_type & (ZEND_ACC_PRIVATE|ZEND_ACC_PRIVATE_SET)) == (ZEND_ACC_PRIVATE|ZEND_ACC_PRIVATE_SET))) {
4581
263
      access_type &= ~ZEND_ACC_PPP_SET_MASK;
4582
263
    }
4583
    /* private(set) properties are implicitly final. */
4584
722
    if (access_type & ZEND_ACC_PRIVATE_SET) {
4585
290
      access_type |= ZEND_ACC_FINAL;
4586
290
    }
4587
722
  }
4588
4589
  /* Virtual properties have no backing storage, the offset should never be used. However, the
4590
   * virtual flag cannot be definitively determined at compile time. Allow using default values
4591
   * anyway, and assert after inheritance that the property is not actually virtual. */
4592
30.4k
  if (access_type & ZEND_ACC_VIRTUAL) {
4593
3.89k
    if (Z_TYPE_P(property) == IS_UNDEF) {
4594
3.66k
      property_info->offset = (uint32_t)-1;
4595
3.66k
      goto skip_property_storage;
4596
3.66k
    }
4597
3.89k
  }
4598
26.7k
  if (access_type & ZEND_ACC_STATIC) {
4599
4.24k
    if ((property_info_ptr = zend_hash_find_ptr(&ce->properties_info, name)) != NULL) {
4600
4
      ZEND_ASSERT(property_info_ptr->flags & ZEND_ACC_STATIC);
4601
4
      property_info->offset = property_info_ptr->offset;
4602
4
      zval_ptr_dtor(&ce->default_static_members_table[property_info->offset]);
4603
4
      if (property_info_ptr->doc_comment && property_info_ptr->ce == ce) {
4604
4
        zend_string_release(property_info_ptr->doc_comment);
4605
4
      }
4606
4
      zend_hash_del(&ce->properties_info, name);
4607
4.24k
    } else {
4608
4.24k
      property_info->offset = ce->default_static_members_count++;
4609
4.24k
      ce->default_static_members_table = perealloc(ce->default_static_members_table, sizeof(zval) * ce->default_static_members_count, ce->type == ZEND_INTERNAL_CLASS);
4610
4.24k
    }
4611
4.24k
    ZVAL_COPY_VALUE(&ce->default_static_members_table[property_info->offset], property);
4612
4.24k
    if (!ZEND_MAP_PTR(ce->static_members_table)) {
4613
4.24k
      if (ce->type == ZEND_INTERNAL_CLASS &&
4614
4.24k
          ce->info.internal.module->type == MODULE_PERSISTENT) {
4615
0
        ZEND_MAP_PTR_NEW(ce->static_members_table);
4616
0
      }
4617
4.24k
    }
4618
22.4k
  } else {
4619
22.4k
    zval *property_default_ptr;
4620
22.4k
    if ((property_info_ptr = zend_hash_find_ptr(&ce->properties_info, name)) != NULL) {
4621
0
      ZEND_ASSERT(!(property_info_ptr->flags & ZEND_ACC_STATIC));
4622
0
      property_info->offset = property_info_ptr->offset;
4623
0
      zval_ptr_dtor(&ce->default_properties_table[OBJ_PROP_TO_NUM(property_info->offset)]);
4624
0
      if (property_info_ptr->doc_comment && property_info_ptr->ce == ce) {
4625
0
        zend_string_release_ex(property_info_ptr->doc_comment, 1);
4626
0
      }
4627
0
      zend_hash_del(&ce->properties_info, name);
4628
4629
0
      ZEND_ASSERT(ce->type == ZEND_INTERNAL_CLASS);
4630
0
      ZEND_ASSERT(ce->properties_info_table != NULL);
4631
0
      ce->properties_info_table[OBJ_PROP_TO_NUM(property_info->offset)] = property_info;
4632
22.4k
    } else {
4633
22.4k
      property_info->offset = OBJ_PROP_TO_OFFSET(ce->default_properties_count);
4634
22.4k
      ce->default_properties_count++;
4635
22.4k
      ce->default_properties_table = perealloc(ce->default_properties_table, sizeof(zval) * ce->default_properties_count, ce->type == ZEND_INTERNAL_CLASS);
4636
4637
      /* For user classes this is handled during linking */
4638
22.4k
      if (ce->type == ZEND_INTERNAL_CLASS) {
4639
848
        ce->properties_info_table = perealloc(ce->properties_info_table, sizeof(zend_property_info *) * ce->default_properties_count, 1);
4640
848
        ce->properties_info_table[ce->default_properties_count - 1] = property_info;
4641
848
      }
4642
22.4k
    }
4643
22.4k
    property_default_ptr = &ce->default_properties_table[OBJ_PROP_TO_NUM(property_info->offset)];
4644
22.4k
    ZVAL_COPY_VALUE(property_default_ptr, property);
4645
22.4k
    Z_PROP_FLAG_P(property_default_ptr) = Z_ISUNDEF_P(property) ? IS_PROP_UNINIT : 0;
4646
22.4k
  }
4647
30.4k
skip_property_storage:
4648
30.4k
  if (ce->type & ZEND_INTERNAL_CLASS) {
4649
    /* Must be interned to avoid ZTS data races */
4650
960
    if (is_persistent_class(ce)) {
4651
960
      name = zend_new_interned_string(zend_string_copy(name));
4652
960
    }
4653
4654
960
    if (Z_REFCOUNTED_P(property)) {
4655
0
      zend_error_noreturn(E_CORE_ERROR, "Internal zvals cannot be refcounted");
4656
0
    }
4657
960
  }
4658
4659
30.4k
  if (access_type & ZEND_ACC_PUBLIC) {
4660
26.5k
    property_info->name = zend_string_copy(name);
4661
26.5k
  } else if (access_type & ZEND_ACC_PRIVATE) {
4662
2.61k
    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));
4663
2.61k
  } else {
4664
1.26k
    ZEND_ASSERT(access_type & ZEND_ACC_PROTECTED);
4665
1.26k
    property_info->name = zend_mangle_property_name("*", 1, ZSTR_VAL(name), ZSTR_LEN(name), is_persistent_class(ce));
4666
1.26k
  }
4667
4668
30.4k
  property_info->name = zend_new_interned_string(property_info->name);
4669
30.4k
  property_info->flags = access_type;
4670
30.4k
  property_info->doc_comment = doc_comment;
4671
30.4k
  property_info->attributes = NULL;
4672
30.4k
  property_info->prototype = property_info;
4673
30.4k
  property_info->hooks = NULL;
4674
30.4k
  property_info->ce = ce;
4675
30.4k
  property_info->type = type;
4676
4677
30.4k
  if (is_persistent_class(ce)) {
4678
960
    zend_normalize_internal_type(&property_info->type);
4679
960
  }
4680
4681
30.4k
  zend_hash_update_ptr(&ce->properties_info, name, property_info);
4682
4683
30.4k
  return property_info;
4684
30.4k
}
4685
/* }}} */
4686
4687
ZEND_API zend_result zend_try_assign_typed_ref_ex(zend_reference *ref, zval *val, bool strict) /* {{{ */
4688
12
{
4689
12
  if (UNEXPECTED(!zend_verify_ref_assignable_zval(ref, val, strict))) {
4690
2
    zval_ptr_dtor(val);
4691
2
    return FAILURE;
4692
10
  } else {
4693
10
    zend_safe_assign_to_variable_noref(&ref->val, val);
4694
10
    return SUCCESS;
4695
10
  }
4696
12
}
4697
/* }}} */
4698
4699
ZEND_API zend_result zend_try_assign_typed_ref(zend_reference *ref, zval *val) /* {{{ */
4700
12
{
4701
12
  return zend_try_assign_typed_ref_ex(ref, val, ZEND_ARG_USES_STRICT_TYPES());
4702
12
}
4703
/* }}} */
4704
4705
ZEND_API zend_result zend_try_assign_typed_ref_null(zend_reference *ref) /* {{{ */
4706
0
{
4707
0
  zval tmp;
4708
4709
0
  ZVAL_NULL(&tmp);
4710
0
  return zend_try_assign_typed_ref(ref, &tmp);
4711
0
}
4712
/* }}} */
4713
4714
ZEND_API zend_result zend_try_assign_typed_ref_bool(zend_reference *ref, bool val) /* {{{ */
4715
0
{
4716
0
  zval tmp;
4717
4718
0
  ZVAL_BOOL(&tmp, val);
4719
0
  return zend_try_assign_typed_ref(ref, &tmp);
4720
0
}
4721
/* }}} */
4722
4723
ZEND_API zend_result zend_try_assign_typed_ref_long(zend_reference *ref, zend_long lval) /* {{{ */
4724
0
{
4725
0
  zval tmp;
4726
4727
0
  ZVAL_LONG(&tmp, lval);
4728
0
  return zend_try_assign_typed_ref(ref, &tmp);
4729
0
}
4730
/* }}} */
4731
4732
ZEND_API zend_result zend_try_assign_typed_ref_double(zend_reference *ref, double dval) /* {{{ */
4733
0
{
4734
0
  zval tmp;
4735
4736
0
  ZVAL_DOUBLE(&tmp, dval);
4737
0
  return zend_try_assign_typed_ref(ref, &tmp);
4738
0
}
4739
/* }}} */
4740
4741
ZEND_API zend_result zend_try_assign_typed_ref_empty_string(zend_reference *ref) /* {{{ */
4742
0
{
4743
0
  zval tmp;
4744
4745
0
  ZVAL_EMPTY_STRING(&tmp);
4746
0
  return zend_try_assign_typed_ref(ref, &tmp);
4747
0
}
4748
/* }}} */
4749
4750
ZEND_API zend_result zend_try_assign_typed_ref_str(zend_reference *ref, zend_string *str) /* {{{ */
4751
0
{
4752
0
  zval tmp;
4753
4754
0
  ZVAL_STR(&tmp, str);
4755
0
  return zend_try_assign_typed_ref(ref, &tmp);
4756
0
}
4757
/* }}} */
4758
4759
ZEND_API zend_result zend_try_assign_typed_ref_string(zend_reference *ref, const char *string) /* {{{ */
4760
7
{
4761
7
  zval tmp;
4762
4763
7
  ZVAL_STRING(&tmp, string);
4764
7
  return zend_try_assign_typed_ref(ref, &tmp);
4765
7
}
4766
/* }}} */
4767
4768
ZEND_API zend_result zend_try_assign_typed_ref_stringl(zend_reference *ref, const char *string, size_t len) /* {{{ */
4769
0
{
4770
0
  zval tmp;
4771
4772
0
  ZVAL_STRINGL(&tmp, string, len);
4773
0
  return zend_try_assign_typed_ref(ref, &tmp);
4774
0
}
4775
/* }}} */
4776
4777
ZEND_API zend_result zend_try_assign_typed_ref_arr(zend_reference *ref, zend_array *arr) /* {{{ */
4778
5
{
4779
5
  zval tmp;
4780
4781
5
  ZVAL_ARR(&tmp, arr);
4782
5
  return zend_try_assign_typed_ref(ref, &tmp);
4783
5
}
4784
/* }}} */
4785
4786
ZEND_API zend_result zend_try_assign_typed_ref_res(zend_reference *ref, zend_resource *res) /* {{{ */
4787
0
{
4788
0
  zval tmp;
4789
4790
0
  ZVAL_RES(&tmp, res);
4791
0
  return zend_try_assign_typed_ref(ref, &tmp);
4792
0
}
4793
/* }}} */
4794
4795
ZEND_API zend_result zend_try_assign_typed_ref_zval(zend_reference *ref, zval *zv) /* {{{ */
4796
0
{
4797
0
  zval tmp;
4798
4799
0
  ZVAL_COPY_VALUE(&tmp, zv);
4800
0
  return zend_try_assign_typed_ref(ref, &tmp);
4801
0
}
4802
/* }}} */
4803
4804
ZEND_API zend_result zend_try_assign_typed_ref_zval_ex(zend_reference *ref, zval *zv, bool strict) /* {{{ */
4805
0
{
4806
0
  zval tmp;
4807
4808
0
  ZVAL_COPY_VALUE(&tmp, zv);
4809
0
  return zend_try_assign_typed_ref_ex(ref, &tmp, strict);
4810
0
}
4811
/* }}} */
4812
4813
ZEND_API void zend_declare_property_ex(zend_class_entry *ce, zend_string *name, zval *property, int access_type, zend_string *doc_comment) /* {{{ */
4814
0
{
4815
0
  zend_declare_typed_property(ce, name, property, access_type, doc_comment, (zend_type) ZEND_TYPE_INIT_NONE(0));
4816
0
}
4817
/* }}} */
4818
4819
ZEND_API void zend_declare_property(zend_class_entry *ce, const char *name, size_t name_length, zval *property, int access_type) /* {{{ */
4820
0
{
4821
0
  zend_string *key = zend_string_init(name, name_length, is_persistent_class(ce));
4822
0
  zend_declare_property_ex(ce, key, property, access_type, NULL);
4823
0
  zend_string_release(key);
4824
0
}
4825
/* }}} */
4826
4827
ZEND_API void zend_declare_property_null(zend_class_entry *ce, const char *name, size_t name_length, int access_type) /* {{{ */
4828
0
{
4829
0
  zval property;
4830
4831
0
  ZVAL_NULL(&property);
4832
0
  zend_declare_property(ce, name, name_length, &property, access_type);
4833
0
}
4834
/* }}} */
4835
4836
ZEND_API void zend_declare_property_bool(zend_class_entry *ce, const char *name, size_t name_length, zend_long value, int access_type) /* {{{ */
4837
0
{
4838
0
  zval property;
4839
4840
0
  ZVAL_BOOL(&property, value);
4841
0
  zend_declare_property(ce, name, name_length, &property, access_type);
4842
0
}
4843
/* }}} */
4844
4845
ZEND_API void zend_declare_property_long(zend_class_entry *ce, const char *name, size_t name_length, zend_long value, int access_type) /* {{{ */
4846
0
{
4847
0
  zval property;
4848
4849
0
  ZVAL_LONG(&property, value);
4850
0
  zend_declare_property(ce, name, name_length, &property, access_type);
4851
0
}
4852
/* }}} */
4853
4854
ZEND_API void zend_declare_property_double(zend_class_entry *ce, const char *name, size_t name_length, double value, int access_type) /* {{{ */
4855
0
{
4856
0
  zval property;
4857
4858
0
  ZVAL_DOUBLE(&property, value);
4859
0
  zend_declare_property(ce, name, name_length, &property, access_type);
4860
0
}
4861
/* }}} */
4862
4863
ZEND_API void zend_declare_property_string(zend_class_entry *ce, const char *name, size_t name_length, const char *value, int access_type) /* {{{ */
4864
0
{
4865
0
  zval property;
4866
4867
0
  ZVAL_NEW_STR(&property, zend_string_init(value, strlen(value), ce->type & ZEND_INTERNAL_CLASS));
4868
0
  zend_declare_property(ce, name, name_length, &property, access_type);
4869
0
}
4870
/* }}} */
4871
4872
ZEND_API void 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) /* {{{ */
4873
0
{
4874
0
  zval property;
4875
4876
0
  ZVAL_NEW_STR(&property, zend_string_init(value, value_len, ce->type & ZEND_INTERNAL_CLASS));
4877
0
  zend_declare_property(ce, name, name_length, &property, access_type);
4878
0
}
4879
/* }}} */
4880
4881
ZEND_API zend_class_constant *zend_declare_typed_class_constant(zend_class_entry *ce, zend_string *name, zval *value, int flags, zend_string *doc_comment, zend_type type) /* {{{ */
4882
10.1k
{
4883
10.1k
  zend_class_constant *c;
4884
4885
10.1k
  if (ce->ce_flags & ZEND_ACC_INTERFACE) {
4886
455
    if (!(flags & ZEND_ACC_PUBLIC)) {
4887
1
      zend_error_noreturn(E_COMPILE_ERROR, "Access type for interface constant %s::%s must be public", ZSTR_VAL(ce->name), ZSTR_VAL(name));
4888
1
    }
4889
455
  }
4890
4891
10.1k
  if (zend_string_equals_ci(name, ZSTR_KNOWN(ZEND_STR_CLASS))) {
4892
6
    zend_error_noreturn(ce->type == ZEND_INTERNAL_CLASS ? E_CORE_ERROR : E_COMPILE_ERROR,
4893
6
        "A class constant must not be called 'class'; it is reserved for class name fetching");
4894
6
  }
4895
4896
10.1k
  if (Z_TYPE_P(value) == IS_STRING && !ZSTR_IS_INTERNED(Z_STR_P(value))) {
4897
1.61k
    zval_make_interned_string(value);
4898
1.61k
  }
4899
4900
10.1k
  if (ce->type == ZEND_INTERNAL_CLASS) {
4901
2.70k
    c = pemalloc(sizeof(zend_class_constant), 1);
4902
2.70k
    if (ZEND_TYPE_PURE_MASK(type) != MAY_BE_ANY) {
4903
2.70k
      ZEND_ASSERT(!ZEND_TYPE_CONTAINS_CODE(type, IS_RESOURCE) && "resource is not allowed in a zend_type");
4904
2.70k
    }
4905
7.44k
  } else {
4906
7.44k
    c = zend_arena_alloc(&CG(arena), sizeof(zend_class_constant));
4907
7.44k
  }
4908
10.1k
  ZVAL_COPY_VALUE(&c->value, value);
4909
10.1k
  ZEND_CLASS_CONST_FLAGS(c) = flags;
4910
10.1k
  c->doc_comment = doc_comment;
4911
10.1k
  c->attributes = NULL;
4912
10.1k
  c->ce = ce;
4913
10.1k
  c->type = type;
4914
4915
10.1k
  if (Z_TYPE_P(value) == IS_CONSTANT_AST) {
4916
4.48k
    ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
4917
4.48k
    ce->ce_flags |= ZEND_ACC_HAS_AST_CONSTANTS;
4918
4.48k
    if (ce->type == ZEND_INTERNAL_CLASS && !ZEND_MAP_PTR(ce->mutable_data)) {
4919
80
      ZEND_MAP_PTR_NEW(ce->mutable_data);
4920
80
    }
4921
4.48k
  }
4922
4923
10.1k
  if (!zend_hash_add_ptr(&ce->constants_table, name, c)) {
4924
43
    zend_error_noreturn(ce->type == ZEND_INTERNAL_CLASS ? E_CORE_ERROR : E_COMPILE_ERROR,
4925
43
      "Cannot redefine class constant %s::%s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
4926
43
  }
4927
4928
10.1k
  return c;
4929
10.1k
}
4930
4931
ZEND_API zend_class_constant *zend_declare_class_constant_ex(zend_class_entry *ce, zend_string *name, zval *value, int flags, zend_string *doc_comment)
4932
3.10k
{
4933
3.10k
  return zend_declare_typed_class_constant(ce, name, value, flags, doc_comment, (zend_type) ZEND_TYPE_INIT_NONE(0));
4934
3.10k
}
4935
4936
ZEND_API void zend_declare_class_constant(zend_class_entry *ce, const char *name, size_t name_length, zval *value) /* {{{ */
4937
0
{
4938
0
  zend_string *key;
4939
4940
0
  if (ce->type == ZEND_INTERNAL_CLASS) {
4941
0
    key = zend_string_init_interned(name, name_length, 1);
4942
0
  } else {
4943
0
    key = zend_string_init(name, name_length, 0);
4944
0
  }
4945
0
  zend_declare_class_constant_ex(ce, key, value, ZEND_ACC_PUBLIC, NULL);
4946
0
  zend_string_release(key);
4947
0
}
4948
/* }}} */
4949
4950
ZEND_API void zend_declare_class_constant_null(zend_class_entry *ce, const char *name, size_t name_length) /* {{{ */
4951
0
{
4952
0
  zval constant;
4953
4954
0
  ZVAL_NULL(&constant);
4955
0
  zend_declare_class_constant(ce, name, name_length, &constant);
4956
0
}
4957
/* }}} */
4958
4959
ZEND_API void zend_declare_class_constant_long(zend_class_entry *ce, const char *name, size_t name_length, zend_long value) /* {{{ */
4960
0
{
4961
0
  zval constant;
4962
4963
0
  ZVAL_LONG(&constant, value);
4964
0
  zend_declare_class_constant(ce, name, name_length, &constant);
4965
0
}
4966
/* }}} */
4967
4968
ZEND_API void zend_declare_class_constant_bool(zend_class_entry *ce, const char *name, size_t name_length, bool value) /* {{{ */
4969
0
{
4970
0
  zval constant;
4971
4972
0
  ZVAL_BOOL(&constant, value);
4973
0
  zend_declare_class_constant(ce, name, name_length, &constant);
4974
0
}
4975
/* }}} */
4976
4977
ZEND_API void zend_declare_class_constant_double(zend_class_entry *ce, const char *name, size_t name_length, double value) /* {{{ */
4978
0
{
4979
0
  zval constant;
4980
4981
0
  ZVAL_DOUBLE(&constant, value);
4982
0
  zend_declare_class_constant(ce, name, name_length, &constant);
4983
0
}
4984
/* }}} */
4985
4986
ZEND_API void zend_declare_class_constant_stringl(zend_class_entry *ce, const char *name, size_t name_length, const char *value, size_t value_length) /* {{{ */
4987
0
{
4988
0
  zval constant;
4989
4990
0
  ZVAL_NEW_STR(&constant, zend_string_init(value, value_length, ce->type & ZEND_INTERNAL_CLASS));
4991
0
  zend_declare_class_constant(ce, name, name_length, &constant);
4992
0
}
4993
/* }}} */
4994
4995
ZEND_API void zend_declare_class_constant_string(zend_class_entry *ce, const char *name, size_t name_length, const char *value) /* {{{ */
4996
0
{
4997
0
  zend_declare_class_constant_stringl(ce, name, name_length, value, strlen(value));
4998
0
}
4999
/* }}} */
5000
5001
ZEND_API void zend_update_property_ex(zend_class_entry *scope, zend_object *object, zend_string *name, zval *value) /* {{{ */
5002
1.28M
{
5003
1.28M
  zend_class_entry *old_scope = EG(fake_scope);
5004
5005
1.28M
  EG(fake_scope) = scope;
5006
5007
1.28M
  object->handlers->write_property(object, name, value, NULL);
5008
5009
1.28M
  EG(fake_scope) = old_scope;
5010
1.28M
}
5011
/* }}} */
5012
5013
ZEND_API void zend_update_property(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, zval *value) /* {{{ */
5014
38.1k
{
5015
38.1k
  zend_string *property;
5016
38.1k
  zend_class_entry *old_scope = EG(fake_scope);
5017
5018
38.1k
  EG(fake_scope) = scope;
5019
5020
38.1k
  property = zend_string_init(name, name_length, 0);
5021
38.1k
  object->handlers->write_property(object, property, value, NULL);
5022
38.1k
  zend_string_release_ex(property, 0);
5023
5024
38.1k
  EG(fake_scope) = old_scope;
5025
38.1k
}
5026
/* }}} */
5027
5028
ZEND_API void zend_update_property_null(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length) /* {{{ */
5029
0
{
5030
0
  zval tmp;
5031
5032
0
  ZVAL_NULL(&tmp);
5033
0
  zend_update_property(scope, object, name, name_length, &tmp);
5034
0
}
5035
/* }}} */
5036
5037
ZEND_API void zend_unset_property(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length) /* {{{ */
5038
2
{
5039
2
  zend_string *property;
5040
2
  zend_class_entry *old_scope = EG(fake_scope);
5041
5042
2
  EG(fake_scope) = scope;
5043
5044
2
  property = zend_string_init(name, name_length, 0);
5045
2
  object->handlers->unset_property(object, property, 0);
5046
2
  zend_string_release_ex(property, 0);
5047
5048
2
  EG(fake_scope) = old_scope;
5049
2
}
5050
/* }}} */
5051
5052
ZEND_API void zend_update_property_bool(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, zend_long value) /* {{{ */
5053
0
{
5054
0
  zval tmp;
5055
5056
0
  ZVAL_BOOL(&tmp, value);
5057
0
  zend_update_property(scope, object, name, name_length, &tmp);
5058
0
}
5059
/* }}} */
5060
5061
ZEND_API void zend_update_property_long(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, zend_long value) /* {{{ */
5062
10
{
5063
10
  zval tmp;
5064
5065
10
  ZVAL_LONG(&tmp, value);
5066
10
  zend_update_property(scope, object, name, name_length, &tmp);
5067
10
}
5068
/* }}} */
5069
5070
ZEND_API void zend_update_property_double(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, double value) /* {{{ */
5071
0
{
5072
0
  zval tmp;
5073
5074
0
  ZVAL_DOUBLE(&tmp, value);
5075
0
  zend_update_property(scope, object, name, name_length, &tmp);
5076
0
}
5077
/* }}} */
5078
5079
ZEND_API void zend_update_property_str(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, zend_string *value) /* {{{ */
5080
0
{
5081
0
  zval tmp;
5082
5083
0
  ZVAL_STR(&tmp, value);
5084
0
  zend_update_property(scope, object, name, name_length, &tmp);
5085
0
}
5086
/* }}} */
5087
5088
ZEND_API void zend_update_property_string(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, const char *value) /* {{{ */
5089
0
{
5090
0
  zval tmp;
5091
5092
0
  ZVAL_STRING(&tmp, value);
5093
0
  Z_SET_REFCOUNT(tmp, 0);
5094
0
  zend_update_property(scope, object, name, name_length, &tmp);
5095
0
}
5096
/* }}} */
5097
5098
ZEND_API void zend_update_property_stringl(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, const char *value, size_t value_len) /* {{{ */
5099
5
{
5100
5
  zval tmp;
5101
5102
5
  ZVAL_STRINGL(&tmp, value, value_len);
5103
5
  Z_SET_REFCOUNT(tmp, 0);
5104
5
  zend_update_property(scope, object, name, name_length, &tmp);
5105
5
}
5106
/* }}} */
5107
5108
ZEND_API zend_result zend_update_static_property_ex(zend_class_entry *scope, zend_string *name, zval *value) /* {{{ */
5109
9
{
5110
9
  zval *property, tmp;
5111
9
  zend_property_info *prop_info;
5112
9
  zend_class_entry *old_scope = EG(fake_scope);
5113
5114
9
  if (UNEXPECTED(!(scope->ce_flags & ZEND_ACC_CONSTANTS_UPDATED))) {
5115
5
    if (UNEXPECTED(zend_update_class_constants(scope) != SUCCESS)) {
5116
0
      return FAILURE;
5117
0
    }
5118
5
  }
5119
5120
9
  EG(fake_scope) = scope;
5121
9
  property = zend_std_get_static_property_with_info(scope, name, BP_VAR_W, &prop_info);
5122
9
  EG(fake_scope) = old_scope;
5123
5124
9
  if (!property) {
5125
0
    return FAILURE;
5126
0
  }
5127
5128
9
  ZEND_ASSERT(!Z_ISREF_P(value));
5129
9
  Z_TRY_ADDREF_P(value);
5130
9
  if (ZEND_TYPE_IS_SET(prop_info->type)) {
5131
0
    ZVAL_COPY_VALUE(&tmp, value);
5132
0
    if (!zend_verify_property_type(prop_info, &tmp, /* strict */ 0)) {
5133
0
      Z_TRY_DELREF_P(value);
5134
0
      return FAILURE;
5135
0
    }
5136
0
    value = &tmp;
5137
0
  }
5138
5139
9
  zend_assign_to_variable(property, value, IS_TMP_VAR, /* strict */ 0);
5140
9
  return SUCCESS;
5141
9
}
5142
/* }}} */
5143
5144
ZEND_API zend_result zend_update_static_property(zend_class_entry *scope, const char *name, size_t name_length, zval *value) /* {{{ */
5145
0
{
5146
0
  zend_string *key = zend_string_init(name, name_length, 0);
5147
0
  zend_result retval = zend_update_static_property_ex(scope, key, value);
5148
0
  zend_string_efree(key);
5149
0
  return retval;
5150
0
}
5151
/* }}} */
5152
5153
ZEND_API zend_result zend_update_static_property_null(zend_class_entry *scope, const char *name, size_t name_length) /* {{{ */
5154
0
{
5155
0
  zval tmp;
5156
5157
0
  ZVAL_NULL(&tmp);
5158
0
  return zend_update_static_property(scope, name, name_length, &tmp);
5159
0
}
5160
/* }}} */
5161
5162
ZEND_API zend_result zend_update_static_property_bool(zend_class_entry *scope, const char *name, size_t name_length, zend_long value) /* {{{ */
5163
0
{
5164
0
  zval tmp;
5165
5166
0
  ZVAL_BOOL(&tmp, value);
5167
0
  return zend_update_static_property(scope, name, name_length, &tmp);
5168
0
}
5169
/* }}} */
5170
5171
ZEND_API zend_result zend_update_static_property_long(zend_class_entry *scope, const char *name, size_t name_length, zend_long value) /* {{{ */
5172
0
{
5173
0
  zval tmp;
5174
5175
0
  ZVAL_LONG(&tmp, value);
5176
0
  return zend_update_static_property(scope, name, name_length, &tmp);
5177
0
}
5178
/* }}} */
5179
5180
ZEND_API zend_result zend_update_static_property_double(zend_class_entry *scope, const char *name, size_t name_length, double value) /* {{{ */
5181
0
{
5182
0
  zval tmp;
5183
5184
0
  ZVAL_DOUBLE(&tmp, value);
5185
0
  return zend_update_static_property(scope, name, name_length, &tmp);
5186
0
}
5187
/* }}} */
5188
5189
ZEND_API zend_result zend_update_static_property_string(zend_class_entry *scope, const char *name, size_t name_length, const char *value) /* {{{ */
5190
0
{
5191
0
  zval tmp;
5192
5193
0
  ZVAL_STRING(&tmp, value);
5194
0
  Z_SET_REFCOUNT(tmp, 0);
5195
0
  return zend_update_static_property(scope, name, name_length, &tmp);
5196
0
}
5197
/* }}} */
5198
5199
ZEND_API zend_result zend_update_static_property_stringl(zend_class_entry *scope, const char *name, size_t name_length, const char *value, size_t value_len) /* {{{ */
5200
0
{
5201
0
  zval tmp;
5202
5203
0
  ZVAL_STRINGL(&tmp, value, value_len);
5204
0
  Z_SET_REFCOUNT(tmp, 0);
5205
0
  return zend_update_static_property(scope, name, name_length, &tmp);
5206
0
}
5207
/* }}} */
5208
5209
ZEND_API zval *zend_read_property_ex(zend_class_entry *scope, zend_object *object, zend_string *name, bool silent, zval *rv) /* {{{ */
5210
23.5M
{
5211
23.5M
  zval *value;
5212
23.5M
  zend_class_entry *old_scope = EG(fake_scope);
5213
5214
23.5M
  EG(fake_scope) = scope;
5215
5216
23.5M
  value = object->handlers->read_property(object, name, silent?BP_VAR_IS:BP_VAR_R, NULL, rv);
5217
5218
23.5M
  EG(fake_scope) = old_scope;
5219
23.5M
  return value;
5220
23.5M
}
5221
/* }}} */
5222
5223
ZEND_API zval *zend_read_property(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, bool silent, zval *rv) /* {{{ */
5224
10
{
5225
10
  zval *value;
5226
10
  zend_string *str;
5227
5228
10
  str = zend_string_init(name, name_length, 0);
5229
10
  value = zend_read_property_ex(scope, object, str, silent, rv);
5230
10
  zend_string_release_ex(str, 0);
5231
10
  return value;
5232
10
}
5233
/* }}} */
5234
5235
ZEND_API zval *zend_read_static_property_ex(zend_class_entry *scope, zend_string *name, bool silent) /* {{{ */
5236
18
{
5237
18
  zval *property;
5238
18
  zend_class_entry *old_scope = EG(fake_scope);
5239
5240
18
  EG(fake_scope) = scope;
5241
18
  property = zend_std_get_static_property(scope, name, silent ? BP_VAR_IS : BP_VAR_R);
5242
18
  EG(fake_scope) = old_scope;
5243
5244
18
  return property;
5245
18
}
5246
/* }}} */
5247
5248
ZEND_API zval *zend_read_static_property(zend_class_entry *scope, const char *name, size_t name_length, bool silent) /* {{{ */
5249
0
{
5250
0
  zend_string *key = zend_string_init(name, name_length, 0);
5251
0
  zval *property = zend_read_static_property_ex(scope, key, silent);
5252
0
  zend_string_efree(key);
5253
0
  return property;
5254
0
}
5255
/* }}} */
5256
5257
ZEND_API void zend_save_error_handling(zend_error_handling *current) /* {{{ */
5258
5
{
5259
5
  current->handling = EG(error_handling);
5260
5
  current->exception = EG(exception_class);
5261
5
}
5262
/* }}} */
5263
5264
ZEND_API void zend_replace_error_handling(zend_error_handling_t error_handling, zend_class_entry *exception_class, zend_error_handling *current) /* {{{ */
5265
5
{
5266
5
  if (current) {
5267
5
    zend_save_error_handling(current);
5268
5
  }
5269
5
  ZEND_ASSERT(error_handling == EH_THROW || exception_class == NULL);
5270
5
  EG(error_handling) = error_handling;
5271
5
  EG(exception_class) = exception_class;
5272
5
}
5273
/* }}} */
5274
5275
ZEND_API void zend_restore_error_handling(zend_error_handling *saved) /* {{{ */
5276
5
{
5277
5
  EG(error_handling) = saved->handling;
5278
5
  EG(exception_class) = saved->exception;
5279
5
}
5280
/* }}} */
5281
5282
ZEND_API ZEND_COLD const char *zend_get_object_type_case(const zend_class_entry *ce, bool upper_case) /* {{{ */
5283
425
{
5284
425
  if (ce->ce_flags & ZEND_ACC_TRAIT) {
5285
7
    return upper_case ? "Trait" : "trait";
5286
418
  } else if (ce->ce_flags & ZEND_ACC_INTERFACE) {
5287
53
    return upper_case ? "Interface" : "interface";
5288
365
  } else if (ce->ce_flags & ZEND_ACC_ENUM) {
5289
51
    return upper_case ? "Enum" : "enum";
5290
314
  } else {
5291
314
    return upper_case ? "Class" : "class";
5292
314
  }
5293
425
}
5294
/* }}} */
5295
5296
ZEND_API bool zend_is_iterable(const zval *iterable) /* {{{ */
5297
53
{
5298
53
  switch (Z_TYPE_P(iterable)) {
5299
0
    case IS_ARRAY:
5300
0
      return 1;
5301
50
    case IS_OBJECT:
5302
50
      return zend_class_implements_interface(Z_OBJCE_P(iterable), zend_ce_traversable);
5303
3
    default:
5304
3
      return 0;
5305
53
  }
5306
53
}
5307
/* }}} */
5308
5309
ZEND_API bool zend_is_countable(const zval *countable) /* {{{ */
5310
0
{
5311
0
  switch (Z_TYPE_P(countable)) {
5312
0
    case IS_ARRAY:
5313
0
      return 1;
5314
0
    case IS_OBJECT:
5315
0
      if (Z_OBJ_HT_P(countable)->count_elements) {
5316
0
        return 1;
5317
0
      }
5318
5319
0
      return zend_class_implements_interface(Z_OBJCE_P(countable), zend_ce_countable);
5320
0
    default:
5321
0
      return 0;
5322
0
  }
5323
0
}
5324
/* }}} */
5325
5326
18
static zend_result get_default_via_ast(zval *default_value_zval, const char *default_value) {
5327
18
  zend_ast *ast;
5328
18
  zend_arena *ast_arena;
5329
5330
18
  zend_string *code = zend_string_concat3(
5331
18
    "<?php ", sizeof("<?php ") - 1, default_value, strlen(default_value), ";", 1);
5332
5333
18
  ast = zend_compile_string_to_ast(code, &ast_arena, ZSTR_EMPTY_ALLOC());
5334
18
  zend_string_release(code);
5335
5336
18
  if (!ast) {
5337
0
    return FAILURE;
5338
0
  }
5339
5340
18
  zend_ast_list *statement_list = zend_ast_get_list(ast);
5341
18
  zend_ast **const_expr_ast_ptr = &statement_list->child[0];
5342
5343
18
  zend_arena *original_ast_arena = CG(ast_arena);
5344
18
  uint32_t original_compiler_options = CG(compiler_options);
5345
18
  zend_file_context original_file_context;
5346
18
  CG(ast_arena) = ast_arena;
5347
  /* Disable constant substitution, to make getDefaultValueConstant() work. */
5348
18
  CG(compiler_options) |= ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION | ZEND_COMPILE_NO_PERSISTENT_CONSTANT_SUBSTITUTION;
5349
18
  zend_file_context_begin(&original_file_context);
5350
18
  zend_const_expr_to_zval(default_value_zval, const_expr_ast_ptr, /* allow_dynamic */ true);
5351
18
  CG(ast_arena) = original_ast_arena;
5352
18
  CG(compiler_options) = original_compiler_options;
5353
18
  zend_file_context_end(&original_file_context);
5354
5355
18
  zend_ast_destroy(ast);
5356
18
  zend_arena_destroy(ast_arena);
5357
5358
18
  return SUCCESS;
5359
18
}
5360
5361
5
static zend_string *try_parse_string(const char *str, size_t len, char quote) {
5362
5
  if (len == 0) {
5363
0
    return ZSTR_EMPTY_ALLOC();
5364
0
  }
5365
5366
10
  for (size_t i = 0; i < len; i++) {
5367
5
    if (str[i] == '\\' || str[i] == quote) {
5368
0
      return NULL;
5369
0
    }
5370
5
  }
5371
5
  return zend_string_init(str, len, 0);
5372
5
}
5373
5374
ZEND_API zend_result zend_get_default_from_internal_arg_info(
5375
    zval *default_value_zval, zend_internal_arg_info *arg_info)
5376
138
{
5377
138
  const char *default_value = arg_info->default_value;
5378
138
  if (!default_value) {
5379
10
    return FAILURE;
5380
10
  }
5381
5382
  /* Avoid going through the full AST machinery for some simple and common cases. */
5383
128
  size_t default_value_len = strlen(default_value);
5384
128
  zend_ulong lval;
5385
128
  if (default_value_len == sizeof("null")-1
5386
128
      && !memcmp(default_value, "null", sizeof("null")-1)) {
5387
90
    ZVAL_NULL(default_value_zval);
5388
90
    return SUCCESS;
5389
90
  } else if (default_value_len == sizeof("true")-1
5390
38
      && !memcmp(default_value, "true", sizeof("true")-1)) {
5391
0
    ZVAL_TRUE(default_value_zval);
5392
0
    return SUCCESS;
5393
38
  } else if (default_value_len == sizeof("false")-1
5394
38
      && !memcmp(default_value, "false", sizeof("false")-1)) {
5395
15
    ZVAL_FALSE(default_value_zval);
5396
15
    return SUCCESS;
5397
23
  } else if (default_value_len >= 2
5398
23
      && (default_value[0] == '\'' || default_value[0] == '"')
5399
23
      && default_value[default_value_len - 1] == default_value[0]) {
5400
5
    zend_string *str = try_parse_string(
5401
5
      default_value + 1, default_value_len - 2, default_value[0]);
5402
5
    if (str) {
5403
5
      ZVAL_STR(default_value_zval, str);
5404
5
      return SUCCESS;
5405
5
    }
5406
18
  } else if (default_value_len == sizeof("[]")-1
5407
18
      && !memcmp(default_value, "[]", sizeof("[]")-1)) {
5408
0
    ZVAL_EMPTY_ARRAY(default_value_zval);
5409
0
    return SUCCESS;
5410
18
  } else if (ZEND_HANDLE_NUMERIC_STR(default_value, default_value_len, lval)) {
5411
0
    ZVAL_LONG(default_value_zval, lval);
5412
0
    return SUCCESS;
5413
0
  }
5414
5415
#if 0
5416
  fprintf(stderr, "Evaluating %s via AST\n", default_value);
5417
#endif
5418
18
  return get_default_via_ast(default_value_zval, default_value);
5419
128
}