Coverage Report

Created: 2026-09-14 06:25

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