Coverage Report

Created: 2026-10-28 06:20

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