Coverage Report

Created: 2026-07-25 06:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/php-src/Zend/zend_execute.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
   |          Dmitry Stogov <dmitry@php.net>                              |
17
   +----------------------------------------------------------------------+
18
*/
19
20
#define ZEND_INTENSIVE_DEBUGGING 0
21
22
#include <stdio.h>
23
#include <signal.h>
24
25
#include "zend.h"
26
#include "zend_compile.h"
27
#include "zend_execute.h"
28
#include "zend_API.h"
29
#include "zend_ptr_stack.h"
30
#include "zend_constants.h"
31
#include "zend_extensions.h"
32
#include "zend_ini.h"
33
#include "zend_exceptions.h"
34
#include "zend_interfaces.h"
35
#include "zend_closures.h"
36
#include "zend_generators.h"
37
#include "zend_vm.h"
38
#include "zend_dtrace.h"
39
#include "zend_inheritance.h"
40
#include "zend_type_info.h"
41
#include "zend_smart_str.h"
42
#include "zend_observer.h"
43
#include "zend_system_id.h"
44
#include "zend_call_stack.h"
45
#include "zend_attributes.h"
46
#include "Optimizer/zend_func_info.h"
47
48
/* Virtual current working directory support */
49
#include "zend_virtual_cwd.h"
50
51
#ifdef HAVE_GCC_GLOBAL_REGS
52
# if defined(__GNUC__) && ZEND_GCC_VERSION >= 4008 && defined(i386)
53
#  define ZEND_VM_FP_GLOBAL_REG "%esi"
54
#  define ZEND_VM_IP_GLOBAL_REG "%edi"
55
# elif defined(__GNUC__) && ZEND_GCC_VERSION >= 4008 && defined(__x86_64__)
56
#  define ZEND_VM_FP_GLOBAL_REG "%r14"
57
#  define ZEND_VM_IP_GLOBAL_REG "%r15"
58
# elif defined(__GNUC__) && ZEND_GCC_VERSION >= 4008 && defined(__powerpc64__)
59
#  define ZEND_VM_FP_GLOBAL_REG "r14"
60
#  define ZEND_VM_IP_GLOBAL_REG "r15"
61
# elif defined(__IBMC__) && ZEND_GCC_VERSION >= 4002 && defined(__powerpc64__)
62
#  define ZEND_VM_FP_GLOBAL_REG "r14"
63
#  define ZEND_VM_IP_GLOBAL_REG "r15"
64
# elif defined(__GNUC__) && ZEND_GCC_VERSION >= 4008 && defined(__aarch64__)
65
#  define ZEND_VM_FP_GLOBAL_REG "x27"
66
#  define ZEND_VM_IP_GLOBAL_REG "x28"
67
#elif defined(__GNUC__) && ZEND_GCC_VERSION >= 4008 && defined(__riscv) && __riscv_xlen == 64
68
#  define ZEND_VM_FP_GLOBAL_REG "x18"
69
#  define ZEND_VM_IP_GLOBAL_REG "x19"
70
# endif
71
#endif
72
73
#if defined(ZEND_VM_FP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID))
74
# pragma GCC diagnostic ignored "-Wvolatile-register-var"
75
  register zend_execute_data* volatile execute_data __asm__(ZEND_VM_FP_GLOBAL_REG);
76
# pragma GCC diagnostic warning "-Wvolatile-register-var"
77
#endif
78
79
#if defined(ZEND_VM_FP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID))
80
# define EXECUTE_DATA_D     void
81
# define EXECUTE_DATA_C
82
# define EXECUTE_DATA_DC
83
# define EXECUTE_DATA_CC
84
# define NO_EXECUTE_DATA_CC
85
#else
86
# define EXECUTE_DATA_D     zend_execute_data* execute_data
87
9.61M
# define EXECUTE_DATA_C     execute_data
88
# define EXECUTE_DATA_DC    , EXECUTE_DATA_D
89
8.18M
# define EXECUTE_DATA_CC    , EXECUTE_DATA_C
90
282
# define NO_EXECUTE_DATA_CC , NULL
91
#endif
92
93
#if defined(ZEND_VM_FP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID))
94
# define OPLINE_D           void
95
# define OPLINE_C
96
# define OPLINE_DC
97
# define OPLINE_CC
98
#else
99
# define OPLINE_D           const zend_op* opline
100
1.64M
# define OPLINE_C           opline
101
# define OPLINE_DC          , OPLINE_D
102
1.64M
# define OPLINE_CC          , OPLINE_C
103
#endif
104
105
#if defined(ZEND_VM_IP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID))
106
# pragma GCC diagnostic ignored "-Wvolatile-register-var"
107
  register const zend_op* volatile opline __asm__(ZEND_VM_IP_GLOBAL_REG);
108
# pragma GCC diagnostic warning "-Wvolatile-register-var"
109
#else
110
#endif
111
112
91.8M
#define _CONST_CODE  0
113
91.8M
#define _TMP_CODE    1
114
91.8M
#define _VAR_CODE    2
115
459M
#define _UNUSED_CODE 3
116
91.8M
#define _CV_CODE     4
117
118
typedef int (ZEND_FASTCALL *incdec_t)(zval *);
119
120
1.28k
#define get_zval_ptr(op_type, node, type) _get_zval_ptr(op_type, node, type EXECUTE_DATA_CC OPLINE_CC)
121
88
#define get_zval_ptr_deref(op_type, node, type) _get_zval_ptr_deref(op_type, node, type EXECUTE_DATA_CC OPLINE_CC)
122
2.84k
#define get_zval_ptr_undef(op_type, node, type) _get_zval_ptr_undef(op_type, node, type EXECUTE_DATA_CC OPLINE_CC)
123
16.0k
#define get_op_data_zval_ptr_r(op_type, node) _get_op_data_zval_ptr_r(op_type, node EXECUTE_DATA_CC OPLINE_CC)
124
0
#define get_op_data_zval_ptr_deref_r(op_type, node) _get_op_data_zval_ptr_deref_r(op_type, node EXECUTE_DATA_CC OPLINE_CC)
125
310
#define get_zval_ptr_ptr(op_type, node, type) _get_zval_ptr_ptr(op_type, node, type EXECUTE_DATA_CC)
126
#define get_zval_ptr_ptr_undef(op_type, node, type) _get_zval_ptr_ptr(op_type, node, type EXECUTE_DATA_CC)
127
#define get_obj_zval_ptr(op_type, node, type) _get_obj_zval_ptr(op_type, node, type EXECUTE_DATA_CC OPLINE_CC)
128
#define get_obj_zval_ptr_deref(op_type, node, type) _get_obj_zval_ptr_deref(op_type, node, type EXECUTE_DATA_CC OPLINE_CC)
129
#define get_obj_zval_ptr_undef(op_type, node, type) _get_obj_zval_ptr_undef(op_type, node, type EXECUTE_DATA_CC OPLINE_CC)
130
#define get_obj_zval_ptr_ptr(op_type, node, type) _get_obj_zval_ptr_ptr(op_type, node, type EXECUTE_DATA_CC)
131
132
655k
#define RETURN_VALUE_USED(opline) ((opline)->result_type != IS_UNUSED)
133
134
static ZEND_FUNCTION(pass)
135
259
{
136
259
}
137
138
static zend_arg_info zend_pass_function_arg_info[1] = {0};
139
140
ZEND_API const zend_internal_function zend_pass_function = {
141
  ZEND_INTERNAL_FUNCTION, /* type              */
142
  {0, 0, 0},              /* arg_flags         */
143
  0,                      /* fn_flags          */
144
  NULL,                   /* name              */
145
  NULL,                   /* scope             */
146
  NULL,                   /* prototype         */
147
  0,                      /* num_args          */
148
  0,                      /* required_num_args */
149
  zend_pass_function_arg_info + 1, /* arg_info */
150
  NULL,                   /* attributes        */
151
  NULL,                   /* run_time_cache    */
152
  NULL,                   /* doc_comment       */
153
  0,                      /* T                 */
154
  0,                      /* fn_flags2         */
155
  NULL,                   /* prop_info */
156
  ZEND_FN(pass),          /* handler           */
157
  NULL,                   /* module            */
158
  NULL,                   /* frameless_function_infos */
159
  {NULL,NULL,NULL,NULL}   /* reserved          */
160
};
161
162
6.41k
#define FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_var) do {     \
163
6.41k
  zval *__container_to_free = EX_VAR(free_var);             \
164
6.41k
  if (UNEXPECTED(Z_REFCOUNTED_P(__container_to_free))) {         \
165
504
    zend_refcounted *__ref = Z_COUNTED_P(__container_to_free);      \
166
504
    if (UNEXPECTED(!GC_DELREF(__ref))) {               \
167
302
      zval *__zv = EX_VAR(opline->result.var);           \
168
302
      if (EXPECTED(Z_TYPE_P(__zv) == IS_INDIRECT)) {         \
169
294
        ZVAL_COPY(__zv, Z_INDIRECT_P(__zv));           \
170
294
      }                                \
171
302
      rc_dtor_func(__ref);                      \
172
302
    }                                  \
173
504
  }                                    \
174
6.41k
} while (0)
175
176
#define FREE_OP(type, var) \
177
30.8k
  if ((type) & (IS_TMP_VAR|IS_VAR)) { \
178
11.3k
    zval_ptr_dtor_nogc(EX_VAR(var)); \
179
11.3k
  }
180
181
1.52M
#define CV_DEF_OF(i) (EX(func)->op_array.vars[i])
182
183
601k
#define ZEND_VM_STACK_PAGE_SLOTS (16 * 1024) /* should be a power of 2 */
184
185
601k
#define ZEND_VM_STACK_PAGE_SIZE  (ZEND_VM_STACK_PAGE_SLOTS * sizeof(zval))
186
187
#define ZEND_VM_STACK_PAGE_ALIGNED_SIZE(size, page_size) \
188
59
  (((size) + ZEND_VM_STACK_HEADER_SLOTS * sizeof(zval) \
189
59
    + ((page_size) - 1)) & ~((page_size) - 1))
190
191
ZEND_API void zend_vm_stack_init(void)
192
300k
{
193
300k
  EG(vm_stack_page_size) = ZEND_VM_STACK_PAGE_SIZE;
194
300k
  EG(vm_stack) = zend_vm_stack_new_page(ZEND_VM_STACK_PAGE_SIZE, NULL);
195
300k
  EG(vm_stack_top) = EG(vm_stack)->top;
196
300k
  EG(vm_stack_end) = EG(vm_stack)->end;
197
300k
}
198
199
ZEND_API void zend_vm_stack_init_ex(size_t page_size)
200
0
{
201
  /* page_size must be a power of 2 */
202
0
  ZEND_ASSERT(page_size > 0 && (page_size & (page_size - 1)) == 0);
203
0
  EG(vm_stack_page_size) = page_size;
204
0
  EG(vm_stack) = zend_vm_stack_new_page(page_size, NULL);
205
0
  EG(vm_stack_top) = EG(vm_stack)->top;
206
0
  EG(vm_stack_end) = EG(vm_stack)->end;
207
0
}
208
209
ZEND_API void zend_vm_stack_destroy(void)
210
301k
{
211
301k
  zend_vm_stack stack = EG(vm_stack);
212
213
603k
  while (stack != NULL) {
214
301k
    zend_vm_stack p = stack->prev;
215
301k
    efree(stack);
216
301k
    stack = p;
217
301k
  }
218
301k
}
219
220
ZEND_API void* zend_vm_stack_extend(size_t size)
221
75
{
222
75
  zend_vm_stack stack;
223
75
  void *ptr;
224
225
75
  stack = EG(vm_stack);
226
75
  stack->top = EG(vm_stack_top);
227
75
  EG(vm_stack) = stack = zend_vm_stack_new_page(
228
75
    EXPECTED(size < EG(vm_stack_page_size) - (ZEND_VM_STACK_HEADER_SLOTS * sizeof(zval))) ?
229
59
      EG(vm_stack_page_size) : ZEND_VM_STACK_PAGE_ALIGNED_SIZE(size, EG(vm_stack_page_size)),
230
75
    stack);
231
75
  ptr = stack->top;
232
75
  EG(vm_stack_top) = (void*)(((char*)ptr) + size);
233
75
  EG(vm_stack_end) = stack->end;
234
75
  return ptr;
235
75
}
236
237
ZEND_API zval* zend_get_compiled_variable_value(const zend_execute_data *execute_data, uint32_t var)
238
0
{
239
0
  return EX_VAR(var);
240
0
}
241
242
ZEND_API bool zend_gcc_global_regs(void)
243
0
{
244
  #if defined(HAVE_GCC_GLOBAL_REGS)
245
        return 1;
246
  #else
247
0
        return 0;
248
0
  #endif
249
0
}
250
251
static zend_always_inline zval *_get_zval_ptr_tmp(uint32_t var EXECUTE_DATA_DC)
252
3.66M
{
253
3.66M
  zval *ret = EX_VAR(var);
254
255
3.66M
  ZEND_ASSERT(Z_TYPE_P(ret) != IS_REFERENCE);
256
257
3.66M
  return ret;
258
3.66M
}
259
260
static zend_always_inline zval *_get_zval_ptr_var(uint32_t var EXECUTE_DATA_DC)
261
338k
{
262
338k
  zval *ret = EX_VAR(var);
263
264
338k
  return ret;
265
338k
}
266
267
static zend_always_inline zval *_get_zval_ptr_var_deref(uint32_t var EXECUTE_DATA_DC)
268
0
{
269
0
  zval *ret = EX_VAR(var);
270
271
0
  ZVAL_DEREF(ret);
272
0
  return ret;
273
0
}
274
275
static zend_never_inline ZEND_COLD zval* zval_undefined_cv(uint32_t var EXECUTE_DATA_DC)
276
1.52M
{
277
1.52M
  if (EXPECTED(EG(exception) == NULL)) {
278
1.52M
    zend_string *cv = CV_DEF_OF(EX_VAR_TO_NUM(var));
279
1.52M
    zend_error_unchecked(E_WARNING, "Undefined variable $%S", cv);
280
1.52M
  }
281
1.52M
  return &EG(uninitialized_zval);
282
1.52M
}
283
284
static zend_never_inline ZEND_COLD zval* ZEND_FASTCALL _zval_undefined_op1(EXECUTE_DATA_D)
285
828k
{
286
828k
  return zval_undefined_cv(EX(opline)->op1.var EXECUTE_DATA_CC);
287
828k
}
288
289
static zend_never_inline ZEND_COLD zval* ZEND_FASTCALL _zval_undefined_op2(EXECUTE_DATA_D)
290
580k
{
291
580k
  return zval_undefined_cv(EX(opline)->op2.var EXECUTE_DATA_CC);
292
580k
}
293
294
828k
#define ZVAL_UNDEFINED_OP1() _zval_undefined_op1(EXECUTE_DATA_C)
295
580k
#define ZVAL_UNDEFINED_OP2() _zval_undefined_op2(EXECUTE_DATA_C)
296
297
static zend_never_inline ZEND_COLD zval *_get_zval_cv_lookup(zval *ptr, uint32_t var, int type EXECUTE_DATA_DC)
298
250
{
299
250
  switch (type) {
300
250
    case BP_VAR_R:
301
250
    case BP_VAR_UNSET:
302
250
      ptr = zval_undefined_cv(var EXECUTE_DATA_CC);
303
250
      break;
304
0
    case BP_VAR_IS:
305
0
      ptr = &EG(uninitialized_zval);
306
0
      break;
307
0
    case BP_VAR_RW:
308
0
      zval_undefined_cv(var EXECUTE_DATA_CC);
309
0
      ZEND_FALLTHROUGH;
310
0
    case BP_VAR_W:
311
0
      ZVAL_NULL(ptr);
312
0
      break;
313
250
  }
314
250
  return ptr;
315
250
}
316
317
static zend_always_inline zval *_get_zval_ptr_cv(uint32_t var, int type EXECUTE_DATA_DC)
318
864
{
319
864
  zval *ret = EX_VAR(var);
320
321
864
  if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
322
49
    if (type == BP_VAR_W) {
323
16
      ZVAL_NULL(ret);
324
33
    } else {
325
33
      return _get_zval_cv_lookup(ret, var, type EXECUTE_DATA_CC);
326
33
    }
327
49
  }
328
831
  return ret;
329
864
}
330
331
static zend_always_inline zval *_get_zval_ptr_cv_deref(uint32_t var, int type EXECUTE_DATA_DC)
332
810
{
333
810
  zval *ret = EX_VAR(var);
334
335
810
  if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
336
217
    if (type == BP_VAR_W) {
337
0
      ZVAL_NULL(ret);
338
0
      return ret;
339
217
    } else {
340
217
      return _get_zval_cv_lookup(ret, var, type EXECUTE_DATA_CC);
341
217
    }
342
217
  }
343
593
  ZVAL_DEREF(ret);
344
593
  return ret;
345
810
}
346
347
static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_R(uint32_t var EXECUTE_DATA_DC)
348
137k
{
349
137k
  zval *ret = EX_VAR(var);
350
351
137k
  if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
352
23.6k
    return zval_undefined_cv(var EXECUTE_DATA_CC);
353
23.6k
  }
354
113k
  return ret;
355
137k
}
356
357
static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_R(uint32_t var EXECUTE_DATA_DC)
358
37.3k
{
359
37.3k
  zval *ret = EX_VAR(var);
360
361
37.3k
  if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
362
6.83k
    return zval_undefined_cv(var EXECUTE_DATA_CC);
363
6.83k
  }
364
30.4k
  ZVAL_DEREF(ret);
365
30.4k
  return ret;
366
37.3k
}
367
368
static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_IS(uint32_t var EXECUTE_DATA_DC)
369
2.77k
{
370
2.77k
  zval *ret = EX_VAR(var);
371
372
2.77k
  return ret;
373
2.77k
}
374
375
static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_RW(uint32_t var EXECUTE_DATA_DC)
376
1.44M
{
377
1.44M
  zval *ret = EX_VAR(var);
378
379
1.44M
  if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
380
85.7k
    zval_undefined_cv(var EXECUTE_DATA_CC);
381
85.7k
    ZVAL_NULL(ret);
382
85.7k
    return ret;
383
85.7k
  }
384
1.35M
  return ret;
385
1.44M
}
386
387
static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_W(uint32_t var EXECUTE_DATA_DC)
388
29.0k
{
389
29.0k
  zval *ret = EX_VAR(var);
390
391
29.0k
  if (Z_TYPE_P(ret) == IS_UNDEF) {
392
2.18k
    ZVAL_NULL(ret);
393
2.18k
  }
394
29.0k
  return ret;
395
29.0k
}
396
397
static zend_always_inline zval *_get_zval_ptr_tmpvarcv(int op_type, znode_op node, int type EXECUTE_DATA_DC)
398
981
{
399
981
  if (op_type & (IS_TMP_VAR|IS_VAR)) {
400
282
    if (op_type == IS_TMP_VAR) {
401
282
      return _get_zval_ptr_tmp(node.var EXECUTE_DATA_CC);
402
282
    } else {
403
0
      ZEND_ASSERT(op_type == IS_VAR);
404
0
      return _get_zval_ptr_var_deref(node.var EXECUTE_DATA_CC);
405
0
    }
406
699
  } else {
407
699
    ZEND_ASSERT(op_type == IS_CV);
408
699
    return _get_zval_ptr_cv_deref(node.var, type EXECUTE_DATA_CC);
409
699
  }
410
981
}
411
412
static zend_always_inline zval *_get_zval_ptr(int op_type, znode_op node, int type EXECUTE_DATA_DC OPLINE_DC)
413
1.28k
{
414
1.28k
  if (op_type & (IS_TMP_VAR|IS_VAR)) {
415
294
    if (!ZEND_DEBUG || op_type == IS_VAR) {
416
0
      return _get_zval_ptr_var(node.var EXECUTE_DATA_CC);
417
294
    } else {
418
294
      ZEND_ASSERT(op_type == IS_TMP_VAR);
419
294
      return _get_zval_ptr_tmp(node.var EXECUTE_DATA_CC);
420
294
    }
421
992
  } else {
422
992
    if (op_type == IS_CONST) {
423
190
      return RT_CONSTANT(opline, node);
424
802
    } else if (op_type == IS_CV) {
425
802
      return _get_zval_ptr_cv(node.var, type EXECUTE_DATA_CC);
426
802
    } else {
427
0
      return NULL;
428
0
    }
429
992
  }
430
1.28k
}
431
432
static zend_always_inline zval *_get_op_data_zval_ptr_r(int op_type, znode_op node EXECUTE_DATA_DC OPLINE_DC)
433
16.2k
{
434
16.2k
  if (op_type & (IS_TMP_VAR|IS_VAR)) {
435
2.56k
    if (!ZEND_DEBUG || op_type == IS_VAR) {
436
0
      return _get_zval_ptr_var(node.var EXECUTE_DATA_CC);
437
2.56k
    } else {
438
2.56k
      ZEND_ASSERT(op_type == IS_TMP_VAR);
439
2.56k
      return _get_zval_ptr_tmp(node.var EXECUTE_DATA_CC);
440
2.56k
    }
441
13.7k
  } else {
442
13.7k
    if (op_type == IS_CONST) {
443
10.7k
      return RT_CONSTANT(opline + 1, node);
444
10.7k
    } else if (op_type == IS_CV) {
445
2.99k
      return _get_zval_ptr_cv_BP_VAR_R(node.var EXECUTE_DATA_CC);
446
2.99k
    } else {
447
0
      return NULL;
448
0
    }
449
13.7k
  }
450
16.2k
}
451
452
static zend_always_inline ZEND_ATTRIBUTE_UNUSED zval *_get_zval_ptr_deref(int op_type, znode_op node, int type EXECUTE_DATA_DC OPLINE_DC)
453
360
{
454
360
  if (op_type & (IS_TMP_VAR|IS_VAR)) {
455
244
    if (op_type == IS_TMP_VAR) {
456
244
      return _get_zval_ptr_tmp(node.var EXECUTE_DATA_CC);
457
244
    } else {
458
0
      ZEND_ASSERT(op_type == IS_VAR);
459
0
      return _get_zval_ptr_var_deref(node.var EXECUTE_DATA_CC);
460
0
    }
461
244
  } else {
462
116
    if (op_type == IS_CONST) {
463
5
      return RT_CONSTANT(opline, node);
464
111
    } else if (op_type == IS_CV) {
465
111
      return _get_zval_ptr_cv_deref(node.var, type EXECUTE_DATA_CC);
466
111
    } else {
467
0
      return NULL;
468
0
    }
469
116
  }
470
360
}
471
472
static zend_always_inline ZEND_ATTRIBUTE_UNUSED zval *_get_op_data_zval_ptr_deref_r(int op_type, znode_op node EXECUTE_DATA_DC OPLINE_DC)
473
0
{
474
0
  if (op_type & (IS_TMP_VAR|IS_VAR)) {
475
0
    if (op_type == IS_TMP_VAR) {
476
0
      return _get_zval_ptr_tmp(node.var EXECUTE_DATA_CC);
477
0
    } else {
478
0
      ZEND_ASSERT(op_type == IS_VAR);
479
0
      return _get_zval_ptr_var_deref(node.var EXECUTE_DATA_CC);
480
0
    }
481
0
  } else {
482
0
    if (op_type == IS_CONST) {
483
0
      return RT_CONSTANT(opline + 1, node);
484
0
    } else if (op_type == IS_CV) {
485
0
      return _get_zval_ptr_cv_deref_BP_VAR_R(node.var EXECUTE_DATA_CC);
486
0
    } else {
487
0
      return NULL;
488
0
    }
489
0
  }
490
0
}
491
492
static zend_always_inline zval *_get_zval_ptr_undef(int op_type, znode_op node, int type EXECUTE_DATA_DC OPLINE_DC)
493
2.84k
{
494
2.84k
  if (op_type & (IS_TMP_VAR|IS_VAR)) {
495
424
    if (!ZEND_DEBUG || op_type == IS_VAR) {
496
0
      return _get_zval_ptr_var(node.var EXECUTE_DATA_CC);
497
424
    } else {
498
424
      ZEND_ASSERT(op_type == IS_TMP_VAR);
499
424
      return _get_zval_ptr_tmp(node.var EXECUTE_DATA_CC);
500
424
    }
501
2.41k
  } else {
502
2.41k
    if (op_type == IS_CONST) {
503
356
      return RT_CONSTANT(opline, node);
504
2.06k
    } else if (op_type == IS_CV) {
505
2.06k
      return EX_VAR(node.var);
506
2.06k
    } else {
507
0
      return NULL;
508
0
    }
509
2.41k
  }
510
2.84k
}
511
512
static zend_always_inline zval *_get_zval_ptr_ptr_var(uint32_t var EXECUTE_DATA_DC)
513
91.9k
{
514
91.9k
  zval *ret = EX_VAR(var);
515
516
91.9k
  if (EXPECTED(Z_TYPE_P(ret) == IS_INDIRECT)) {
517
84.1k
    ret = Z_INDIRECT_P(ret);
518
84.1k
  }
519
91.9k
  return ret;
520
91.9k
}
521
522
static inline zval *_get_zval_ptr_ptr(int op_type, znode_op node, int type EXECUTE_DATA_DC)
523
310
{
524
310
  if (op_type == IS_CV) {
525
62
    return _get_zval_ptr_cv(node.var, type EXECUTE_DATA_CC);
526
248
  } else /* if (op_type == IS_VAR) */ {
527
248
    ZEND_ASSERT(op_type == IS_VAR);
528
248
    return _get_zval_ptr_ptr_var(node.var EXECUTE_DATA_CC);
529
248
  }
530
310
}
531
532
static inline ZEND_ATTRIBUTE_UNUSED zval *_get_obj_zval_ptr(int op_type, znode_op op, int type EXECUTE_DATA_DC OPLINE_DC)
533
0
{
534
0
  if (op_type == IS_UNUSED) {
535
0
    return &EX(This);
536
0
  }
537
0
  return get_zval_ptr(op_type, op, type);
538
0
}
539
540
static inline ZEND_ATTRIBUTE_UNUSED zval *_get_obj_zval_ptr_deref(int op_type, znode_op op, int type EXECUTE_DATA_DC OPLINE_DC)
541
0
{
542
0
  if (op_type == IS_UNUSED) {
543
0
    return &EX(This);
544
0
  }
545
0
  return get_zval_ptr_deref(op_type, op, type);
546
0
}
547
548
static inline ZEND_ATTRIBUTE_UNUSED zval *_get_obj_zval_ptr_undef(int op_type, znode_op op, int type EXECUTE_DATA_DC OPLINE_DC)
549
0
{
550
0
  if (op_type == IS_UNUSED) {
551
0
    return &EX(This);
552
0
  }
553
0
  return get_zval_ptr_undef(op_type, op, type);
554
0
}
555
556
static inline ZEND_ATTRIBUTE_UNUSED zval *_get_obj_zval_ptr_ptr(int op_type, znode_op node, int type EXECUTE_DATA_DC)
557
0
{
558
0
  if (op_type == IS_UNUSED) {
559
0
    return &EX(This);
560
0
  }
561
0
  return get_zval_ptr_ptr(op_type, node, type);
562
0
}
563
564
static inline void zend_assign_to_variable_reference(zval *variable_ptr, zval *value_ptr, zend_refcounted **garbage_ptr)
565
24.4k
{
566
24.4k
  zend_reference *ref;
567
568
24.4k
  if (EXPECTED(!Z_ISREF_P(value_ptr))) {
569
7.31k
    ZVAL_NEW_REF(value_ptr, value_ptr);
570
17.1k
  } else if (UNEXPECTED(variable_ptr == value_ptr)) {
571
2.90k
    return;
572
2.90k
  }
573
574
21.5k
  ref = Z_REF_P(value_ptr);
575
21.5k
  GC_ADDREF(ref);
576
21.5k
  if (Z_REFCOUNTED_P(variable_ptr)) {
577
9.72k
    *garbage_ptr = Z_COUNTED_P(variable_ptr);
578
9.72k
  }
579
21.5k
  ZVAL_REF(variable_ptr, ref);
580
21.5k
}
581
582
static zend_never_inline zval* zend_assign_to_typed_property_reference(zend_property_info *prop_info, zval *prop, zval *value_ptr, zend_refcounted **garbage_ptr EXECUTE_DATA_DC)
583
1.11k
{
584
1.11k
  if (!zend_verify_prop_assignable_by_ref(prop_info, value_ptr, EX_USES_STRICT_TYPES())) {
585
216
    return &EG(uninitialized_zval);
586
216
  }
587
894
  if (Z_ISREF_P(prop)) {
588
534
    ZEND_REF_DEL_TYPE_SOURCE(Z_REF_P(prop), prop_info);
589
534
  }
590
894
  zend_assign_to_variable_reference(prop, value_ptr, garbage_ptr);
591
894
  ZEND_REF_ADD_TYPE_SOURCE(Z_REF_P(prop), prop_info);
592
894
  return prop;
593
1.11k
}
594
595
static zend_never_inline ZEND_COLD zval *zend_wrong_assign_to_variable_reference(zval *variable_ptr, zval *value_ptr, zend_refcounted **garbage_ptr OPLINE_DC EXECUTE_DATA_DC)
596
77
{
597
77
  zend_error(E_NOTICE, "Only variables should be assigned by reference");
598
77
  if (UNEXPECTED(EG(exception) != NULL)) {
599
0
    return &EG(uninitialized_zval);
600
0
  }
601
602
  /* Use IS_TMP_VAR instead of IS_VAR to avoid ISREF check */
603
77
  Z_TRY_ADDREF_P(value_ptr);
604
77
  return zend_assign_to_variable_ex(variable_ptr, value_ptr, IS_TMP_VAR, EX_USES_STRICT_TYPES(), garbage_ptr);
605
77
}
606
607
ZEND_API zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_cannot_pass_by_reference(uint32_t arg_num)
608
128
{
609
128
  const zend_execute_data *execute_data = EG(current_execute_data);
610
128
  zend_string *func_name = get_function_or_method_name(EX(call)->func);
611
128
  const char *param_name = get_function_arg_name(EX(call)->func, arg_num);
612
613
128
  zend_throw_error(NULL, "%s(): Argument #%d%s%s%s could not be passed by reference",
614
128
    ZSTR_VAL(func_name), arg_num, param_name ? " ($" : "", param_name ? param_name : "", param_name ? ")" : ""
615
128
  );
616
617
128
  zend_string_release(func_name);
618
128
}
619
620
35
static zend_never_inline ZEND_COLD void zend_throw_auto_init_in_prop_error(const zend_property_info *prop) {
621
35
  zend_string *type_str = zend_type_to_string(prop->type);
622
35
  zend_type_error(
623
35
    "Cannot auto-initialize an array inside property %s::$%s of type %s",
624
35
    ZSTR_VAL(prop->ce->name), zend_get_unmangled_property_name(prop->name),
625
35
    ZSTR_VAL(type_str)
626
35
  );
627
35
  zend_string_release(type_str);
628
35
}
629
630
13
static zend_never_inline ZEND_COLD void zend_throw_auto_init_in_ref_error(const zend_property_info *prop) {
631
13
  zend_string *type_str = zend_type_to_string(prop->type);
632
13
  zend_type_error(
633
13
    "Cannot auto-initialize an array inside a reference held by property %s::$%s of type %s",
634
13
    ZSTR_VAL(prop->ce->name), zend_get_unmangled_property_name(prop->name),
635
13
    ZSTR_VAL(type_str)
636
13
  );
637
13
  zend_string_release(type_str);
638
13
}
639
640
static zend_never_inline ZEND_COLD void zend_throw_access_uninit_prop_by_ref_error(
641
17
    const zend_property_info *prop) {
642
17
  zend_throw_error(NULL,
643
17
    "Cannot access uninitialized non-nullable property %s::$%s by reference",
644
17
    ZSTR_VAL(prop->ce->name),
645
17
    zend_get_unmangled_property_name(prop->name));
646
17
}
647
648
/* this should modify object only if it's empty */
649
static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_throw_non_object_error(const zval *object, const zval *property OPLINE_DC EXECUTE_DATA_DC)
650
1.14k
{
651
1.14k
  zend_string *tmp_property_name;
652
1.14k
  zend_string *property_name = zval_get_tmp_string(property, &tmp_property_name);
653
654
1.14k
  if (opline->opcode == ZEND_PRE_INC_OBJ
655
1.06k
   || opline->opcode == ZEND_PRE_DEC_OBJ
656
1.03k
   || opline->opcode == ZEND_POST_INC_OBJ
657
994
   || opline->opcode == ZEND_POST_DEC_OBJ) {
658
154
    zend_throw_error(NULL,
659
154
      "Attempt to increment/decrement property \"%s\" on %s",
660
154
      ZSTR_VAL(property_name), zend_zval_value_name(object)
661
154
    );
662
989
  } else if (opline->opcode == ZEND_FETCH_OBJ_W
663
816
      || opline->opcode == ZEND_FETCH_OBJ_RW
664
774
      || opline->opcode == ZEND_FETCH_OBJ_FUNC_ARG
665
770
      || opline->opcode == ZEND_ASSIGN_OBJ_REF) {
666
284
    zend_throw_error(NULL,
667
284
      "Attempt to modify property \"%s\" on %s",
668
284
      ZSTR_VAL(property_name), zend_zval_value_name(object)
669
284
    );
670
705
  } else {
671
705
    zend_throw_error(NULL,
672
705
      "Attempt to assign property \"%s\" on %s",
673
705
      ZSTR_VAL(property_name), zend_zval_value_name(object)
674
705
    );
675
705
  }
676
1.14k
  zend_tmp_string_release(tmp_property_name);
677
678
1.14k
  if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
679
491
    ZVAL_NULL(EX_VAR(opline->result.var));
680
491
  }
681
1.14k
}
682
683
static zend_never_inline ZEND_COLD void zend_verify_type_error_common(
684
    const zend_function *zf, const zend_arg_info *arg_info, const zval *value,
685
    const char **fname, const char **fsep, const char **fclass,
686
    zend_string **need_msg, const char **given_kind)
687
1.27k
{
688
1.27k
  *fname = ZSTR_VAL(zf->common.function_name);
689
1.27k
  if (zf->common.scope) {
690
367
    *fsep =  "::";
691
367
    *fclass = ZSTR_VAL(zf->common.scope->name);
692
906
  } else {
693
906
    *fsep =  "";
694
906
    *fclass = "";
695
906
  }
696
697
1.27k
  *need_msg = zend_type_to_string_resolved(arg_info->type, zf->common.scope);
698
699
1.27k
  if (value) {
700
1.18k
    *given_kind = zend_zval_value_name(value);
701
1.18k
  } else {
702
92
    *given_kind = "none";
703
92
  }
704
1.27k
}
705
706
ZEND_API zend_never_inline ZEND_COLD void zend_verify_arg_error(
707
    const zend_function *zf, const zend_arg_info *arg_info, uint32_t arg_num, const zval *value)
708
847
{
709
847
  const zend_execute_data *ptr = EG(current_execute_data)->prev_execute_data;
710
847
  const char *fname, *fsep, *fclass;
711
847
  zend_string *need_msg;
712
847
  const char *given_msg;
713
714
847
  zend_verify_type_error_common(
715
847
    zf, arg_info, value, &fname, &fsep, &fclass, &need_msg, &given_msg);
716
717
847
  ZEND_ASSERT(zf->common.type == ZEND_USER_FUNCTION
718
847
    && "Arginfo verification is not performed for internal functions");
719
847
  if (ptr && ptr->func && ZEND_USER_CODE(ptr->func->common.type)) {
720
816
    zend_argument_type_error(arg_num, "must be of type %s, %s given, called in %s on line %d",
721
816
      ZSTR_VAL(need_msg), given_msg,
722
816
      ZSTR_VAL(ptr->func->op_array.filename), ptr->opline->lineno
723
816
    );
724
816
  } else {
725
31
    zend_argument_type_error(arg_num,
726
31
      "must be of type %s, %s given", ZSTR_VAL(need_msg), given_msg);
727
31
  }
728
729
847
  zend_string_release(need_msg);
730
847
}
731
732
static bool zend_verify_weak_scalar_type_hint(uint32_t type_mask, zval *arg)
733
3.62k
{
734
3.62k
  zend_long lval;
735
3.62k
  double dval;
736
737
  /* Type preference order: int -> float -> string -> bool */
738
3.62k
  if (type_mask & MAY_BE_LONG) {
739
    /* For an int|float union type and string value,
740
     * determine chosen type by is_numeric_string() semantics. */
741
1.60k
    if ((type_mask & MAY_BE_DOUBLE) && Z_TYPE_P(arg) == IS_STRING) {
742
117
      uint8_t type = is_numeric_str_function(Z_STR_P(arg), &lval, &dval);
743
117
      if (type == IS_LONG) {
744
22
        zend_string_release(Z_STR_P(arg));
745
22
        ZVAL_LONG(arg, lval);
746
22
        return true;
747
22
      }
748
95
      if (type == IS_DOUBLE) {
749
25
        zend_string_release(Z_STR_P(arg));
750
25
        ZVAL_DOUBLE(arg, dval);
751
25
        return true;
752
25
      }
753
1.49k
    } else if (zend_parse_arg_long_weak(arg, &lval, 0)) {
754
968
      zval_ptr_dtor(arg);
755
968
      ZVAL_LONG(arg, lval);
756
968
      return true;
757
968
    } else if (UNEXPECTED(EG(exception))) {
758
0
      return false;
759
0
    }
760
1.60k
  }
761
2.61k
  if (type_mask & MAY_BE_DOUBLE) {
762
446
    dval = zend_parse_arg_double_weak(arg, 0);
763
446
    if (EXPECTED(!zend_isnan(dval))) {
764
267
      zval_ptr_dtor(arg);
765
267
      ZVAL_DOUBLE(arg, dval);
766
267
      return true;
767
267
    }
768
446
  }
769
2.34k
  if ((type_mask & MAY_BE_STRING) && zend_parse_arg_str_weak(arg, 0)) {
770
    /* on success "arg" is converted to IS_STRING */
771
716
    return true;
772
716
  }
773
1.62k
  if ((type_mask & MAY_BE_BOOL) == MAY_BE_BOOL) {
774
73
    zpp_parse_bool_status bval = zend_parse_arg_bool_weak(arg, 0);
775
73
    if (UNEXPECTED(bval == ZPP_PARSE_BOOL_STATUS_ERROR)) {
776
0
      return false;
777
0
    }
778
73
    zval_ptr_dtor(arg);
779
73
    ZVAL_BOOL(arg, bval);
780
73
    return true;
781
73
  }
782
1.55k
  return false;
783
1.62k
}
784
785
#if ZEND_DEBUG
786
4.06k
static bool can_convert_to_string(const zval *zv) {
787
  /* We don't call cast_object here, because this check must be side-effect free. As this
788
   * is only used for a sanity check of arginfo/zpp consistency, it's okay if we accept
789
   * more than actually allowed here. */
790
4.06k
  if (Z_TYPE_P(zv) == IS_OBJECT) {
791
1.05k
    return Z_OBJ_HT_P(zv)->cast_object != zend_std_cast_object_tostring
792
1.05k
      || Z_OBJCE_P(zv)->__tostring;
793
1.05k
  }
794
3.01k
  return Z_TYPE_P(zv) <= IS_STRING;
795
4.06k
}
796
797
/* Used to sanity-check internal arginfo types without performing any actual type conversions. */
798
static bool zend_verify_weak_scalar_type_hint_no_sideeffect(uint32_t type_mask, const zval *arg)
799
7.33k
{
800
7.33k
  zend_long lval;
801
802
  /* Pass (uint32_t)-1 as arg_num to indicate to ZPP not to emit any deprecation notice,
803
   * this is needed because the version with side effects also uses 0 (e.g. for typed properties) */
804
7.33k
  if ((type_mask & MAY_BE_LONG) && zend_parse_arg_long_weak(arg, &lval, (uint32_t)-1)) {
805
505
    return true;
806
505
  }
807
6.82k
  if ((type_mask & MAY_BE_DOUBLE) && !zend_isnan(zend_parse_arg_double_weak(arg, (uint32_t)-1))) {
808
736
    return true;
809
736
  }
810
6.09k
  if ((type_mask & MAY_BE_STRING) && can_convert_to_string(arg)) {
811
4.00k
    return true;
812
4.00k
  }
813
2.08k
  if ((type_mask & MAY_BE_BOOL) == MAY_BE_BOOL && zend_parse_arg_bool_weak(arg, (uint32_t)-1) != ZPP_PARSE_BOOL_STATUS_ERROR) {
814
1.68k
    return true;
815
1.68k
  }
816
398
  return false;
817
2.08k
}
818
#endif
819
820
ZEND_API bool zend_verify_scalar_type_hint(uint32_t type_mask, zval *arg, bool strict, bool is_internal_arg)
821
17.2k
{
822
17.2k
  if (UNEXPECTED(strict)) {
823
    /* SSTH Exception: IS_LONG may be accepted as IS_DOUBLE (converted) */
824
374
    if (!(type_mask & MAY_BE_DOUBLE) || Z_TYPE_P(arg) != IS_LONG) {
825
369
      return 0;
826
369
    }
827
16.9k
  } else if (UNEXPECTED(Z_TYPE_P(arg) == IS_NULL)) {
828
    /* NULL may be accepted only by nullable hints (this is already checked).
829
     * As an exception for internal functions, null is allowed for scalar types in weak mode. */
830
6.37k
    return is_internal_arg
831
6.12k
      && (type_mask & (MAY_BE_TRUE|MAY_BE_FALSE|MAY_BE_LONG|MAY_BE_DOUBLE|MAY_BE_STRING));
832
6.37k
  }
833
10.5k
#if ZEND_DEBUG
834
10.5k
  if (is_internal_arg) {
835
7.33k
    return zend_verify_weak_scalar_type_hint_no_sideeffect(type_mask, arg);
836
7.33k
  }
837
3.21k
#endif
838
3.21k
  return zend_verify_weak_scalar_type_hint(type_mask, arg);
839
10.5k
}
840
841
static zend_never_inline ZEND_COLD void zend_verify_class_constant_type_error(const zend_class_constant *c, const zend_string *name, const zval *constant)
842
73
{
843
73
  zend_string *type_str = zend_type_to_string(c->type);
844
845
73
  zend_type_error("Cannot assign %s to class constant %s::%s of type %s",
846
73
    zend_zval_type_name(constant), ZSTR_VAL(c->ce->name), ZSTR_VAL(name), ZSTR_VAL(type_str));
847
848
73
  zend_string_release(type_str);
849
73
}
850
851
static zend_never_inline ZEND_COLD void zend_verify_property_type_error(const zend_property_info *info, const zval *property)
852
765
{
853
765
  zend_string *type_str;
854
855
  /* we _may_ land here in case reading already errored and runtime cache thus has not been updated (i.e. it contains a valid but unrelated info) */
856
765
  if (EG(exception)) {
857
20
    return;
858
20
  }
859
860
745
  type_str = zend_type_to_string(info->type);
861
745
  zend_type_error("Cannot assign %s to property %s::$%s of type %s",
862
745
    zend_zval_value_name(property),
863
745
    ZSTR_VAL(info->ce->name),
864
745
    zend_get_unmangled_property_name(info->name),
865
745
    ZSTR_VAL(type_str));
866
745
  zend_string_release(type_str);
867
745
}
868
869
static zend_never_inline ZEND_COLD void zend_magic_get_property_type_inconsistency_error(const zend_property_info *info, const zval *property)
870
22
{
871
  /* we _may_ land here in case reading already errored and runtime cache thus has not been updated (i.e. it contains a valid but unrelated info) */
872
22
  if (EG(exception)) {
873
0
    return;
874
0
  }
875
876
22
  zend_string *type_str = zend_type_to_string(info->type);
877
22
  zend_type_error("Value of type %s returned from %s::__get() must be compatible with unset property %s::$%s of type %s",
878
22
    zend_zval_type_name(property),
879
22
    ZSTR_VAL(info->ce->name),
880
22
    ZSTR_VAL(info->ce->name),
881
22
    zend_get_unmangled_property_name(info->name),
882
22
    ZSTR_VAL(type_str));
883
22
  zend_string_release(type_str);
884
22
}
885
886
zend_never_inline ZEND_COLD void zend_match_unhandled_error(const zval *value)
887
212
{
888
212
  zend_long max_len = EG(exception_string_param_max_len);
889
212
  smart_str msg = {0};
890
212
  if (
891
212
    EG(exception_ignore_args)
892
212
    || (Z_TYPE_P(value) == IS_STRING && max_len == 0)
893
212
    || smart_str_append_zval(&msg, value, max_len) != SUCCESS
894
212
  ) {
895
10
    smart_str_appendl(&msg, "of type ", sizeof("of type ")-1);
896
10
    smart_str_appends(&msg, zend_zval_type_name(value));
897
10
  }
898
212
  smart_str_0(&msg);
899
900
212
  zend_throw_exception_ex(
901
212
    zend_ce_unhandled_match_error, 0, "Unhandled match case %s", ZSTR_VAL(msg.s));
902
903
212
  smart_str_free(&msg);
904
212
}
905
906
ZEND_API zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_readonly_property_modification_error(
907
257
    const zend_property_info *info) {
908
257
  zend_readonly_property_modification_error_ex(
909
257
    ZSTR_VAL(info->ce->name), zend_get_unmangled_property_name(info->name));
910
257
}
911
912
ZEND_API zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_readonly_property_modification_error_ex(
913
257
    const char *class_name, const char *prop_name) {
914
257
  zend_throw_error(NULL, "Cannot modify readonly property %s::$%s", class_name, prop_name);
915
257
}
916
917
ZEND_API zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_readonly_property_indirect_modification_error(const zend_property_info *info)
918
160
{
919
160
  zend_throw_error(NULL, "Cannot indirectly modify readonly property %s::$%s",
920
160
    ZSTR_VAL(info->ce->name), zend_get_unmangled_property_name(info->name));
921
160
}
922
923
ZEND_API zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_invalid_class_constant_type_error(const uint8_t type)
924
583
{
925
583
  zend_type_error("Cannot use value of type %s as class constant name", zend_get_type_by_const(type));
926
583
}
927
928
ZEND_API zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_object_released_while_assigning_to_property_error(const zend_property_info *info)
929
16
{
930
16
  zend_throw_error(NULL, "Object was released while assigning to property %s::$%s",
931
16
    ZSTR_VAL(info->ce->name), zend_get_unmangled_property_name(info->name));
932
16
}
933
934
ZEND_API zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_asymmetric_visibility_property_modification_error(
935
  const zend_property_info *prop_info, const char *operation
936
489
) {
937
489
  const zend_class_entry *scope;
938
489
  if (EG(fake_scope)) {
939
8
    scope = EG(fake_scope);
940
481
  } else {
941
481
    scope = zend_get_called_scope(EG(current_execute_data));
942
481
  }
943
944
489
  const char *visibility;
945
489
  if (prop_info->flags & ZEND_ACC_PRIVATE_SET) {
946
424
    visibility = "private(set)";
947
424
  } else {
948
65
    ZEND_ASSERT(prop_info->flags & ZEND_ACC_PROTECTED_SET);
949
65
    if (prop_info->flags & ZEND_ACC_READONLY) {
950
42
      visibility = "protected(set) readonly";
951
42
    } else {
952
23
      visibility = "protected(set)";
953
23
    }
954
65
  }
955
956
489
  zend_throw_error(NULL, "Cannot %s %s property %s::$%s from %s%s",
957
489
    operation,
958
489
    visibility,
959
489
    ZSTR_VAL(prop_info->ce->name),
960
489
    ZSTR_VAL(prop_info->name),
961
489
    scope ? "scope " : "global scope", scope ? ZSTR_VAL(scope->name) : "");
962
489
}
963
964
84
static const zend_class_entry *resolve_single_class_type(zend_string *name, const zend_class_entry *self_ce) {
965
84
  if (zend_string_equals_ci(name, ZSTR_KNOWN(ZEND_STR_SELF))) {
966
37
    return self_ce;
967
47
  } else if (zend_string_equals_ci(name, ZSTR_KNOWN(ZEND_STR_PARENT))) {
968
24
    return self_ce->parent;
969
24
  } else {
970
23
    return zend_lookup_class_ex(name, NULL, ZEND_FETCH_CLASS_NO_AUTOLOAD);
971
23
  }
972
84
}
973
974
static zend_always_inline const zend_class_entry *zend_ce_from_type(
975
266k
    const zend_class_entry *scope, const zend_type *type) {
976
266k
  ZEND_ASSERT(ZEND_TYPE_HAS_NAME(*type));
977
266k
  zend_string *name = ZEND_TYPE_NAME(*type);
978
266k
  if (ZSTR_HAS_CE_CACHE(name)) {
979
266k
    zend_class_entry *ce = ZSTR_GET_CE_CACHE(name);
980
266k
    if (!ce) {
981
2.20k
      ce = zend_lookup_class_ex(name, NULL, ZEND_FETCH_CLASS_NO_AUTOLOAD);
982
2.20k
    }
983
266k
    return ce;
984
266k
  }
985
84
  return resolve_single_class_type(name, scope);
986
266k
}
987
988
static bool zend_check_intersection_for_property_or_class_constant_class_type(
989
  const zend_class_entry *scope, const zend_type_list *intersection_type_list, const zend_class_entry *value_ce)
990
191
{
991
191
  const zend_type *list_type;
992
993
541
  ZEND_TYPE_LIST_FOREACH(intersection_type_list, list_type) {
994
541
    ZEND_ASSERT(!ZEND_TYPE_HAS_LIST(*list_type));
995
541
    const zend_class_entry *ce = zend_ce_from_type(scope, list_type);
996
350
    if (!ce || !instanceof_function(value_ce, ce)) {
997
93
      return false;
998
93
    }
999
350
  } ZEND_TYPE_LIST_FOREACH_END();
1000
98
  return true;
1001
191
}
1002
1003
static bool zend_check_and_resolve_property_or_class_constant_class_type(
1004
266k
  const zend_class_entry *scope, const zend_type member_type, const zend_class_entry *value_ce) {
1005
266k
  if (ZEND_TYPE_HAS_LIST(member_type)) {
1006
264
    if (ZEND_TYPE_IS_INTERSECTION(member_type)) {
1007
101
      return zend_check_intersection_for_property_or_class_constant_class_type(
1008
101
        scope, ZEND_TYPE_LIST(member_type), value_ce);
1009
163
    } else {
1010
163
      const zend_type *list_type;
1011
399
      ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(member_type), list_type) {
1012
399
        if (ZEND_TYPE_IS_INTERSECTION(*list_type)) {
1013
90
          if (zend_check_intersection_for_property_or_class_constant_class_type(
1014
90
              scope, ZEND_TYPE_LIST(*list_type), value_ce)) {
1015
52
            return true;
1016
52
          }
1017
38
          continue;
1018
90
        }
1019
146
        ZEND_ASSERT(!ZEND_TYPE_HAS_LIST(*list_type));
1020
146
        const zend_class_entry *ce = zend_ce_from_type(scope, list_type);
1021
146
        if (ce && instanceof_function(value_ce, ce)) {
1022
58
          return true;
1023
58
        }
1024
146
      } ZEND_TYPE_LIST_FOREACH_END();
1025
1026
53
      if ((ZEND_TYPE_PURE_MASK(member_type) & MAY_BE_STATIC)) {
1027
0
        return value_ce == scope;
1028
0
      }
1029
1030
53
      return false;
1031
53
    }
1032
266k
  } else if ((ZEND_TYPE_PURE_MASK(member_type) & MAY_BE_STATIC) && value_ce == scope) {
1033
12
    return true;
1034
266k
  } else if (ZEND_TYPE_HAS_NAME(member_type)) {
1035
266k
    const zend_class_entry *ce = zend_ce_from_type(scope, &member_type);
1036
266k
    return ce && instanceof_function(value_ce, ce);
1037
266k
  }
1038
1039
6
  return false;
1040
266k
}
1041
1042
static zend_always_inline bool i_zend_check_property_type(const zend_property_info *info, zval *property, bool strict)
1043
326k
{
1044
326k
  ZEND_ASSERT(!Z_ISREF_P(property));
1045
326k
  if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(info->type, Z_TYPE_P(property)))) {
1046
78.1k
    return 1;
1047
78.1k
  }
1048
1049
248k
  if (ZEND_TYPE_IS_COMPLEX(info->type) && Z_TYPE_P(property) == IS_OBJECT
1050
247k
      && zend_check_and_resolve_property_or_class_constant_class_type(info->ce, info->type, Z_OBJCE_P(property))) {
1051
247k
    return 1;
1052
247k
  }
1053
1054
1.39k
  uint32_t type_mask = ZEND_TYPE_FULL_MASK(info->type);
1055
1.39k
  ZEND_ASSERT(!(type_mask & (MAY_BE_CALLABLE|MAY_BE_STATIC|MAY_BE_NEVER|MAY_BE_VOID)));
1056
1.39k
  return zend_verify_scalar_type_hint(type_mask, property, strict, false);
1057
1.39k
}
1058
1059
static zend_always_inline bool i_zend_verify_property_type(const zend_property_info *info, zval *property, bool strict)
1060
160k
{
1061
160k
  if (i_zend_check_property_type(info, property, strict)) {
1062
159k
    return 1;
1063
159k
  }
1064
1065
577
  zend_verify_property_type_error(info, property);
1066
577
  return 0;
1067
160k
}
1068
1069
158k
ZEND_API bool zend_never_inline zend_verify_property_type(const zend_property_info *info, zval *property, bool strict) {
1070
158k
  return i_zend_verify_property_type(info, property, strict);
1071
158k
}
1072
1073
static zend_never_inline zval* zend_assign_to_typed_prop(const zend_property_info *info, zval *property_val, zval *value, zend_refcounted **garbage_ptr EXECUTE_DATA_DC)
1074
1.59k
{
1075
1.59k
  zval tmp;
1076
1077
1.59k
  if (UNEXPECTED(info->flags & (ZEND_ACC_READONLY|ZEND_ACC_PPP_SET_MASK))) {
1078
182
    if ((info->flags & ZEND_ACC_READONLY) && !(Z_PROP_FLAG_P(property_val) & IS_PROP_REINITABLE)) {
1079
32
      zend_readonly_property_modification_error(info);
1080
32
      return &EG(uninitialized_zval);
1081
32
    }
1082
150
    if (info->flags & ZEND_ACC_PPP_SET_MASK && !zend_asymmetric_property_has_set_access(info)) {
1083
23
      zend_asymmetric_visibility_property_modification_error(info, "modify");
1084
23
      return &EG(uninitialized_zval);
1085
23
    }
1086
150
  }
1087
1088
1.53k
  ZVAL_DEREF(value);
1089
1.53k
  ZVAL_COPY(&tmp, value);
1090
1091
1.53k
  if (UNEXPECTED(!i_zend_verify_property_type(info, &tmp, EX_USES_STRICT_TYPES()))) {
1092
90
    zval_ptr_dtor(&tmp);
1093
90
    return &EG(uninitialized_zval);
1094
90
  }
1095
1096
1.44k
  Z_PROP_FLAG_P(property_val) &= ~IS_PROP_REINITABLE;
1097
1098
1.44k
  return zend_assign_to_variable_ex(property_val, &tmp, IS_TMP_VAR, EX_USES_STRICT_TYPES(), garbage_ptr);
1099
1.53k
}
1100
1101
259
static zend_always_inline bool zend_value_instanceof_static(const zval *zv) {
1102
259
  if (Z_TYPE_P(zv) != IS_OBJECT) {
1103
0
    return 0;
1104
0
  }
1105
1106
259
  zend_class_entry *called_scope = zend_get_called_scope(EG(current_execute_data));
1107
259
  if (!called_scope) {
1108
5
    return 0;
1109
5
  }
1110
254
  return instanceof_function(Z_OBJCE_P(zv), called_scope);
1111
259
}
1112
1113
static zend_always_inline zend_class_entry *zend_fetch_ce_from_type(
1114
    const zend_type *type)
1115
45.7k
{
1116
45.7k
  zend_string *name = ZEND_TYPE_NAME(*type);
1117
45.7k
  zend_class_entry *ce;
1118
45.7k
  if (ZSTR_HAS_CE_CACHE(name)) {
1119
45.5k
    ce = ZSTR_GET_CE_CACHE(name);
1120
45.5k
    if (!ce) {
1121
4.09k
      ce = zend_lookup_class_ex(name, NULL, ZEND_FETCH_CLASS_NO_AUTOLOAD);
1122
4.09k
      if (UNEXPECTED(!ce)) {
1123
        /* Cannot resolve */
1124
96
        return NULL;
1125
96
      }
1126
4.09k
    }
1127
45.5k
  } else {
1128
180
    ce = zend_fetch_class(name,
1129
180
      ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD | ZEND_FETCH_CLASS_SILENT);
1130
180
    if (UNEXPECTED(!ce)) {
1131
5
      return NULL;
1132
5
    }
1133
180
  }
1134
45.6k
  return ce;
1135
45.7k
}
1136
1137
static bool zend_check_intersection_type_from_list(
1138
  const zend_type_list *intersection_type_list,
1139
  zend_class_entry *arg_ce)
1140
512
{
1141
512
  zend_class_entry *ce;
1142
512
  const zend_type *list_type;
1143
1.36k
  ZEND_TYPE_LIST_FOREACH(intersection_type_list, list_type) {
1144
1.36k
    ce = zend_fetch_ce_from_type(list_type);
1145
    /* If type is not an instance of one of the types taking part in the
1146
     * intersection it cannot be a valid instance of the whole intersection type. */
1147
1.36k
    if (!ce || !instanceof_function(arg_ce, ce)) {
1148
225
      return false;
1149
225
    }
1150
1.36k
  } ZEND_TYPE_LIST_FOREACH_END();
1151
287
  return true;
1152
512
}
1153
1154
static zend_always_inline bool zend_check_type_slow(
1155
    const zend_type *type, zval *arg, const zend_reference *ref,
1156
    bool current_frame, bool is_internal)
1157
69.6k
{
1158
69.6k
  if (ZEND_TYPE_IS_COMPLEX(*type) && EXPECTED(Z_TYPE_P(arg) == IS_OBJECT)) {
1159
45.1k
    zend_class_entry *ce;
1160
45.1k
    if (UNEXPECTED(ZEND_TYPE_HAS_LIST(*type))) {
1161
504
      if (ZEND_TYPE_IS_INTERSECTION(*type)) {
1162
70
        return zend_check_intersection_type_from_list(ZEND_TYPE_LIST(*type), Z_OBJCE_P(arg));
1163
434
      } else {
1164
434
        const zend_type *list_type;
1165
1.10k
        ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(*type), list_type) {
1166
1.10k
          if (ZEND_TYPE_IS_INTERSECTION(*list_type)) {
1167
442
            if (zend_check_intersection_type_from_list(ZEND_TYPE_LIST(*list_type), Z_OBJCE_P(arg))) {
1168
232
              return true;
1169
232
            }
1170
442
          } else {
1171
229
            ZEND_ASSERT(!ZEND_TYPE_HAS_LIST(*list_type));
1172
229
            ce = zend_fetch_ce_from_type(list_type);
1173
            /* Instance of a single type part of a union is sufficient to pass the type check */
1174
229
            if (ce && instanceof_function(Z_OBJCE_P(arg), ce)) {
1175
82
              return true;
1176
82
            }
1177
229
          }
1178
1.10k
        } ZEND_TYPE_LIST_FOREACH_END();
1179
434
      }
1180
44.6k
    } else {
1181
44.6k
      ce = zend_fetch_ce_from_type(type);
1182
      /* If we have a CE we check if it satisfies the type constraint,
1183
       * otherwise it will check if a standard type satisfies it. */
1184
44.6k
      if (ce && instanceof_function(Z_OBJCE_P(arg), ce)) {
1185
44.4k
        return true;
1186
44.4k
      }
1187
44.6k
    }
1188
45.1k
  }
1189
1190
24.7k
  const uint32_t type_mask = ZEND_TYPE_FULL_MASK(*type);
1191
24.7k
  if ((type_mask & MAY_BE_CALLABLE) &&
1192
8.92k
    zend_is_callable(arg, is_internal ? IS_CALLABLE_SUPPRESS_DEPRECATIONS : 0, NULL)) {
1193
8.67k
    return 1;
1194
8.67k
  }
1195
16.0k
  if ((type_mask & MAY_BE_STATIC) && zend_value_instanceof_static(arg)) {
1196
221
    return 1;
1197
221
  }
1198
15.8k
  if (ref && ZEND_REF_HAS_TYPE_SOURCES(ref)) {
1199
    /* We cannot have conversions for typed refs. */
1200
9
    return 0;
1201
9
  }
1202
15.8k
  if (is_internal && current_frame) {
1203
    /* For internal returns, the type has to match exactly, because we're not
1204
     * going to check it for non-debug builds, and there will be no chance to
1205
     * apply coercions. */
1206
0
    return 0;
1207
0
  }
1208
1209
15.8k
  return zend_verify_scalar_type_hint(type_mask, arg,
1210
15.8k
    current_frame ? ZEND_RET_USES_STRICT_TYPES() : ZEND_ARG_USES_STRICT_TYPES(),
1211
15.8k
    is_internal);
1212
1213
  /* Special handling for IS_VOID is not necessary (for return types),
1214
   * because this case is already checked at compile-time. */
1215
15.8k
}
1216
1217
static zend_always_inline bool zend_check_type(
1218
    const zend_type *type, zval *arg, bool current_frame, bool is_internal)
1219
2.25M
{
1220
2.25M
  const zend_reference *ref = NULL;
1221
2.25M
  ZEND_ASSERT(ZEND_TYPE_IS_SET(*type));
1222
1223
2.25M
  if (UNEXPECTED(Z_ISREF_P(arg))) {
1224
6.63k
    ref = Z_REF_P(arg);
1225
6.63k
    arg = Z_REFVAL_P(arg);
1226
6.63k
  }
1227
1228
2.25M
  if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(*type, Z_TYPE_P(arg)))) {
1229
2.18M
    return 1;
1230
2.18M
  }
1231
1232
68.6k
  return zend_check_type_slow(type, arg, ref, current_frame, is_internal);
1233
2.25M
}
1234
1235
/* We can not expose zend_check_type() directly because it's inline and uses static functions */
1236
ZEND_API bool zend_check_type_ex(
1237
    const zend_type *type, zval *arg, bool current_frame, bool is_internal)
1238
139
{
1239
139
  return zend_check_type(type, arg, current_frame, is_internal);
1240
139
}
1241
1242
ZEND_API bool zend_check_user_type_slow(
1243
    const zend_type *type, zval *arg, const zend_reference *ref, bool current_frame)
1244
0
{
1245
0
  return zend_check_type_slow(
1246
0
    type, arg, ref, current_frame, /* is_internal */ false);
1247
0
}
1248
1249
static zend_always_inline bool zend_verify_recv_arg_type(const zend_function *zf, uint32_t arg_num, zval *arg)
1250
7.52k
{
1251
7.52k
  const zend_arg_info *cur_arg_info;
1252
1253
7.52k
  ZEND_ASSERT(arg_num <= zf->common.num_args);
1254
7.52k
  cur_arg_info = &zf->common.arg_info[arg_num-1];
1255
1256
7.52k
  if (ZEND_TYPE_IS_SET(cur_arg_info->type)
1257
7.49k
      && UNEXPECTED(!zend_check_type(&cur_arg_info->type, arg, false, false))) {
1258
811
    zend_verify_arg_error(zf, cur_arg_info, arg_num, arg);
1259
811
    return 0;
1260
811
  }
1261
1262
6.71k
  return 1;
1263
7.52k
}
1264
1265
static zend_always_inline bool zend_verify_variadic_arg_type(
1266
    const zend_function *zf, const zend_arg_info *arg_info, uint32_t arg_num, zval *arg)
1267
250
{
1268
250
  ZEND_ASSERT(ZEND_TYPE_IS_SET(arg_info->type));
1269
250
  if (UNEXPECTED(!zend_check_type(&arg_info->type, arg, false, false))) {
1270
36
    zend_verify_arg_error(zf, arg_info, arg_num, arg);
1271
36
    return 0;
1272
36
  }
1273
1274
214
  return 1;
1275
250
}
1276
1277
static zend_never_inline ZEND_ATTRIBUTE_UNUSED bool zend_verify_internal_arg_types(const zend_function *fbc, zend_execute_data *call)
1278
1.37M
{
1279
1.37M
  uint32_t i;
1280
1.37M
  uint32_t num_args = ZEND_CALL_NUM_ARGS(call);
1281
1.37M
  zval *arg = ZEND_CALL_ARG(call, 1);
1282
1283
3.20M
  for (i = 0; i < num_args; ++i) {
1284
1.82M
    zend_arg_info *cur_arg_info;
1285
1.82M
    if (EXPECTED(i < fbc->common.num_args)) {
1286
1.81M
      cur_arg_info = &fbc->common.arg_info[i];
1287
1.81M
    } else if (UNEXPECTED(fbc->common.fn_flags & ZEND_ACC_VARIADIC)) {
1288
10.0k
      cur_arg_info = &fbc->common.arg_info[fbc->common.num_args];
1289
10.0k
    } else {
1290
0
      break;
1291
0
    }
1292
1293
1.82M
    if (ZEND_TYPE_IS_SET(cur_arg_info->type)
1294
1.82M
        && UNEXPECTED(!zend_check_type(&cur_arg_info->type, arg, false, /* is_internal */ true))) {
1295
690
      return 0;
1296
690
    }
1297
1.82M
    arg++;
1298
1.82M
  }
1299
1.37M
  return 1;
1300
1.37M
}
1301
1302
#if ZEND_DEBUG
1303
/* Determine whether an internal call should throw, because the passed arguments violate
1304
 * an arginfo constraint. This is only checked in debug builds. In release builds, we
1305
 * trust that arginfo matches what is enforced by zend_parse_parameters. */
1306
ZEND_API bool zend_internal_call_should_throw(const zend_function *fbc, zend_execute_data *call)
1307
1.56M
{
1308
1.56M
  if (fbc->internal_function.handler == ZEND_FN(pass) || (fbc->internal_function.fn_flags & ZEND_ACC_FAKE_CLOSURE)) {
1309
    /* Be lenient about the special pass function and about fake closures. */
1310
859
    return 0;
1311
859
  }
1312
1313
1.56M
  if (fbc->common.required_num_args > ZEND_CALL_NUM_ARGS(call)) {
1314
    /* Required argument not passed. */
1315
357
    return 1;
1316
357
  }
1317
1318
1.56M
  if (fbc->common.num_args < ZEND_CALL_NUM_ARGS(call)
1319
6.67k
      && !(fbc->common.fn_flags & ZEND_ACC_VARIADIC)) {
1320
    /* Too many arguments passed. For internal functions (unlike userland functions),
1321
     * this should always throw. */
1322
165
    return 1;
1323
165
  }
1324
1325
1.56M
  if ((fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) &&
1326
1.37M
      !zend_verify_internal_arg_types(fbc, call)) {
1327
690
    zend_clear_exception();
1328
690
    return 1;
1329
690
  }
1330
1331
1.56M
  return 0;
1332
1.56M
}
1333
1334
ZEND_API zend_never_inline ZEND_COLD void zend_internal_call_arginfo_violation(const zend_function *fbc)
1335
0
{
1336
0
  zend_error_noreturn(E_ERROR, "Arginfo / zpp mismatch during call of %s%s%s()",
1337
0
    fbc->common.scope ? ZSTR_VAL(fbc->common.scope->name) : "",
1338
0
    fbc->common.scope ? "::" : "",
1339
0
    ZSTR_VAL(fbc->common.function_name));
1340
0
}
1341
1342
#ifndef ZEND_VERIFY_FUNC_INFO
1343
# define ZEND_VERIFY_FUNC_INFO 0
1344
#endif
1345
1346
623k
static void zend_verify_internal_func_info(const zend_function *fn, const zval *retval) {
1347
#if ZEND_VERIFY_FUNC_INFO
1348
  zend_string *name = fn->common.function_name;
1349
  const uint32_t type_mask = zend_get_internal_func_info(fn, NULL, NULL);
1350
  if (!type_mask) {
1351
    return;
1352
  }
1353
1354
  /* Always check refcount of arrays, as immutable arrays are RCN. */
1355
  if (Z_REFCOUNTED_P(retval) || Z_TYPE_P(retval) == IS_ARRAY) {
1356
    if (!(type_mask & MAY_BE_RC1)) {
1357
      zend_error_noreturn(E_CORE_ERROR, "%s() missing rc1", ZSTR_VAL(name));
1358
    }
1359
    if (Z_REFCOUNT_P(retval) > 1 && !(type_mask & MAY_BE_RCN)) {
1360
      zend_error_noreturn(E_CORE_ERROR, "%s() missing rcn", ZSTR_VAL(name));
1361
    }
1362
  }
1363
1364
  const uint32_t type = 1u << Z_TYPE_P(retval);
1365
  if (!(type_mask & type)) {
1366
    zend_error_noreturn(E_CORE_ERROR, "%s() missing type %s",
1367
      ZSTR_VAL(name), zend_get_type_by_const(Z_TYPE_P(retval)));
1368
  }
1369
1370
  if (Z_TYPE_P(retval) == IS_ARRAY) {
1371
    const HashTable *ht = Z_ARRVAL_P(retval);
1372
    uint32_t num_checked = 0;
1373
    zend_string *str;
1374
    zval *val;
1375
    ZEND_HASH_FOREACH_STR_KEY_VAL(ht, str, val) {
1376
      if (str) {
1377
        if (!(type_mask & MAY_BE_ARRAY_KEY_STRING)) {
1378
          zend_error_noreturn(E_CORE_ERROR,
1379
            "%s() missing array_key_string", ZSTR_VAL(name));
1380
        }
1381
      } else {
1382
        if (!(type_mask & MAY_BE_ARRAY_KEY_LONG)) {
1383
          zend_error_noreturn(E_CORE_ERROR,
1384
            "%s() missing array_key_long", ZSTR_VAL(name));
1385
        }
1386
      }
1387
1388
      const uint32_t array_type = 1u << (Z_TYPE_P(val) + MAY_BE_ARRAY_SHIFT);
1389
      if (!(type_mask & array_type)) {
1390
        zend_error_noreturn(E_CORE_ERROR,
1391
          "%s() missing array element type %s",
1392
          ZSTR_VAL(name), zend_get_type_by_const(Z_TYPE_P(retval)));
1393
      }
1394
1395
      /* Don't check all elements of large arrays. */
1396
      if (++num_checked > 16) {
1397
        break;
1398
      }
1399
    } ZEND_HASH_FOREACH_END();
1400
  }
1401
#endif
1402
623k
}
1403
#endif
1404
1405
ZEND_API zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_missing_arg_error(const zend_execute_data *execute_data)
1406
312
{
1407
312
  const zend_execute_data *ptr = EX(prev_execute_data);
1408
1409
312
  if (ptr && ptr->func && ZEND_USER_CODE(ptr->func->common.type)) {
1410
310
    zend_throw_error(zend_ce_argument_count_error, "Too few arguments to function %s%s%s(), %d passed in %s on line %d and %s %d expected",
1411
310
      EX(func)->common.scope ? ZSTR_VAL(EX(func)->common.scope->name) : "",
1412
310
      EX(func)->common.scope ? "::" : "",
1413
310
      ZSTR_VAL(EX(func)->common.function_name),
1414
310
      EX_NUM_ARGS(),
1415
310
      ZSTR_VAL(ptr->func->op_array.filename),
1416
310
      ptr->opline->lineno,
1417
310
      EX(func)->common.required_num_args == EX(func)->common.num_args ? "exactly" : "at least",
1418
310
      EX(func)->common.required_num_args);
1419
310
  } else {
1420
2
    zend_throw_error(zend_ce_argument_count_error, "Too few arguments to function %s%s%s(), %d passed and %s %d expected",
1421
2
      EX(func)->common.scope ? ZSTR_VAL(EX(func)->common.scope->name) : "",
1422
2
      EX(func)->common.scope ? "::" : "",
1423
2
      ZSTR_VAL(EX(func)->common.function_name),
1424
2
      EX_NUM_ARGS(),
1425
2
      EX(func)->common.required_num_args == EX(func)->common.num_args ? "exactly" : "at least",
1426
2
      EX(func)->common.required_num_args);
1427
2
  }
1428
312
}
1429
1430
ZEND_API zend_never_inline ZEND_COLD void zend_verify_return_error(const zend_function *zf, const zval *value)
1431
426
{
1432
426
  const zend_arg_info *arg_info = &zf->common.arg_info[-1];
1433
426
  const char *fname, *fsep, *fclass;
1434
426
  zend_string *need_msg;
1435
426
  const char *given_msg;
1436
1437
426
  zend_verify_type_error_common(
1438
426
    zf, arg_info, value, &fname, &fsep, &fclass, &need_msg, &given_msg);
1439
1440
426
  zend_type_error("%s%s%s(): Return value must be of type %s, %s returned",
1441
426
    fclass, fsep, fname, ZSTR_VAL(need_msg), given_msg);
1442
1443
426
  zend_string_release(need_msg);
1444
426
}
1445
1446
ZEND_API zend_never_inline ZEND_COLD void zend_verify_never_error(const zend_function *zf)
1447
12
{
1448
12
  zend_string *func_name = get_function_or_method_name(zf);
1449
1450
12
  zend_type_error("%s(): never-returning %s must not implicitly return",
1451
12
    ZSTR_VAL(func_name), zf->common.scope ? "method" : "function");
1452
1453
12
  zend_string_release(func_name);
1454
12
}
1455
1456
#if ZEND_DEBUG
1457
static zend_never_inline ZEND_COLD void zend_verify_internal_return_error(const zend_function *zf, const zval *value)
1458
0
{
1459
0
  const zend_arg_info *arg_info = &zf->common.arg_info[-1];
1460
0
  const char *fname, *fsep, *fclass;
1461
0
  zend_string *need_msg;
1462
0
  const char *given_msg;
1463
1464
0
  zend_verify_type_error_common(
1465
0
    zf, arg_info, value, &fname, &fsep, &fclass, &need_msg, &given_msg);
1466
1467
0
  zend_error_noreturn(E_CORE_ERROR, "%s%s%s(): Return value must be of type %s, %s returned",
1468
0
    fclass, fsep, fname, ZSTR_VAL(need_msg), given_msg);
1469
0
}
1470
1471
static zend_never_inline ZEND_COLD void zend_verify_void_return_error(const zend_function *zf, const char *returned_msg, const char *returned_kind)
1472
0
{
1473
0
  const char *fname = ZSTR_VAL(zf->common.function_name);
1474
0
  const char *fsep;
1475
0
  const char *fclass;
1476
1477
0
  if (zf->common.scope) {
1478
0
    fsep =  "::";
1479
0
    fclass = ZSTR_VAL(zf->common.scope->name);
1480
0
  } else {
1481
0
    fsep =  "";
1482
0
    fclass = "";
1483
0
  }
1484
1485
0
  zend_type_error("%s%s%s() must not return a value, %s%s returned",
1486
0
    fclass, fsep, fname, returned_msg, returned_kind);
1487
0
}
1488
1489
ZEND_API bool zend_verify_internal_return_type(const zend_function *zf, zval *ret)
1490
1.04M
{
1491
1.04M
  const zend_arg_info *ret_info = zf->internal_function.arg_info - 1;
1492
1493
1.04M
  if (ZEND_TYPE_FULL_MASK(ret_info->type) & MAY_BE_VOID) {
1494
625k
    if (UNEXPECTED(Z_TYPE_P(ret) != IS_NULL)) {
1495
0
      zend_verify_void_return_error(zf, zend_zval_value_name(ret), "");
1496
0
      return 0;
1497
0
    }
1498
625k
    return 1;
1499
625k
  }
1500
1501
424k
  if (UNEXPECTED(!zend_check_type(&ret_info->type, ret, true, /* is_internal */ true))) {
1502
0
    zend_verify_internal_return_error(zf, ret);
1503
0
    return 0;
1504
0
  }
1505
1506
424k
  return 1;
1507
424k
}
1508
#endif
1509
1510
static zend_never_inline ZEND_COLD void zend_verify_missing_return_type(const zend_function *zf)
1511
92
{
1512
  /* VERIFY_RETURN_TYPE is not emitted for "void" functions, so this is always an error. */
1513
92
  zend_verify_return_error(zf, NULL);
1514
92
}
1515
1516
static zend_always_inline bool zend_check_class_constant_type(const zend_class_constant *c, zval *constant)
1517
265
{
1518
265
  ZEND_ASSERT(!Z_ISREF_P(constant));
1519
265
  if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(c->type, Z_TYPE_P(constant)))) {
1520
14
    return 1;
1521
14
  }
1522
1523
251
  if (((ZEND_TYPE_PURE_MASK(c->type) & MAY_BE_STATIC) || ZEND_TYPE_IS_COMPLEX(c->type)) && Z_TYPE_P(constant) == IS_OBJECT
1524
230
    && zend_check_and_resolve_property_or_class_constant_class_type(c->ce, c->type, Z_OBJCE_P(constant))) {
1525
178
    return 1;
1526
178
  }
1527
1528
73
  uint32_t type_mask = ZEND_TYPE_FULL_MASK(c->type);
1529
73
  ZEND_ASSERT(!(type_mask & (MAY_BE_CALLABLE|MAY_BE_NEVER|MAY_BE_VOID)));
1530
73
  return zend_verify_scalar_type_hint(type_mask, constant, true, false);
1531
73
}
1532
1533
ZEND_API bool zend_never_inline zend_verify_class_constant_type(const zend_class_constant *c, const zend_string *name, zval *constant)
1534
265
{
1535
265
  if (!zend_check_class_constant_type(c, constant)) {
1536
73
    zend_verify_class_constant_type_error(c, name, constant);
1537
73
    return 0;
1538
73
  }
1539
1540
192
  return 1;
1541
265
}
1542
1543
static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_use_object_as_array(const zend_object *object)
1544
11
{
1545
11
  zend_throw_error(NULL, "Cannot use object of type %s as array", ZSTR_VAL(object->ce->name));
1546
11
}
1547
1548
static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_illegal_array_offset_access(const zval *offset)
1549
163
{
1550
163
  zend_illegal_container_offset(ZSTR_KNOWN(ZEND_STR_ARRAY), offset, BP_VAR_RW);
1551
163
}
1552
1553
static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_illegal_array_offset_isset(const zval *offset)
1554
35
{
1555
35
  zend_illegal_container_offset(ZSTR_KNOWN(ZEND_STR_ARRAY), offset, BP_VAR_IS);
1556
35
}
1557
1558
static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_illegal_array_offset_unset(const zval *offset)
1559
9
{
1560
9
  zend_illegal_container_offset(ZSTR_KNOWN(ZEND_STR_ARRAY), offset, BP_VAR_UNSET);
1561
9
}
1562
1563
static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_illegal_string_offset(const zval *offset, int type)
1564
343
{
1565
343
  zend_illegal_container_offset(ZSTR_KNOWN(ZEND_STR_STRING), offset, type);
1566
343
}
1567
1568
static zend_never_inline void zend_assign_to_object_dim(zend_object *obj, zval *dim, zval *value OPLINE_DC EXECUTE_DATA_DC)
1569
1.96k
{
1570
1.96k
  obj->handlers->write_dimension(obj, dim, value);
1571
1572
1.96k
  if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
1573
101
    ZVAL_COPY(EX_VAR(opline->result.var), value);
1574
101
  }
1575
1.96k
}
1576
1577
static void frameless_observed_call_copy(zend_execute_data *call, uint32_t arg, zval *zv)
1578
0
{
1579
0
  if (Z_ISUNDEF_P(zv)) {
1580
0
    ZVAL_NULL(ZEND_CALL_VAR_NUM(call, arg));
1581
0
  } else {
1582
0
    ZVAL_COPY_DEREF(ZEND_CALL_VAR_NUM(call, arg), zv);
1583
0
  }
1584
0
}
1585
1586
ZEND_API void zend_frameless_observed_call(zend_execute_data *execute_data)
1587
0
{
1588
0
  const zend_op *opline = EX(opline);
1589
0
  uint8_t num_args = ZEND_FLF_NUM_ARGS(opline->opcode);
1590
0
  zend_function *fbc = ZEND_FLF_FUNC(opline);
1591
0
  zval *result = EX_VAR(opline->result.var);
1592
1593
0
  zend_execute_data *call = zend_vm_stack_push_call_frame_ex(zend_vm_calc_used_stack(num_args, fbc), ZEND_CALL_NESTED_FUNCTION, fbc, num_args, NULL);
1594
0
  call->prev_execute_data = execute_data;
1595
1596
0
  switch (num_args) {
1597
0
    case 3: frameless_observed_call_copy(call, 2, zend_get_zval_ptr(opline+1, (opline+1)->op1_type, &(opline+1)->op1, execute_data)); ZEND_FALLTHROUGH;
1598
0
    case 2: frameless_observed_call_copy(call, 1, zend_get_zval_ptr(opline, opline->op2_type, &opline->op2, execute_data)); ZEND_FALLTHROUGH;
1599
0
    case 1: frameless_observed_call_copy(call, 0, zend_get_zval_ptr(opline, opline->op1_type, &opline->op1, execute_data));
1600
0
  }
1601
1602
0
  EG(current_execute_data) = call;
1603
1604
0
  zend_observer_fcall_begin_prechecked(call, ZEND_OBSERVER_DATA(fbc));
1605
0
  fbc->internal_function.handler(call, result);
1606
0
  zend_observer_fcall_end(call, result);
1607
1608
0
  EG(current_execute_data) = execute_data;
1609
1610
0
  if (UNEXPECTED(EG(exception) != NULL)) {
1611
0
    zend_rethrow_exception(execute_data);
1612
0
  }
1613
1614
0
  zend_vm_stack_free_args(call);
1615
1616
0
  uint32_t call_info = ZEND_CALL_INFO(call);
1617
0
  if (UNEXPECTED(call_info & ZEND_CALL_ALLOCATED)) {
1618
0
    zend_vm_stack_free_call_frame_ex(call_info, call);
1619
0
  } else {
1620
0
    EG(vm_stack_top) = (zval*)call;
1621
0
  }
1622
0
}
1623
1624
1625
static zend_always_inline int zend_binary_op(zval *ret, zval *op1, zval *op2 OPLINE_DC)
1626
1.47M
{
1627
1.47M
  static const binary_op_type zend_binary_ops[] = {
1628
1.47M
    add_function,
1629
1.47M
    sub_function,
1630
1.47M
    mul_function,
1631
1.47M
    div_function,
1632
1.47M
    mod_function,
1633
1.47M
    shift_left_function,
1634
1.47M
    shift_right_function,
1635
1.47M
    concat_function,
1636
1.47M
    bitwise_or_function,
1637
1.47M
    bitwise_and_function,
1638
1.47M
    bitwise_xor_function,
1639
1.47M
    pow_function
1640
1.47M
  };
1641
  /* size_t cast makes GCC to better optimize 64-bit PIC code */
1642
1.47M
  size_t opcode = (size_t)opline->extended_value;
1643
1644
1.47M
  return zend_binary_ops[opcode - ZEND_ADD](ret, op1, op2);
1645
1.47M
}
1646
1647
static zend_never_inline void zend_binary_assign_op_obj_dim(zend_object *obj, zval *property OPLINE_DC EXECUTE_DATA_DC)
1648
72
{
1649
72
  zval *value;
1650
72
  zval *z;
1651
72
  zval rv, res;
1652
1653
72
  GC_ADDREF(obj);
1654
72
  if (property && UNEXPECTED(Z_ISUNDEF_P(property))) {
1655
0
    property = ZVAL_UNDEFINED_OP2();
1656
0
  }
1657
72
  value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
1658
72
  if ((z = obj->handlers->read_dimension(obj, property, BP_VAR_R, &rv)) != NULL) {
1659
1660
61
    if (zend_binary_op(&res, z, value OPLINE_CC) == SUCCESS) {
1661
51
      obj->handlers->write_dimension(obj, property, &res);
1662
51
    }
1663
61
    if (z == &rv) {
1664
43
      zval_ptr_dtor(&rv);
1665
43
    }
1666
61
    if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
1667
5
      ZVAL_COPY(EX_VAR(opline->result.var), &res);
1668
5
    }
1669
61
    zval_ptr_dtor(&res);
1670
61
  } else {
1671
11
    zend_use_object_as_array(obj);
1672
11
    if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
1673
3
      ZVAL_NULL(EX_VAR(opline->result.var));
1674
3
    }
1675
11
  }
1676
72
  FREE_OP((opline+1)->op1_type, (opline+1)->op1.var);
1677
72
  if (UNEXPECTED(GC_DELREF(obj) == 0)) {
1678
0
    zend_objects_store_del(obj);
1679
0
  }
1680
72
}
1681
1682
static zend_never_inline void zend_binary_assign_op_typed_ref(zend_reference *ref, zval *value OPLINE_DC EXECUTE_DATA_DC)
1683
234
{
1684
234
  zval z_copy;
1685
1686
  /* Make sure that in-place concatenation is used if the LHS is a string. */
1687
234
  if (opline->extended_value == ZEND_CONCAT && Z_TYPE(ref->val) == IS_STRING) {
1688
52
    concat_function(&ref->val, &ref->val, value);
1689
52
    ZEND_ASSERT(Z_TYPE(ref->val) == IS_STRING && "Concat should return string");
1690
52
    return;
1691
52
  }
1692
1693
182
  zend_binary_op(&z_copy, &ref->val, value OPLINE_CC);
1694
182
  if (EXPECTED(zend_verify_ref_assignable_zval(ref, &z_copy, EX_USES_STRICT_TYPES()))) {
1695
142
    zval_ptr_dtor(&ref->val);
1696
142
    ZVAL_COPY_VALUE(&ref->val, &z_copy);
1697
142
  } else {
1698
40
    zval_ptr_dtor(&z_copy);
1699
40
  }
1700
182
}
1701
1702
static zend_never_inline void zend_binary_assign_op_typed_prop(const zend_property_info *prop_info, zval *zptr, zval *value OPLINE_DC EXECUTE_DATA_DC)
1703
365
{
1704
365
  zval z_copy;
1705
1706
  /* Make sure that in-place concatenation is used if the LHS is a string. */
1707
365
  if (opline->extended_value == ZEND_CONCAT && Z_TYPE_P(zptr) == IS_STRING) {
1708
157
    concat_function(zptr, zptr, value);
1709
157
    ZEND_ASSERT(Z_TYPE_P(zptr) == IS_STRING && "Concat should return string");
1710
157
    return;
1711
157
  }
1712
1713
208
  zend_binary_op(&z_copy, zptr, value OPLINE_CC);
1714
208
  if (EXPECTED(zend_verify_property_type(prop_info, &z_copy, EX_USES_STRICT_TYPES()))) {
1715
162
    zval_ptr_dtor(zptr);
1716
162
    ZVAL_COPY_VALUE(zptr, &z_copy);
1717
162
  } else {
1718
46
    zval_ptr_dtor(&z_copy);
1719
46
  }
1720
208
}
1721
1722
static zend_never_inline zend_long zend_check_string_offset(const zval *dim, int type EXECUTE_DATA_DC)
1723
445
{
1724
445
  zend_long offset;
1725
1726
445
try_again:
1727
445
  switch(Z_TYPE_P(dim)) {
1728
139
    case IS_LONG:
1729
139
      return Z_LVAL_P(dim);
1730
129
    case IS_STRING:
1731
129
    {
1732
129
      bool trailing_data = false;
1733
      /* For BC reasons we allow errors so that we can warn on leading numeric string */
1734
129
      if (IS_LONG == is_numeric_string_ex(Z_STRVAL_P(dim), Z_STRLEN_P(dim), &offset, NULL,
1735
129
          /* allow errors */ true, NULL, &trailing_data)) {
1736
15
        if (UNEXPECTED(trailing_data) && type != BP_VAR_UNSET) {
1737
9
          zend_error(E_WARNING, "Illegal string offset \"%s\"", Z_STRVAL_P(dim));
1738
9
        }
1739
15
        return offset;
1740
15
      }
1741
114
      zend_illegal_string_offset(dim, type);
1742
114
      return 0;
1743
129
    }
1744
53
    case IS_DOUBLE:
1745
      /* Suppress potential double warning */
1746
53
      zend_error(E_WARNING, "String offset cast occurred");
1747
53
      return zend_dval_to_lval_silent(Z_DVAL_P(dim));
1748
7
    case IS_UNDEF:
1749
7
      ZVAL_UNDEFINED_OP2();
1750
7
      ZEND_FALLTHROUGH;
1751
117
    case IS_NULL:
1752
118
    case IS_FALSE:
1753
119
    case IS_TRUE:
1754
119
      zend_error(E_WARNING, "String offset cast occurred");
1755
119
      break;
1756
0
    case IS_REFERENCE:
1757
0
      dim = Z_REFVAL_P(dim);
1758
0
      goto try_again;
1759
5
    default:
1760
5
      zend_illegal_string_offset(dim, type);
1761
5
      return 0;
1762
445
  }
1763
1764
119
  return zval_get_long_func(dim, /* is_strict */ false);
1765
445
}
1766
1767
ZEND_API zend_never_inline ZEND_COLD void zend_wrong_string_offset_error(void)
1768
168
{
1769
168
  const char *msg = NULL;
1770
168
  const zend_execute_data *execute_data = EG(current_execute_data);
1771
168
  const zend_op *opline = execute_data->opline;
1772
1773
168
  if (UNEXPECTED(EG(exception) != NULL)) {
1774
14
    return;
1775
14
  }
1776
1777
154
  switch (opline->opcode) {
1778
8
    case ZEND_ASSIGN_DIM_OP:
1779
8
      msg = "Cannot use assign-op operators with string offsets";
1780
8
      break;
1781
6
    case ZEND_FETCH_LIST_W:
1782
6
      msg = "Cannot create references to/from string offsets";
1783
6
      break;
1784
70
    case ZEND_FETCH_DIM_W:
1785
109
    case ZEND_FETCH_DIM_RW:
1786
117
    case ZEND_FETCH_DIM_FUNC_ARG:
1787
140
    case ZEND_FETCH_DIM_UNSET:
1788
140
      switch (opline->extended_value) {
1789
43
        case ZEND_FETCH_DIM_REF:
1790
43
          msg = "Cannot create references to/from string offsets";
1791
43
          break;
1792
42
        case ZEND_FETCH_DIM_DIM:
1793
42
          msg = "Cannot use string offset as an array";
1794
42
          break;
1795
45
        case ZEND_FETCH_DIM_OBJ:
1796
45
          msg = "Cannot use string offset as an object";
1797
45
          break;
1798
10
        case ZEND_FETCH_DIM_INCDEC:
1799
10
          msg = "Cannot increment/decrement string offsets";
1800
10
          break;
1801
0
        default: ZEND_UNREACHABLE();
1802
140
      }
1803
140
      break;
1804
140
    default: ZEND_UNREACHABLE();
1805
154
  }
1806
154
  ZEND_ASSERT(msg != NULL);
1807
154
  zend_throw_error(NULL, "%s", msg);
1808
154
}
1809
1810
ZEND_COLD static zend_result ZEND_FASTCALL get_deprecation_suffix_from_attribute(HashTable *attributes, zend_class_entry* scope, zend_string **message_suffix)
1811
666
{
1812
666
  *message_suffix = ZSTR_EMPTY_ALLOC();
1813
1814
666
  if (!attributes) {
1815
0
    return SUCCESS;
1816
0
  }
1817
1818
666
  zend_attribute *deprecated = zend_get_attribute_str(attributes, "deprecated", sizeof("deprecated")-1);
1819
1820
666
  if (!deprecated) {
1821
0
    return SUCCESS;
1822
0
  }
1823
1824
666
  if (deprecated->argc == 0) {
1825
211
    return SUCCESS;
1826
211
  }
1827
1828
455
  zend_result result = FAILURE;
1829
1830
455
  zend_string *message = ZSTR_EMPTY_ALLOC();
1831
455
  zend_string *since = ZSTR_EMPTY_ALLOC();
1832
1833
455
  zval obj;
1834
455
  ZVAL_UNDEF(&obj);
1835
455
  zval *z;
1836
1837
  /* Construct the Deprecated object to correctly handle parameter processing. */
1838
455
  if (FAILURE == zend_get_attribute_object(&obj, zend_ce_deprecated, deprecated, scope, NULL)) {
1839
34
    goto out;
1840
34
  }
1841
1842
  /* Extract the $message property. */
1843
421
  z = zend_read_property_ex(zend_ce_deprecated, Z_OBJ_P(&obj), ZSTR_KNOWN(ZEND_STR_MESSAGE), false, NULL);
1844
421
  ZEND_ASSERT(z != &EG(uninitialized_zval));
1845
421
  if (Z_TYPE_P(z) == IS_STRING) {
1846
335
    message = Z_STR_P(z);
1847
335
  }
1848
1849
  /* Extract the $since property. */
1850
421
  z = zend_read_property_ex(zend_ce_deprecated, Z_OBJ_P(&obj), ZSTR_KNOWN(ZEND_STR_SINCE), false, NULL);
1851
421
  ZEND_ASSERT(z != &EG(uninitialized_zval));
1852
421
  if (Z_TYPE_P(z) == IS_STRING) {
1853
262
    since = Z_STR_P(z);
1854
262
  }
1855
1856
  /* Construct the suffix. */
1857
421
  *message_suffix = zend_strpprintf_unchecked(
1858
421
    0,
1859
421
    "%s%S%s%S",
1860
421
    ZSTR_LEN(since) > 0 ? " since " : "",
1861
421
    since,
1862
421
    ZSTR_LEN(message) > 0 ? ", " : "",
1863
421
    message
1864
421
  );
1865
1866
421
  result = SUCCESS;
1867
1868
455
 out:
1869
1870
455
  zval_ptr_dtor(&obj);
1871
1872
455
  return result;
1873
421
}
1874
1875
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_deprecated_function(const zend_function *fbc)
1876
337
{
1877
337
  zend_string *message_suffix = ZSTR_EMPTY_ALLOC();
1878
1879
337
  if (get_deprecation_suffix_from_attribute(fbc->common.attributes, fbc->common.scope, &message_suffix) == FAILURE) {
1880
16
    return;
1881
16
  }
1882
1883
321
  int code = fbc->type == ZEND_INTERNAL_FUNCTION ? E_DEPRECATED : E_USER_DEPRECATED;
1884
1885
321
  if (fbc->common.scope) {
1886
135
    zend_error_unchecked(code, "Method %s::%s() is deprecated%S",
1887
135
      ZSTR_VAL(fbc->common.scope->name),
1888
135
      ZSTR_VAL(fbc->common.function_name),
1889
135
      message_suffix
1890
135
    );
1891
186
  } else {
1892
186
    zend_error_unchecked(code, "Function %s() is deprecated%S",
1893
186
      ZSTR_VAL(fbc->common.function_name),
1894
186
      message_suffix
1895
186
    );
1896
186
  }
1897
1898
321
  zend_string_release(message_suffix);
1899
321
}
1900
1901
ZEND_COLD static zend_result ZEND_FASTCALL get_nodiscard_suffix_from_attribute(HashTable *attributes, zend_class_entry* scope, zend_string **message_suffix)
1902
613
{
1903
613
  *message_suffix = ZSTR_EMPTY_ALLOC();
1904
1905
613
  if (!attributes) {
1906
0
    return SUCCESS;
1907
0
  }
1908
1909
613
  zend_attribute *nodiscard = zend_get_attribute_str(attributes, "nodiscard", sizeof("nodiscard")-1);
1910
1911
613
  if (!nodiscard) {
1912
0
    return SUCCESS;
1913
0
  }
1914
1915
613
  if (nodiscard->argc == 0) {
1916
570
    return SUCCESS;
1917
570
  }
1918
1919
43
  zend_result result = FAILURE;
1920
1921
43
  zend_string *message = ZSTR_EMPTY_ALLOC();
1922
1923
43
  zval obj;
1924
43
  ZVAL_UNDEF(&obj);
1925
43
  zval *z;
1926
1927
  /* Construct the NoDiscard object to correctly handle parameter processing. */
1928
43
  if (FAILURE == zend_get_attribute_object(&obj, zend_ce_nodiscard, nodiscard, scope, NULL)) {
1929
10
    goto out;
1930
10
  }
1931
1932
  /* Extract the $message property. */
1933
33
  z = zend_read_property_ex(zend_ce_nodiscard, Z_OBJ_P(&obj), ZSTR_KNOWN(ZEND_STR_MESSAGE), false, NULL);
1934
33
  ZEND_ASSERT(z != &EG(uninitialized_zval));
1935
33
  if (Z_TYPE_P(z) == IS_STRING) {
1936
33
    message = Z_STR_P(z);
1937
33
  }
1938
1939
  /* Construct the suffix. */
1940
33
  *message_suffix = zend_strpprintf_unchecked(
1941
33
    0,
1942
33
    "%s%S",
1943
33
    ZSTR_LEN(message) > 0 ? ", " : "",
1944
33
    message
1945
33
  );
1946
1947
33
  result = SUCCESS;
1948
1949
43
 out:
1950
1951
43
  zval_ptr_dtor(&obj);
1952
1953
43
  return result;
1954
33
}
1955
1956
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_nodiscard_function(const zend_function *fbc)
1957
613
{
1958
613
  zend_string *message_suffix = ZSTR_EMPTY_ALLOC();
1959
1960
613
  if (get_nodiscard_suffix_from_attribute(fbc->common.attributes, fbc->common.scope, &message_suffix) == FAILURE) {
1961
10
    return;
1962
10
  }
1963
1964
603
  int code = fbc->type == ZEND_INTERNAL_FUNCTION ? E_WARNING : E_USER_WARNING;
1965
1966
603
  if (fbc->common.scope) {
1967
76
    zend_error_unchecked(code, "The return value of method %s::%s() should either be used or intentionally ignored by casting it as (void)%S",
1968
76
      ZSTR_VAL(fbc->common.scope->name),
1969
76
      ZSTR_VAL(fbc->common.function_name),
1970
76
      message_suffix
1971
76
    );
1972
527
  } else {
1973
527
    zend_error_unchecked(code, "The return value of function %s() should either be used or intentionally ignored by casting it as (void)%S",
1974
527
      ZSTR_VAL(fbc->common.function_name),
1975
527
      message_suffix
1976
527
    );
1977
527
  }
1978
1979
603
  zend_string_release(message_suffix);
1980
603
}
1981
1982
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_deprecated_class_constant(const zend_class_constant *c, const zend_string *constant_name)
1983
89
{
1984
89
  zend_string *message_suffix = ZSTR_EMPTY_ALLOC();
1985
1986
89
  if (get_deprecation_suffix_from_attribute(c->attributes, c->ce, &message_suffix) == FAILURE) {
1987
5
    return;
1988
5
  }
1989
1990
84
  int code = c->ce->type == ZEND_INTERNAL_CLASS ? E_DEPRECATED : E_USER_DEPRECATED;
1991
84
  char *type = (ZEND_CLASS_CONST_FLAGS(c) & ZEND_CLASS_CONST_IS_CASE) ? "Enum case" : "Constant";
1992
1993
84
  zend_error_unchecked(code, "%s %s::%s is deprecated%S",
1994
84
    type,
1995
84
    ZSTR_VAL(c->ce->name),
1996
84
    ZSTR_VAL(constant_name),
1997
84
    message_suffix
1998
84
  );
1999
2000
84
  zend_string_release(message_suffix);
2001
84
}
2002
2003
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_deprecated_constant(const zend_constant *c, const zend_string *constant_name)
2004
166
{
2005
166
  zend_string *message_suffix = ZSTR_EMPTY_ALLOC();
2006
2007
166
  if (get_deprecation_suffix_from_attribute(c->attributes, NULL, &message_suffix) == FAILURE) {
2008
8
    return;
2009
8
  }
2010
2011
158
  int code = ZEND_CONSTANT_MODULE_NUMBER(c) == PHP_USER_CONSTANT ? E_USER_DEPRECATED : E_DEPRECATED;
2012
2013
158
  zend_error_unchecked(code, "Constant %s is deprecated%S",
2014
158
    ZSTR_VAL(constant_name),
2015
158
    message_suffix
2016
158
  );
2017
2018
158
  zend_string_release(message_suffix);
2019
158
}
2020
2021
ZEND_API ZEND_COLD void zend_use_of_deprecated_trait(
2022
  zend_class_entry *trait,
2023
  const zend_string *used_by
2024
74
) {
2025
74
  zend_string *message_suffix = ZSTR_EMPTY_ALLOC();
2026
2027
74
  if (get_deprecation_suffix_from_attribute(trait->attributes, trait, &message_suffix) == FAILURE) {
2028
5
    return;
2029
5
  }
2030
2031
69
  int code = trait->type == ZEND_INTERNAL_CLASS ? E_DEPRECATED : E_USER_DEPRECATED;
2032
2033
69
  zend_error_unchecked(code, "Trait %s used by %s is deprecated%S",
2034
69
    ZSTR_VAL(trait->name),
2035
69
    ZSTR_VAL(used_by),
2036
69
    message_suffix
2037
69
  );
2038
2039
69
  zend_string_release(message_suffix);
2040
69
}
2041
2042
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_false_to_array_deprecated(void)
2043
1.27k
{
2044
1.27k
  zend_error(E_DEPRECATED, "Automatic conversion of false to array is deprecated");
2045
1.27k
}
2046
2047
static zend_never_inline void zend_assign_to_string_offset(zval *str, zval *dim, zval *value OPLINE_DC EXECUTE_DATA_DC)
2048
593
{
2049
593
  zend_uchar c;
2050
593
  size_t string_len;
2051
593
  zend_long offset;
2052
593
  zend_string *s;
2053
2054
  /* separate string */
2055
593
  if (Z_REFCOUNTED_P(str) && Z_REFCOUNT_P(str) == 1) {
2056
286
    s = Z_STR_P(str);
2057
307
  } else {
2058
307
    s = zend_string_init(Z_STRVAL_P(str), Z_STRLEN_P(str), 0);
2059
307
    ZSTR_H(s) = ZSTR_H(Z_STR_P(str));
2060
307
    if (Z_REFCOUNTED_P(str)) {
2061
59
      GC_DELREF(Z_STR_P(str));
2062
59
    }
2063
307
    ZVAL_NEW_STR(str, s);
2064
307
  }
2065
2066
593
  if (EXPECTED(Z_TYPE_P(dim) == IS_LONG)) {
2067
316
    offset = Z_LVAL_P(dim);
2068
316
  } else {
2069
    /* The string may be destroyed while throwing the notice.
2070
     * Temporarily increase the refcount to detect this situation. */
2071
277
    GC_ADDREF(s);
2072
277
    offset = zend_check_string_offset(dim, BP_VAR_W EXECUTE_DATA_CC);
2073
277
    if (UNEXPECTED(GC_DELREF(s) == 0)) {
2074
0
      zend_string_efree(s);
2075
0
      if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
2076
0
        ZVAL_NULL(EX_VAR(opline->result.var));
2077
0
      }
2078
0
      return;
2079
0
    }
2080
    /* Illegal offset assignment */
2081
277
    if (UNEXPECTED(EG(exception) != NULL)) {
2082
105
      if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
2083
10
        ZVAL_UNDEF(EX_VAR(opline->result.var));
2084
10
      }
2085
105
      return;
2086
105
    }
2087
277
  }
2088
2089
488
  if (UNEXPECTED(offset < -(zend_long)ZSTR_LEN(s))) {
2090
    /* Error on negative offset */
2091
80
    zend_error(E_WARNING, "Illegal string offset " ZEND_LONG_FMT, offset);
2092
80
    if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
2093
65
      ZVAL_NULL(EX_VAR(opline->result.var));
2094
65
    }
2095
80
    return;
2096
80
  }
2097
2098
408
  if (offset < 0) { /* Handle negative offset */
2099
63
    offset += (zend_long)ZSTR_LEN(s);
2100
63
  }
2101
2102
408
  if (UNEXPECTED(Z_TYPE_P(value) != IS_STRING)) {
2103
131
    zend_string *tmp;
2104
2105
    /* The string may be destroyed while throwing the notice.
2106
     * Temporarily increase the refcount to detect this situation. */
2107
131
    GC_ADDREF(s);
2108
131
    if (UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) {
2109
0
      zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC);
2110
0
    }
2111
    /* Convert to string, just the time to pick the 1st byte */
2112
131
    tmp = zval_try_get_string_func(value);
2113
131
    if (UNEXPECTED(GC_DELREF(s) == 0)) {
2114
0
      zend_string_efree(s);
2115
0
      if (tmp) {
2116
0
        zend_string_release_ex(tmp, 0);
2117
0
      }
2118
0
      if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
2119
0
        ZVAL_NULL(EX_VAR(opline->result.var));
2120
0
      }
2121
0
      return;
2122
0
    }
2123
131
    if (UNEXPECTED(!tmp)) {
2124
17
      if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
2125
0
        ZVAL_UNDEF(EX_VAR(opline->result.var));
2126
0
      }
2127
17
      return;
2128
17
    }
2129
2130
114
    string_len = ZSTR_LEN(tmp);
2131
114
    c = (zend_uchar)ZSTR_VAL(tmp)[0];
2132
114
    zend_string_release_ex(tmp, 0);
2133
277
  } else {
2134
277
    string_len = Z_STRLEN_P(value);
2135
277
    c = (zend_uchar)Z_STRVAL_P(value)[0];
2136
277
  }
2137
2138
391
  if (UNEXPECTED(string_len != 1)) {
2139
107
    if (string_len == 0) {
2140
      /* Error on empty input string */
2141
37
      zend_throw_error(NULL, "Cannot assign an empty string to a string offset");
2142
37
      if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
2143
31
        ZVAL_NULL(EX_VAR(opline->result.var));
2144
31
      }
2145
37
      return;
2146
37
    }
2147
2148
    /* The string may be destroyed while throwing the notice.
2149
     * Temporarily increase the refcount to detect this situation. */
2150
70
    GC_ADDREF(s);
2151
70
    zend_error(E_WARNING, "Only the first byte will be assigned to the string offset");
2152
70
    if (UNEXPECTED(GC_DELREF(s) == 0)) {
2153
0
      zend_string_efree(s);
2154
0
      if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
2155
0
        ZVAL_NULL(EX_VAR(opline->result.var));
2156
0
      }
2157
0
      return;
2158
0
    }
2159
    /* Illegal offset assignment */
2160
70
    if (UNEXPECTED(EG(exception) != NULL)) {
2161
0
      if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
2162
0
        ZVAL_UNDEF(EX_VAR(opline->result.var));
2163
0
      }
2164
0
      return;
2165
0
    }
2166
70
  }
2167
2168
354
  if ((size_t)offset >= ZSTR_LEN(s)) {
2169
    /* Extend string if needed */
2170
49
    zend_long old_len = ZSTR_LEN(s);
2171
49
    ZVAL_NEW_STR(str, zend_string_extend(s, (size_t)offset + 1, 0));
2172
49
    memset(Z_STRVAL_P(str) + old_len, ' ', offset - old_len);
2173
49
    Z_STRVAL_P(str)[offset+1] = 0;
2174
305
  } else {
2175
305
    zend_string_forget_hash_val(Z_STR_P(str));
2176
305
  }
2177
2178
354
  Z_STRVAL_P(str)[offset] = c;
2179
2180
354
  if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
2181
    /* Return the new character */
2182
81
    ZVAL_CHAR(EX_VAR(opline->result.var), c);
2183
81
  }
2184
354
}
2185
2186
static zend_property_info *zend_get_prop_not_accepting_double(zend_reference *ref)
2187
265
{
2188
265
  zend_property_info *prop;
2189
795
  ZEND_REF_FOREACH_TYPE_SOURCES(ref, prop) {
2190
795
    if (!(ZEND_TYPE_FULL_MASK(prop->type) & MAY_BE_DOUBLE)) {
2191
204
      return prop;
2192
204
    }
2193
795
  } ZEND_REF_FOREACH_TYPE_SOURCES_END();
2194
61
  return NULL;
2195
265
}
2196
2197
static zend_never_inline ZEND_COLD zend_long zend_throw_incdec_ref_error(const zend_property_info *error_prop OPLINE_DC)
2198
204
{
2199
204
  zend_string *type_str = zend_type_to_string(error_prop->type);
2200
204
  if (ZEND_IS_INCREMENT(opline->opcode)) {
2201
110
    zend_type_error(
2202
110
      "Cannot increment a reference held by property %s::$%s of type %s past its maximal value",
2203
110
      ZSTR_VAL(error_prop->ce->name),
2204
110
      zend_get_unmangled_property_name(error_prop->name),
2205
110
      ZSTR_VAL(type_str));
2206
110
    zend_string_release(type_str);
2207
110
    return ZEND_LONG_MAX;
2208
110
  } else {
2209
94
    zend_type_error(
2210
94
      "Cannot decrement a reference held by property %s::$%s of type %s past its minimal value",
2211
94
      ZSTR_VAL(error_prop->ce->name),
2212
94
      zend_get_unmangled_property_name(error_prop->name),
2213
94
      ZSTR_VAL(type_str));
2214
94
    zend_string_release(type_str);
2215
94
    return ZEND_LONG_MIN;
2216
94
  }
2217
204
}
2218
2219
125
static zend_never_inline ZEND_COLD zend_long zend_throw_incdec_prop_error(const zend_property_info *prop OPLINE_DC) {
2220
125
  zend_string *type_str = zend_type_to_string(prop->type);
2221
125
  if (ZEND_IS_INCREMENT(opline->opcode)) {
2222
74
    zend_type_error("Cannot increment property %s::$%s of type %s past its maximal value",
2223
74
      ZSTR_VAL(prop->ce->name),
2224
74
      zend_get_unmangled_property_name(prop->name),
2225
74
      ZSTR_VAL(type_str));
2226
74
    zend_string_release(type_str);
2227
74
    return ZEND_LONG_MAX;
2228
74
  } else {
2229
51
    zend_type_error("Cannot decrement property %s::$%s of type %s past its minimal value",
2230
51
      ZSTR_VAL(prop->ce->name),
2231
51
      zend_get_unmangled_property_name(prop->name),
2232
51
      ZSTR_VAL(type_str));
2233
51
    zend_string_release(type_str);
2234
51
    return ZEND_LONG_MIN;
2235
51
  }
2236
125
}
2237
2238
static void zend_incdec_typed_ref(zend_reference *ref, zval *copy OPLINE_DC EXECUTE_DATA_DC)
2239
436
{
2240
436
  zval tmp;
2241
436
  zval *var_ptr = &ref->val;
2242
2243
436
  if (!copy) {
2244
321
    copy = &tmp;
2245
321
  }
2246
2247
436
  ZVAL_COPY(copy, var_ptr);
2248
2249
436
  if (ZEND_IS_INCREMENT(opline->opcode)) {
2250
202
    increment_function(var_ptr);
2251
234
  } else {
2252
234
    decrement_function(var_ptr);
2253
234
  }
2254
2255
436
  if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_DOUBLE) && Z_TYPE_P(copy) == IS_LONG) {
2256
265
    zend_property_info *error_prop = zend_get_prop_not_accepting_double(ref);
2257
265
    if (UNEXPECTED(error_prop)) {
2258
204
      zend_long val = zend_throw_incdec_ref_error(error_prop OPLINE_CC);
2259
204
      ZVAL_LONG(var_ptr, val);
2260
204
    }
2261
265
  } else if (UNEXPECTED(!zend_verify_ref_assignable_zval(ref, var_ptr, EX_USES_STRICT_TYPES()))) {
2262
6
    zval_ptr_dtor(var_ptr);
2263
6
    ZVAL_COPY_VALUE(var_ptr, copy);
2264
6
    ZVAL_UNDEF(copy);
2265
165
  } else if (copy == &tmp) {
2266
121
    zval_ptr_dtor(&tmp);
2267
121
  }
2268
436
}
2269
2270
static void zend_incdec_typed_prop(const zend_property_info *prop_info, zval *var_ptr, zval *copy OPLINE_DC EXECUTE_DATA_DC)
2271
91
{
2272
91
  zval tmp;
2273
2274
91
  if (!copy) {
2275
70
    copy = &tmp;
2276
70
  }
2277
2278
91
  ZVAL_COPY(copy, var_ptr);
2279
2280
91
  if (ZEND_IS_INCREMENT(opline->opcode)) {
2281
56
    increment_function(var_ptr);
2282
56
  } else {
2283
35
    decrement_function(var_ptr);
2284
35
  }
2285
2286
91
  if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_DOUBLE) && Z_TYPE_P(copy) == IS_LONG) {
2287
0
    if (!(ZEND_TYPE_FULL_MASK(prop_info->type) & MAY_BE_DOUBLE)) {
2288
0
      zend_long val = zend_throw_incdec_prop_error(prop_info OPLINE_CC);
2289
0
      ZVAL_LONG(var_ptr, val);
2290
0
    }
2291
91
  } else if (UNEXPECTED(!zend_verify_property_type(prop_info, var_ptr, EX_USES_STRICT_TYPES()))) {
2292
13
    zval_ptr_dtor(var_ptr);
2293
13
    ZVAL_COPY_VALUE(var_ptr, copy);
2294
13
    ZVAL_UNDEF(copy);
2295
78
  } else if (copy == &tmp) {
2296
65
    zval_ptr_dtor(&tmp);
2297
65
  }
2298
91
}
2299
2300
static void zend_pre_incdec_property_zval(zval *prop, const zend_property_info *prop_info OPLINE_DC EXECUTE_DATA_DC)
2301
2.02k
{
2302
2.02k
  if (EXPECTED(Z_TYPE_P(prop) == IS_LONG)) {
2303
1.27k
    if (ZEND_IS_INCREMENT(opline->opcode)) {
2304
1.18k
      fast_long_increment_function(prop);
2305
1.18k
    } else {
2306
93
      fast_long_decrement_function(prop);
2307
93
    }
2308
1.27k
    if (UNEXPECTED(Z_TYPE_P(prop) != IS_LONG) && prop_info
2309
139
        && !(ZEND_TYPE_FULL_MASK(prop_info->type) & MAY_BE_DOUBLE)) {
2310
100
      zend_long val = zend_throw_incdec_prop_error(prop_info OPLINE_CC);
2311
100
      ZVAL_LONG(prop, val);
2312
100
    }
2313
1.27k
  } else {
2314
751
    do {
2315
751
      if (Z_ISREF_P(prop)) {
2316
156
        zend_reference *ref = Z_REF_P(prop);
2317
156
        prop = Z_REFVAL_P(prop);
2318
156
        if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
2319
116
          zend_incdec_typed_ref(ref, NULL OPLINE_CC EXECUTE_DATA_CC);
2320
116
          break;
2321
116
        }
2322
156
      }
2323
2324
635
      if (prop_info) {
2325
70
        zend_incdec_typed_prop(prop_info, prop, NULL OPLINE_CC EXECUTE_DATA_CC);
2326
565
      } else if (ZEND_IS_INCREMENT(opline->opcode)) {
2327
509
        increment_function(prop);
2328
509
      } else {
2329
56
        decrement_function(prop);
2330
56
      }
2331
635
    } while (0);
2332
751
  }
2333
2.02k
  if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
2334
1.32k
    ZVAL_COPY(EX_VAR(opline->result.var), prop);
2335
1.32k
  }
2336
2.02k
}
2337
2338
static void zend_post_incdec_property_zval(zval *prop, const zend_property_info *prop_info OPLINE_DC EXECUTE_DATA_DC)
2339
1.65k
{
2340
1.65k
  if (EXPECTED(Z_TYPE_P(prop) == IS_LONG)) {
2341
1.33k
    ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(prop));
2342
1.33k
    if (ZEND_IS_INCREMENT(opline->opcode)) {
2343
367
      fast_long_increment_function(prop);
2344
968
    } else {
2345
968
      fast_long_decrement_function(prop);
2346
968
    }
2347
1.33k
    if (UNEXPECTED(Z_TYPE_P(prop) != IS_LONG) && prop_info
2348
64
        && !(ZEND_TYPE_FULL_MASK(prop_info->type) & MAY_BE_DOUBLE)) {
2349
25
      zend_long val = zend_throw_incdec_prop_error(prop_info OPLINE_CC);
2350
25
      ZVAL_LONG(prop, val);
2351
25
    }
2352
1.33k
  } else {
2353
321
    if (Z_ISREF_P(prop)) {
2354
75
      zend_reference *ref = Z_REF_P(prop);
2355
75
      prop = Z_REFVAL_P(prop);
2356
75
      if (ZEND_REF_HAS_TYPE_SOURCES(ref)) {
2357
63
        zend_incdec_typed_ref(ref, EX_VAR(opline->result.var) OPLINE_CC EXECUTE_DATA_CC);
2358
63
        return;
2359
63
      }
2360
75
    }
2361
2362
258
    if (prop_info) {
2363
21
      zend_incdec_typed_prop(prop_info, prop, EX_VAR(opline->result.var) OPLINE_CC EXECUTE_DATA_CC);
2364
237
    } else {
2365
237
      ZVAL_COPY(EX_VAR(opline->result.var), prop);
2366
237
      if (ZEND_IS_INCREMENT(opline->opcode)) {
2367
47
        increment_function(prop);
2368
190
      } else {
2369
190
        decrement_function(prop);
2370
190
      }
2371
237
    }
2372
258
  }
2373
1.65k
}
2374
2375
static zend_never_inline void zend_post_incdec_overloaded_property(zend_object *object, zend_string *name, void **cache_slot OPLINE_DC EXECUTE_DATA_DC)
2376
42
{
2377
42
  zval rv;
2378
42
  zval *z;
2379
42
  zval z_copy;
2380
2381
42
  GC_ADDREF(object);
2382
42
  z =object->handlers->read_property(object, name, BP_VAR_R, cache_slot, &rv);
2383
42
  if (UNEXPECTED(EG(exception))) {
2384
4
    OBJ_RELEASE(object);
2385
4
    ZVAL_UNDEF(EX_VAR(opline->result.var));
2386
4
    return;
2387
4
  }
2388
2389
38
  ZVAL_COPY_DEREF(&z_copy, z);
2390
38
  ZVAL_COPY(EX_VAR(opline->result.var), &z_copy);
2391
38
  if (ZEND_IS_INCREMENT(opline->opcode)) {
2392
33
    increment_function(&z_copy);
2393
33
  } else {
2394
5
    decrement_function(&z_copy);
2395
5
  }
2396
38
  object->handlers->write_property(object, name, &z_copy, cache_slot);
2397
38
  OBJ_RELEASE(object);
2398
38
  zval_ptr_dtor(&z_copy);
2399
38
  if (z == &rv) {
2400
23
    zval_ptr_dtor(z);
2401
23
  }
2402
38
}
2403
2404
static zend_never_inline void zend_pre_incdec_overloaded_property(zend_object *object, zend_string *name, void **cache_slot OPLINE_DC EXECUTE_DATA_DC)
2405
267
{
2406
267
  zval rv;
2407
267
  zval *z;
2408
267
  zval z_copy;
2409
2410
267
  GC_ADDREF(object);
2411
267
  z = object->handlers->read_property(object, name, BP_VAR_R, cache_slot, &rv);
2412
267
  if (UNEXPECTED(EG(exception))) {
2413
5
    OBJ_RELEASE(object);
2414
5
    if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
2415
0
      ZVAL_NULL(EX_VAR(opline->result.var));
2416
0
    }
2417
5
    return;
2418
5
  }
2419
2420
262
  ZVAL_COPY_DEREF(&z_copy, z);
2421
262
  if (ZEND_IS_INCREMENT(opline->opcode)) {
2422
207
    increment_function(&z_copy);
2423
207
  } else {
2424
55
    decrement_function(&z_copy);
2425
55
  }
2426
262
  if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
2427
22
    ZVAL_COPY(EX_VAR(opline->result.var), &z_copy);
2428
22
  }
2429
262
  object->handlers->write_property(object, name, &z_copy, cache_slot);
2430
262
  OBJ_RELEASE(object);
2431
262
  zval_ptr_dtor(&z_copy);
2432
262
  if (z == &rv) {
2433
127
    zval_ptr_dtor(z);
2434
127
  }
2435
262
}
2436
2437
static zend_never_inline void zend_assign_op_overloaded_property(zend_object *object, zend_string *name, void **cache_slot, zval *value OPLINE_DC EXECUTE_DATA_DC)
2438
338
{
2439
338
  zval *z;
2440
338
  zval rv, res;
2441
2442
338
  GC_ADDREF(object);
2443
338
  z = object->handlers->read_property(object, name, BP_VAR_R, cache_slot, &rv);
2444
338
  if (UNEXPECTED(EG(exception))) {
2445
14
    OBJ_RELEASE(object);
2446
14
    if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
2447
2
      ZVAL_UNDEF(EX_VAR(opline->result.var));
2448
2
    }
2449
14
    return;
2450
14
  }
2451
324
  if (zend_binary_op(&res, z, value OPLINE_CC) == SUCCESS) {
2452
295
    object->handlers->write_property(object, name, &res, cache_slot);
2453
295
  }
2454
324
  if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
2455
81
    ZVAL_COPY(EX_VAR(opline->result.var), &res);
2456
81
  }
2457
324
  if (z == &rv) {
2458
226
    zval_ptr_dtor(z);
2459
226
  }
2460
324
  zval_ptr_dtor(&res);
2461
324
  OBJ_RELEASE(object);
2462
324
}
2463
2464
/* Utility Functions for Extensions */
2465
static void zend_extension_statement_handler(const zend_extension *extension, zend_execute_data *frame)
2466
0
{
2467
0
  if (extension->statement_handler) {
2468
0
    extension->statement_handler(frame);
2469
0
  }
2470
0
}
2471
2472
2473
static void zend_extension_fcall_begin_handler(const zend_extension *extension, zend_execute_data *frame)
2474
0
{
2475
0
  if (extension->fcall_begin_handler) {
2476
0
    extension->fcall_begin_handler(frame);
2477
0
  }
2478
0
}
2479
2480
2481
static void zend_extension_fcall_end_handler(const zend_extension *extension, zend_execute_data *frame)
2482
0
{
2483
0
  if (extension->fcall_end_handler) {
2484
0
    extension->fcall_end_handler(frame);
2485
0
  }
2486
0
}
2487
2488
2489
static zend_always_inline HashTable *zend_get_target_symbol_table(int fetch_type EXECUTE_DATA_DC)
2490
90.6k
{
2491
90.6k
  HashTable *ht;
2492
2493
90.6k
  if (EXPECTED(fetch_type & (ZEND_FETCH_GLOBAL_LOCK | ZEND_FETCH_GLOBAL))) {
2494
6.69k
    ht = &EG(symbol_table);
2495
83.9k
  } else {
2496
83.9k
    ZEND_ASSERT(fetch_type & ZEND_FETCH_LOCAL);
2497
83.9k
    if (!(EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE)) {
2498
2.84k
      zend_rebuild_symbol_table();
2499
2.84k
    }
2500
83.9k
    ht = EX(symbol_table);
2501
83.9k
  }
2502
90.6k
  return ht;
2503
90.6k
}
2504
2505
static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_undefined_offset(zend_long lval)
2506
3.85k
{
2507
3.85k
  zend_error(E_WARNING, "Undefined array key " ZEND_LONG_FMT, lval);
2508
3.85k
}
2509
2510
static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_undefined_index(const zend_string *offset)
2511
3.80k
{
2512
3.80k
  zend_error(E_WARNING, "Undefined array key \"%s\"", ZSTR_VAL(offset));
2513
3.80k
}
2514
2515
ZEND_API ZEND_COLD zval* ZEND_FASTCALL zend_undefined_offset_write(HashTable *ht, zend_long lval)
2516
675
{
2517
  /* The array may be destroyed while throwing the notice.
2518
   * Temporarily increase the refcount to detect this situation. */
2519
675
  if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) {
2520
675
    GC_ADDREF(ht);
2521
675
  }
2522
675
  zend_undefined_offset(lval);
2523
675
  if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && GC_DELREF(ht) != 1) {
2524
0
    if (!GC_REFCOUNT(ht)) {
2525
0
      zend_array_destroy(ht);
2526
0
    }
2527
0
    return NULL;
2528
0
  }
2529
675
  if (EG(exception)) {
2530
0
    return NULL;
2531
0
  }
2532
675
  return zend_hash_index_add_new(ht, lval, &EG(uninitialized_zval));
2533
675
}
2534
2535
ZEND_API ZEND_COLD zval* ZEND_FASTCALL zend_undefined_index_write(HashTable *ht, zend_string *offset)
2536
1.73k
{
2537
1.73k
  zval *retval;
2538
2539
  /* The array may be destroyed while throwing the notice.
2540
   * Temporarily increase the refcount to detect this situation. */
2541
1.73k
  if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) {
2542
1.73k
    GC_ADDREF(ht);
2543
1.73k
  }
2544
  /* Key may be released while throwing the undefined index warning. */
2545
1.73k
  zend_string_addref(offset);
2546
1.73k
  zend_undefined_index(offset);
2547
1.73k
  if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && GC_DELREF(ht) != 1) {
2548
0
    if (!GC_REFCOUNT(ht)) {
2549
0
      zend_array_destroy(ht);
2550
0
    }
2551
0
    retval = NULL;
2552
1.73k
  } else if (EG(exception)) {
2553
0
    retval = NULL;
2554
1.73k
  } else {
2555
1.73k
    retval = zend_hash_add_new(ht, offset, &EG(uninitialized_zval));
2556
1.73k
  }
2557
1.73k
  zend_string_release(offset);
2558
1.73k
  return retval;
2559
1.73k
}
2560
2561
ZEND_API zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_undefined_method(const zend_class_entry *ce, const zend_string *method)
2562
656
{
2563
656
  zend_throw_error(NULL, "Call to undefined method %s::%s()", ZSTR_VAL(ce->name), ZSTR_VAL(method));
2564
656
}
2565
2566
static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_invalid_method_call(const zval *object, const zval *function_name)
2567
785
{
2568
785
  zend_throw_error(NULL, "Call to a member function %s() on %s",
2569
785
    Z_STRVAL_P(function_name), zend_zval_value_name(object));
2570
785
}
2571
2572
ZEND_API zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_non_static_method_call(const zend_function *fbc)
2573
63
{
2574
63
  zend_throw_error(
2575
63
    zend_ce_error,
2576
63
    "Non-static method %s::%s() cannot be called statically",
2577
63
    ZSTR_VAL(fbc->common.scope->name), ZSTR_VAL(fbc->common.function_name));
2578
63
}
2579
2580
ZEND_COLD void ZEND_FASTCALL zend_param_must_be_ref(const zend_function *func, uint32_t arg_num)
2581
393
{
2582
393
  const char *arg_name = get_function_arg_name(func, arg_num);
2583
2584
393
  zend_error(E_WARNING, "%s%s%s(): Argument #%d%s%s%s must be passed by reference, value given",
2585
393
    func->common.scope ? ZSTR_VAL(func->common.scope->name) : "",
2586
393
    func->common.scope ? "::" : "",
2587
393
    ZSTR_VAL(func->common.function_name),
2588
393
    arg_num,
2589
393
    arg_name ? " ($" : "",
2590
393
    arg_name ? arg_name : "",
2591
393
    arg_name ? ")" : ""
2592
393
  );
2593
393
}
2594
2595
static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_use_scalar_as_array(void)
2596
474
{
2597
474
  zend_throw_error(NULL, "Cannot use a scalar value as an array");
2598
474
}
2599
2600
ZEND_API zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_cannot_add_element(void)
2601
124
{
2602
124
  zend_throw_error(NULL, "Cannot add element to the array as the next element is already occupied");
2603
124
}
2604
2605
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_use_resource_as_offset(const zval *dim)
2606
0
{
2607
0
  zend_error(E_WARNING,
2608
0
    "Resource ID#" ZEND_LONG_FMT " used as offset, casting to integer (" ZEND_LONG_FMT ")",
2609
0
    Z_RES_HANDLE_P(dim), Z_RES_HANDLE_P(dim));
2610
0
}
2611
2612
static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_use_new_element_for_string(void)
2613
42
{
2614
42
  zend_throw_error(NULL, "[] operator not supported for strings");
2615
42
}
2616
2617
#ifdef ZEND_CHECK_STACK_LIMIT
2618
ZEND_API zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_call_stack_size_error(void)
2619
1
{
2620
1
  size_t max_stack_size = 0;
2621
1
  if ((uintptr_t) EG(stack_base) > (uintptr_t) EG(stack_limit)) {
2622
1
    max_stack_size = (size_t) ((uintptr_t) EG(stack_base) - (uintptr_t) EG(stack_limit));
2623
1
  }
2624
2625
1
  zend_throw_error(NULL, "Maximum call stack size of %zu bytes (zend.max_allowed_stack_size - zend.reserved_stack_size) reached. Infinite recursion?",
2626
1
    max_stack_size);
2627
1
}
2628
#endif /* ZEND_CHECK_STACK_LIMIT */
2629
2630
static ZEND_COLD void zend_binary_assign_op_dim_slow(const zval *container, const zval *dim OPLINE_DC EXECUTE_DATA_DC)
2631
47
{
2632
47
  if (UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) {
2633
20
    if (opline->op2_type == IS_UNUSED) {
2634
10
      zend_use_new_element_for_string();
2635
10
    } else {
2636
10
      zend_check_string_offset(dim, BP_VAR_RW EXECUTE_DATA_CC);
2637
10
      zend_wrong_string_offset_error();
2638
10
    }
2639
27
  } else {
2640
27
    zend_use_scalar_as_array();
2641
27
  }
2642
47
}
2643
2644
static zend_never_inline uint8_t slow_index_convert(HashTable *ht, const zval *dim, zend_value *value EXECUTE_DATA_DC)
2645
2.71k
{
2646
2.71k
  switch (Z_TYPE_P(dim)) {
2647
1.02k
    case IS_UNDEF: {
2648
      /* The array may be destroyed while throwing the notice.
2649
       * Temporarily increase the refcount to detect this situation. */
2650
1.02k
      if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) {
2651
822
        GC_ADDREF(ht);
2652
822
      }
2653
1.02k
      ZVAL_UNDEFINED_OP2();
2654
1.02k
      if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) {
2655
0
        zend_array_destroy(ht);
2656
0
        return IS_NULL;
2657
0
      }
2658
1.02k
      if (EG(exception)) {
2659
0
        return IS_NULL;
2660
0
      }
2661
1.02k
      ZEND_FALLTHROUGH;
2662
1.02k
    }
2663
1.95k
    case IS_NULL:
2664
      /* The array may be destroyed while throwing the notice.
2665
       * Temporarily increase the refcount to detect this situation. */
2666
1.95k
      GC_TRY_ADDREF(ht);
2667
2668
1.95k
      zend_error(E_DEPRECATED, "Using null as an array offset is deprecated, use an empty string instead");
2669
2670
1.95k
      if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) {
2671
0
        zend_array_destroy(ht);
2672
0
        return IS_NULL;
2673
0
      }
2674
2675
1.95k
      if (EG(exception)) {
2676
0
        return IS_NULL;
2677
0
      }
2678
2679
1.95k
      value->str = ZSTR_EMPTY_ALLOC();
2680
1.95k
      return IS_STRING;
2681
511
    case IS_DOUBLE:
2682
      /* The array may be destroyed while throwing the notice.
2683
       * Temporarily increase the refcount to detect this situation. */
2684
511
      if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) {
2685
281
        GC_ADDREF(ht);
2686
281
      }
2687
511
      value->lval = zend_dval_to_lval_safe(Z_DVAL_P(dim));
2688
511
      if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) {
2689
0
        zend_array_destroy(ht);
2690
0
        return IS_NULL;
2691
0
      }
2692
511
      if (EG(exception)) {
2693
0
        return IS_NULL;
2694
0
      }
2695
511
      return IS_LONG;
2696
0
    case IS_RESOURCE:
2697
      /* The array may be destroyed while throwing the notice.
2698
       * Temporarily increase the refcount to detect this situation. */
2699
0
      if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) {
2700
0
        GC_ADDREF(ht);
2701
0
      }
2702
0
      zend_use_resource_as_offset(dim);
2703
0
      if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) {
2704
0
        zend_array_destroy(ht);
2705
0
        return IS_NULL;
2706
0
      }
2707
0
      if (EG(exception)) {
2708
0
        return IS_NULL;
2709
0
      }
2710
0
      value->lval = Z_RES_HANDLE_P(dim);
2711
0
      return IS_LONG;
2712
47
    case IS_FALSE:
2713
47
      value->lval = 0;
2714
47
      return IS_LONG;
2715
189
    case IS_TRUE:
2716
189
      value->lval = 1;
2717
189
      return IS_LONG;
2718
13
    default:
2719
13
      zend_illegal_array_offset_access(dim);
2720
13
      return IS_NULL;
2721
2.71k
  }
2722
2.71k
}
2723
2724
static zend_never_inline uint8_t slow_index_convert_w(HashTable *ht, const zval *dim, zend_value *value EXECUTE_DATA_DC)
2725
17.6k
{
2726
17.6k
  switch (Z_TYPE_P(dim)) {
2727
12.6k
    case IS_UNDEF: {
2728
      /* The array may be destroyed while throwing the notice.
2729
       * Temporarily increase the refcount to detect this situation. */
2730
12.6k
      if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) {
2731
12.6k
        GC_ADDREF(ht);
2732
12.6k
      }
2733
12.6k
      ZVAL_UNDEFINED_OP2();
2734
12.6k
      if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && GC_DELREF(ht) != 1) {
2735
0
        if (!GC_REFCOUNT(ht)) {
2736
0
          zend_array_destroy(ht);
2737
0
        }
2738
0
        return IS_NULL;
2739
0
      }
2740
12.6k
      if (EG(exception)) {
2741
0
        return IS_NULL;
2742
0
      }
2743
12.6k
      ZEND_FALLTHROUGH;
2744
12.6k
    }
2745
15.4k
    case IS_NULL:
2746
      /* The array may be destroyed while throwing the notice.
2747
       * Temporarily increase the refcount to detect this situation. */
2748
15.4k
      GC_TRY_ADDREF(ht);
2749
2750
15.4k
      zend_error(E_DEPRECATED, "Using null as an array offset is deprecated, use an empty string instead");
2751
2752
15.4k
      if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && GC_DELREF(ht) != 1) {
2753
0
        if (!GC_REFCOUNT(ht)) {
2754
0
          zend_array_destroy(ht);
2755
0
        }
2756
0
        return IS_NULL;
2757
0
      }
2758
15.4k
      if (EG(exception)) {
2759
0
        return IS_NULL;
2760
0
      }
2761
15.4k
      value->str = ZSTR_EMPTY_ALLOC();
2762
15.4k
      return IS_STRING;
2763
413
    case IS_DOUBLE:
2764
      /* The array may be destroyed while throwing the notice.
2765
       * Temporarily increase the refcount to detect this situation. */
2766
413
      if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) {
2767
413
        GC_ADDREF(ht);
2768
413
      }
2769
413
      value->lval = zend_dval_to_lval_safe(Z_DVAL_P(dim));
2770
413
      if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && GC_DELREF(ht) != 1) {
2771
0
        if (!GC_REFCOUNT(ht)) {
2772
0
          zend_array_destroy(ht);
2773
0
        }
2774
0
        return IS_NULL;
2775
0
      }
2776
413
      if (EG(exception)) {
2777
0
        return IS_NULL;
2778
0
      }
2779
413
      return IS_LONG;
2780
0
    case IS_RESOURCE:
2781
      /* The array may be destroyed while throwing the notice.
2782
       * Temporarily increase the refcount to detect this situation. */
2783
0
      if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) {
2784
0
        GC_ADDREF(ht);
2785
0
      }
2786
0
      zend_use_resource_as_offset(dim);
2787
0
      if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && GC_DELREF(ht) != 1) {
2788
0
        if (!GC_REFCOUNT(ht)) {
2789
0
          zend_array_destroy(ht);
2790
0
        }
2791
0
        return IS_NULL;
2792
0
      }
2793
0
      if (EG(exception)) {
2794
0
        return IS_NULL;
2795
0
      }
2796
0
      value->lval = Z_RES_HANDLE_P(dim);
2797
0
      return IS_LONG;
2798
318
    case IS_FALSE:
2799
318
      value->lval = 0;
2800
318
      return IS_LONG;
2801
1.30k
    case IS_TRUE:
2802
1.30k
      value->lval = 1;
2803
1.30k
      return IS_LONG;
2804
137
    default:
2805
137
      zend_illegal_array_offset_access(dim);
2806
137
      return IS_NULL;
2807
17.6k
  }
2808
17.6k
}
2809
2810
static zend_always_inline zval *zend_fetch_dimension_address_inner(HashTable *ht, const zval *dim, int dim_type, int type EXECUTE_DATA_DC)
2811
106k
{
2812
106k
  zval *retval = NULL;
2813
106k
  zend_string *offset_key;
2814
106k
  zend_ulong hval;
2815
2816
106k
try_again:
2817
106k
  if (EXPECTED(Z_TYPE_P(dim) == IS_LONG)) {
2818
59.2k
    hval = Z_LVAL_P(dim);
2819
62.5k
num_index:
2820
62.5k
    if (type != BP_VAR_W) {
2821
23.1k
      ZEND_HASH_INDEX_FIND(ht, hval, retval, num_undef);
2822
20.5k
      return retval;
2823
2.56k
num_undef:
2824
2.56k
      switch (type) {
2825
1.80k
        case BP_VAR_R:
2826
1.80k
          zend_undefined_offset(hval);
2827
1.80k
          ZEND_FALLTHROUGH;
2828
1.80k
        case BP_VAR_UNSET:
2829
1.88k
        case BP_VAR_IS:
2830
1.88k
          retval = &EG(uninitialized_zval);
2831
1.88k
          break;
2832
675
        case BP_VAR_RW:
2833
675
          retval = zend_undefined_offset_write(ht, hval);
2834
675
          break;
2835
2.56k
        }
2836
39.4k
    } else {
2837
39.4k
      ZEND_HASH_INDEX_LOOKUP(ht, hval, retval);
2838
39.4k
    }
2839
62.5k
  } else if (EXPECTED(Z_TYPE_P(dim) == IS_STRING)) {
2840
27.2k
    offset_key = Z_STR_P(dim);
2841
27.2k
    if (ZEND_CONST_COND(dim_type != IS_CONST, 1)) {
2842
27.2k
      if (ZEND_HANDLE_NUMERIC(offset_key, hval)) {
2843
547
        goto num_index;
2844
547
      }
2845
27.2k
    }
2846
44.1k
str_index:
2847
44.1k
    if (type != BP_VAR_W) {
2848
18.7k
      retval = zend_hash_find_ex(ht, offset_key, ZEND_CONST_COND(dim_type == IS_CONST, 0));
2849
18.7k
      if (!retval) {
2850
4.60k
        switch (type) {
2851
2.07k
          case BP_VAR_R:
2852
2.07k
            zend_undefined_index(offset_key);
2853
2.07k
            ZEND_FALLTHROUGH;
2854
2.08k
          case BP_VAR_UNSET:
2855
2.87k
          case BP_VAR_IS:
2856
2.87k
            retval = &EG(uninitialized_zval);
2857
2.87k
            break;
2858
1.73k
          case BP_VAR_RW:
2859
1.73k
            retval = zend_undefined_index_write(ht, offset_key);
2860
1.73k
            break;
2861
4.60k
        }
2862
4.60k
      }
2863
25.3k
    } else {
2864
25.3k
      retval = zend_hash_lookup(ht, offset_key);
2865
25.3k
    }
2866
44.1k
  } else if (EXPECTED(Z_TYPE_P(dim) == IS_REFERENCE)) {
2867
5
    dim = Z_REFVAL_P(dim);
2868
5
    goto try_again;
2869
20.3k
  } else {
2870
20.3k
    zend_value val;
2871
20.3k
    uint8_t t;
2872
2873
20.3k
    if (type != BP_VAR_W && type != BP_VAR_RW) {
2874
2.71k
      t = slow_index_convert(ht, dim, &val EXECUTE_DATA_CC);
2875
17.6k
    } else {
2876
17.6k
      t = slow_index_convert_w(ht, dim, &val EXECUTE_DATA_CC);
2877
17.6k
    }
2878
20.3k
    if (t == IS_STRING) {
2879
17.3k
      offset_key = val.str;
2880
17.3k
      goto str_index;
2881
17.3k
    } else if (t == IS_LONG) {
2882
2.77k
      hval = val.lval;
2883
2.77k
      goto num_index;
2884
2.77k
    } else {
2885
150
      retval = (type == BP_VAR_W || type == BP_VAR_RW) ?
2886
150
          NULL : &EG(uninitialized_zval);
2887
150
    }
2888
20.3k
  }
2889
86.3k
  return retval;
2890
106k
}
2891
2892
static zend_never_inline zval* ZEND_FASTCALL zend_fetch_dimension_address_inner_W(HashTable *ht, const zval *dim EXECUTE_DATA_DC)
2893
30.7k
{
2894
30.7k
  return zend_fetch_dimension_address_inner(ht, dim, IS_TMP_VAR, BP_VAR_W EXECUTE_DATA_CC);
2895
30.7k
}
2896
2897
static zend_never_inline zval* ZEND_FASTCALL zend_fetch_dimension_address_inner_W_CONST(HashTable *ht, const zval *dim EXECUTE_DATA_DC)
2898
9.89k
{
2899
9.89k
  return zend_fetch_dimension_address_inner(ht, dim, IS_CONST, BP_VAR_W EXECUTE_DATA_CC);
2900
9.89k
}
2901
2902
static zend_never_inline zval* ZEND_FASTCALL zend_fetch_dimension_address_inner_RW(HashTable *ht, const zval *dim EXECUTE_DATA_DC)
2903
6.79k
{
2904
6.79k
  return zend_fetch_dimension_address_inner(ht, dim, IS_TMP_VAR, BP_VAR_RW EXECUTE_DATA_CC);
2905
6.79k
}
2906
2907
static zend_never_inline zval* ZEND_FASTCALL zend_fetch_dimension_address_inner_RW_CONST(HashTable *ht, const zval *dim EXECUTE_DATA_DC)
2908
6.25k
{
2909
6.25k
  return zend_fetch_dimension_address_inner(ht, dim, IS_CONST, BP_VAR_RW EXECUTE_DATA_CC);
2910
6.25k
}
2911
2912
static zend_always_inline void zend_fetch_dimension_address(zval *result, zval *container, zval *dim, int dim_type, int type EXECUTE_DATA_DC)
2913
31.0k
{
2914
31.0k
  zval *retval;
2915
2916
31.0k
  if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
2917
24.1k
try_array:
2918
24.1k
    SEPARATE_ARRAY(container);
2919
29.9k
fetch_from_array:
2920
29.9k
    if (dim == NULL) {
2921
4.19k
      retval = zend_hash_next_index_insert(Z_ARRVAL_P(container), &EG(uninitialized_zval));
2922
4.19k
      if (UNEXPECTED(retval == NULL)) {
2923
35
        zend_cannot_add_element();
2924
35
        ZVAL_UNDEF(result);
2925
35
        return;
2926
35
      }
2927
25.7k
    } else {
2928
25.7k
      retval = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, dim_type, type EXECUTE_DATA_CC);
2929
25.7k
      if (UNEXPECTED(!retval)) {
2930
        /* This may fail without throwing if the array was modified while throwing an
2931
         * undefined index error. */
2932
25
        ZVAL_NULL(result);
2933
25
        return;
2934
25
      }
2935
25.7k
    }
2936
29.8k
    ZVAL_INDIRECT(result, retval);
2937
29.8k
    return;
2938
29.9k
  } else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) {
2939
4.52k
    zend_reference *ref = Z_REF_P(container);
2940
4.52k
    container = Z_REFVAL_P(container);
2941
4.52k
    if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
2942
4.13k
      goto try_array;
2943
4.13k
    } else if (EXPECTED(Z_TYPE_P(container) <= IS_FALSE)) {
2944
338
      if (type != BP_VAR_UNSET) {
2945
338
        if (ZEND_REF_HAS_TYPE_SOURCES(ref)) {
2946
5
          if (UNEXPECTED(!zend_verify_ref_array_assignable(ref))) {
2947
5
            ZVAL_UNDEF(result);
2948
5
            return;
2949
5
          }
2950
5
        }
2951
333
        array_init(container);
2952
333
        goto fetch_from_array;
2953
338
      } else {
2954
0
        goto return_null;
2955
0
      }
2956
338
    }
2957
4.52k
  }
2958
6.57k
  if (UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) {
2959
165
    if (dim == NULL) {
2960
7
      zend_use_new_element_for_string();
2961
158
    } else {
2962
158
      zend_check_string_offset(dim, type EXECUTE_DATA_CC);
2963
158
      zend_wrong_string_offset_error();
2964
158
    }
2965
165
    ZVAL_UNDEF(result);
2966
6.40k
  } else if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
2967
690
    zend_object *obj = Z_OBJ_P(container);
2968
690
    GC_ADDREF(obj);
2969
690
    if (ZEND_CONST_COND(dim_type == IS_CV, dim != NULL) && UNEXPECTED(Z_TYPE_P(dim) == IS_UNDEF)) {
2970
0
      dim = ZVAL_UNDEFINED_OP2();
2971
690
    } else if (dim_type == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) {
2972
0
      dim++;
2973
0
    }
2974
690
    retval = obj->handlers->read_dimension(obj, dim, type, result);
2975
2976
690
    if (UNEXPECTED(retval == &EG(uninitialized_zval))) {
2977
0
      zend_class_entry *ce = obj->ce;
2978
2979
0
      ZVAL_NULL(result);
2980
0
      zend_error(E_NOTICE, "Indirect modification of overloaded element of %s has no effect", ZSTR_VAL(ce->name));
2981
690
    } else if (EXPECTED(retval && Z_TYPE_P(retval) != IS_UNDEF)) {
2982
664
      if (!Z_ISREF_P(retval)) {
2983
337
        if (result != retval) {
2984
320
          ZVAL_COPY(result, retval);
2985
320
          retval = result;
2986
320
        }
2987
337
        if (Z_TYPE_P(retval) != IS_OBJECT) {
2988
213
          zend_class_entry *ce = obj->ce;
2989
213
          zend_error(E_NOTICE, "Indirect modification of overloaded element of %s has no effect", ZSTR_VAL(ce->name));
2990
213
        }
2991
337
      } else if (UNEXPECTED(Z_REFCOUNT_P(retval) == 1)) {
2992
218
        ZVAL_UNREF(retval);
2993
218
      }
2994
664
      if (result != retval) {
2995
192
        ZVAL_INDIRECT(result, retval);
2996
192
      }
2997
664
    } else {
2998
26
      ZEND_ASSERT(EG(exception) && "read_dimension() returned NULL without exception");
2999
26
      ZVAL_UNDEF(result);
3000
26
    }
3001
690
    if (UNEXPECTED(GC_DELREF(obj) == 0)) {
3002
0
      zend_objects_store_del(obj);
3003
0
    }
3004
5.71k
  } else {
3005
5.71k
    if (EXPECTED(Z_TYPE_P(container) <= IS_FALSE)) {
3006
5.53k
      if (type != BP_VAR_W && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
3007
269
        ZVAL_UNDEFINED_OP1();
3008
269
      }
3009
5.53k
      if (type != BP_VAR_UNSET) {
3010
5.39k
        HashTable *ht = zend_new_array(0);
3011
5.39k
        uint8_t old_type = Z_TYPE_P(container);
3012
3013
5.39k
        ZVAL_ARR(container, ht);
3014
5.39k
        if (UNEXPECTED(old_type == IS_FALSE)) {
3015
335
          GC_ADDREF(ht);
3016
335
          zend_false_to_array_deprecated();
3017
335
          if (UNEXPECTED(GC_DELREF(ht) == 0)) {
3018
0
            zend_array_destroy(ht);
3019
0
            goto return_null;
3020
0
          }
3021
335
        }
3022
5.39k
        goto fetch_from_array;
3023
5.39k
      } else {
3024
139
        if (UNEXPECTED(Z_TYPE_P(container) == IS_FALSE)) {
3025
12
          zend_false_to_array_deprecated();
3026
12
        }
3027
139
return_null:
3028
        /* for read-mode only */
3029
139
        if (ZEND_CONST_COND(dim_type == IS_CV, dim != NULL) && UNEXPECTED(Z_TYPE_P(dim) == IS_UNDEF)) {
3030
2
          ZVAL_UNDEFINED_OP2();
3031
2
        }
3032
139
        ZVAL_NULL(result);
3033
139
      }
3034
5.53k
    } else {
3035
185
      if (type == BP_VAR_UNSET) {
3036
21
        zend_throw_error(NULL, "Cannot unset offset in a non-array variable");
3037
21
        ZVAL_UNDEF(result);
3038
164
      } else {
3039
164
        zend_use_scalar_as_array();
3040
164
        ZVAL_UNDEF(result);
3041
164
      }
3042
185
    }
3043
5.71k
  }
3044
6.57k
}
3045
3046
static zend_never_inline void ZEND_FASTCALL zend_fetch_dimension_address_W(zval *container_ptr, zval *dim, int dim_type OPLINE_DC EXECUTE_DATA_DC)
3047
29.2k
{
3048
29.2k
  zval *result = EX_VAR(opline->result.var);
3049
29.2k
  zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_W EXECUTE_DATA_CC);
3050
29.2k
}
3051
3052
static zend_never_inline void ZEND_FASTCALL zend_fetch_dimension_address_RW(zval *container_ptr, zval *dim, int dim_type OPLINE_DC EXECUTE_DATA_DC)
3053
1.60k
{
3054
1.60k
  zval *result = EX_VAR(opline->result.var);
3055
1.60k
  zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_RW EXECUTE_DATA_CC);
3056
1.60k
}
3057
3058
static zend_never_inline void ZEND_FASTCALL zend_fetch_dimension_address_UNSET(zval *container_ptr, zval *dim, int dim_type OPLINE_DC EXECUTE_DATA_DC)
3059
264
{
3060
264
  zval *result = EX_VAR(opline->result.var);
3061
264
  zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_UNSET EXECUTE_DATA_CC);
3062
264
}
3063
3064
static zend_always_inline void zend_fetch_dimension_address_read(zval *result, const zval *container, zval *dim, int dim_type, int type, bool is_list, bool slow EXECUTE_DATA_DC)
3065
31.9k
{
3066
31.9k
  zval *retval;
3067
3068
31.9k
  if (!slow) {
3069
13.2k
    if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
3070
9.85k
try_array:
3071
9.85k
      retval = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, dim_type, type EXECUTE_DATA_CC);
3072
9.85k
      ZVAL_COPY_DEREF(result, retval);
3073
9.85k
      return;
3074
9.83k
    } else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) {
3075
98
      container = Z_REFVAL_P(container);
3076
98
      if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
3077
28
        goto try_array;
3078
28
      }
3079
98
    }
3080
13.2k
  }
3081
22.0k
  if (!is_list && EXPECTED(Z_TYPE_P(container) == IS_STRING)) {
3082
4.16k
    zend_string *str = Z_STR_P(container);
3083
4.16k
    zend_long offset;
3084
3085
4.16k
try_string_offset:
3086
4.16k
    if (UNEXPECTED(Z_TYPE_P(dim) != IS_LONG)) {
3087
1.10k
      switch (Z_TYPE_P(dim)) {
3088
533
        case IS_STRING:
3089
533
        {
3090
533
          bool trailing_data = false;
3091
          /* For BC reasons we allow errors so that we can warn on leading numeric string */
3092
533
          if (IS_LONG == is_numeric_string_ex(Z_STRVAL_P(dim), Z_STRLEN_P(dim), &offset,
3093
533
              NULL, /* allow errors */ true, NULL, &trailing_data)) {
3094
290
            if (UNEXPECTED(trailing_data)) {
3095
121
              zend_error(E_WARNING, "Illegal string offset \"%s\"", Z_STRVAL_P(dim));
3096
121
            }
3097
290
            goto out;
3098
290
          }
3099
243
          if (type == BP_VAR_IS) {
3100
51
            ZVAL_NULL(result);
3101
51
            return;
3102
51
          }
3103
192
          zend_illegal_string_offset(dim, BP_VAR_R);
3104
192
          ZVAL_NULL(result);
3105
192
          return;
3106
243
        }
3107
75
        case IS_UNDEF:
3108
          /* The string may be destroyed while throwing the notice.
3109
           * Temporarily increase the refcount to detect this situation. */
3110
75
          if (!(GC_FLAGS(str) & IS_STR_INTERNED)) {
3111
6
            GC_ADDREF(str);
3112
6
          }
3113
75
          ZVAL_UNDEFINED_OP2();
3114
75
          if (!(GC_FLAGS(str) & IS_STR_INTERNED) && UNEXPECTED(GC_DELREF(str) == 0)) {
3115
0
            zend_string_efree(str);
3116
0
            ZVAL_NULL(result);
3117
0
            return;
3118
0
          }
3119
75
          ZEND_FALLTHROUGH;
3120
473
        case IS_DOUBLE:
3121
491
        case IS_NULL:
3122
521
        case IS_FALSE:
3123
539
        case IS_TRUE:
3124
539
          if (type != BP_VAR_IS) {
3125
            /* The string may be destroyed while throwing the notice.
3126
             * Temporarily increase the refcount to detect this situation. */
3127
524
            if (!(GC_FLAGS(str) & IS_STR_INTERNED)) {
3128
8
              GC_ADDREF(str);
3129
8
            }
3130
524
            zend_error(E_WARNING, "String offset cast occurred");
3131
524
            if (!(GC_FLAGS(str) & IS_STR_INTERNED) && UNEXPECTED(GC_DELREF(str) == 0)) {
3132
0
              zend_string_efree(str);
3133
0
              ZVAL_NULL(result);
3134
0
              return;
3135
0
            }
3136
524
          }
3137
          /* To prevent double warning */
3138
539
          if (Z_TYPE_P(dim) == IS_DOUBLE) {
3139
398
            offset = zend_dval_to_lval_silent(Z_DVAL_P(dim));
3140
398
            goto out;
3141
398
          }
3142
141
          break;
3143
141
        case IS_REFERENCE:
3144
0
          dim = Z_REFVAL_P(dim);
3145
0
          goto try_string_offset;
3146
32
        default:
3147
32
          zend_illegal_string_offset(dim, BP_VAR_R);
3148
32
          ZVAL_NULL(result);
3149
32
          return;
3150
1.10k
      }
3151
3152
141
      offset = zval_get_long_func(dim, /* is_strict */ false);
3153
3.05k
    } else {
3154
3.05k
      offset = Z_LVAL_P(dim);
3155
3.05k
    }
3156
3.88k
    out:
3157
3158
3.88k
    if (UNEXPECTED(ZSTR_LEN(str) < ((offset < 0) ? -(size_t)offset : ((size_t)offset + 1)))) {
3159
1.41k
      if (type != BP_VAR_IS) {
3160
1.40k
        zend_error(E_WARNING, "Uninitialized string offset " ZEND_LONG_FMT, offset);
3161
1.40k
        ZVAL_EMPTY_STRING(result);
3162
1.40k
      } else {
3163
16
        ZVAL_NULL(result);
3164
16
      }
3165
2.46k
    } else {
3166
2.46k
      zend_uchar c;
3167
2.46k
      zend_long real_offset;
3168
3169
2.46k
      real_offset = (UNEXPECTED(offset < 0)) /* Handle negative offset */
3170
2.46k
        ? (zend_long)ZSTR_LEN(str) + offset : offset;
3171
2.46k
      c = (zend_uchar)ZSTR_VAL(str)[real_offset];
3172
3173
2.46k
      ZVAL_CHAR(result, c);
3174
2.46k
    }
3175
17.8k
  } else if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
3176
2.67k
    zend_object *obj = Z_OBJ_P(container);
3177
3178
2.67k
    GC_ADDREF(obj);
3179
2.67k
    if (ZEND_CONST_COND(dim_type == IS_CV, 1) && UNEXPECTED(Z_TYPE_P(dim) == IS_UNDEF)) {
3180
7
      dim = ZVAL_UNDEFINED_OP2();
3181
7
    }
3182
2.67k
    if (dim_type == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) {
3183
8
      dim++;
3184
8
    }
3185
2.67k
    retval = obj->handlers->read_dimension(obj, dim, type, result);
3186
3187
2.67k
    ZEND_ASSERT(result != NULL);
3188
2.67k
    if (retval) {
3189
2.11k
      if (result != retval) {
3190
1.55k
        ZVAL_COPY_DEREF(result, retval);
3191
1.55k
      } else if (UNEXPECTED(Z_ISREF_P(retval))) {
3192
137
        zend_unwrap_reference(result);
3193
137
      }
3194
2.11k
    } else {
3195
72
      ZVAL_NULL(result);
3196
72
    }
3197
2.18k
    if (UNEXPECTED(GC_DELREF(obj) == 0)) {
3198
7
      zend_objects_store_del(obj);
3199
7
    }
3200
15.2k
  } else {
3201
15.2k
    if (type != BP_VAR_IS && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
3202
9.14k
      container = ZVAL_UNDEFINED_OP1();
3203
9.14k
    }
3204
15.2k
    if (ZEND_CONST_COND(dim_type == IS_CV, 1) && UNEXPECTED(Z_TYPE_P(dim) == IS_UNDEF)) {
3205
2.34k
      ZVAL_UNDEFINED_OP2();
3206
2.34k
    }
3207
15.2k
    if (is_list && Z_TYPE_P(container) > IS_NULL) {
3208
323
      zend_error(E_WARNING, "Cannot use %s as array", zend_zval_type_name(container));
3209
323
    }
3210
15.2k
    if (!is_list && type != BP_VAR_IS) {
3211
13.5k
      zend_error(E_WARNING, "Trying to access array offset on %s",
3212
13.5k
        zend_zval_value_name(container));
3213
13.5k
    }
3214
15.2k
    ZVAL_NULL(result);
3215
15.2k
  }
3216
22.0k
}
3217
3218
static zend_never_inline void ZEND_FASTCALL zend_fetch_dimension_address_read_R(const zval *container, zval *dim, int dim_type OPLINE_DC EXECUTE_DATA_DC)
3219
2.34k
{
3220
2.34k
  zval *result = EX_VAR(opline->result.var);
3221
2.34k
  zend_fetch_dimension_address_read(result, container, dim, dim_type, BP_VAR_R, 0, 0 EXECUTE_DATA_CC);
3222
2.34k
}
3223
3224
static zend_never_inline void zend_fetch_dimension_address_read_R_slow(const zval *container, zval *dim OPLINE_DC EXECUTE_DATA_DC)
3225
18.6k
{
3226
18.6k
  zval *result = EX_VAR(opline->result.var);
3227
18.6k
  zend_fetch_dimension_address_read(result, container, dim, IS_CV, BP_VAR_R, 0, 1 EXECUTE_DATA_CC);
3228
18.6k
}
3229
3230
static zend_never_inline void ZEND_FASTCALL zend_fetch_dimension_address_read_IS(const zval *container, zval *dim, int dim_type OPLINE_DC EXECUTE_DATA_DC)
3231
4.31k
{
3232
4.31k
  zval *result = EX_VAR(opline->result.var);
3233
4.31k
  zend_fetch_dimension_address_read(result, container, dim, dim_type, BP_VAR_IS, 0, 0 EXECUTE_DATA_CC);
3234
4.31k
}
3235
3236
static zend_never_inline void ZEND_FASTCALL zend_fetch_dimension_address_LIST_r(const zval *container, zval *dim, int dim_type OPLINE_DC EXECUTE_DATA_DC)
3237
6.35k
{
3238
6.35k
  zval *result = EX_VAR(opline->result.var);
3239
6.35k
  zend_fetch_dimension_address_read(result, container, dim, dim_type, BP_VAR_R, 1, 0 EXECUTE_DATA_CC);
3240
6.35k
}
3241
3242
ZEND_API void zend_fetch_dimension_const(zval *result, const zval *container, zval *dim, int type)
3243
282
{
3244
282
  zend_fetch_dimension_address_read(result, container, dim, IS_TMP_VAR, type, 0, 0 NO_EXECUTE_DATA_CC);
3245
282
}
3246
3247
static zend_never_inline zval* ZEND_FASTCALL zend_find_array_dim_slow(HashTable *ht, const zval *offset EXECUTE_DATA_DC)
3248
373
{
3249
373
  zend_ulong hval;
3250
3251
373
  if (Z_TYPE_P(offset) == IS_DOUBLE) {
3252
    /* The array may be destroyed while throwing a warning in case the float is not representable as an int.
3253
     * Temporarily increase the refcount to detect this situation. */
3254
13
    GC_TRY_ADDREF(ht);
3255
13
    hval = zend_dval_to_lval_safe(Z_DVAL_P(offset));
3256
13
    if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) {
3257
0
      zend_array_destroy(ht);
3258
0
      return NULL;
3259
0
    }
3260
13
    if (EG(exception)) {
3261
0
      return NULL;
3262
0
    }
3263
33
num_idx:
3264
33
    return zend_hash_index_find(ht, hval);
3265
360
  } else if (Z_TYPE_P(offset) == IS_NULL) {
3266
305
null_undef_idx:
3267
    /* The array may be destroyed while throwing the notice.
3268
     * Temporarily increase the refcount to detect this situation. */
3269
305
    GC_TRY_ADDREF(ht);
3270
3271
305
    zend_error(E_DEPRECATED, "Using null as an array offset is deprecated, use an empty string instead");
3272
3273
305
    if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) {
3274
0
      zend_array_destroy(ht);
3275
0
      return NULL;
3276
0
    }
3277
3278
305
    if (EG(exception)) {
3279
0
      return NULL;
3280
0
    }
3281
3282
305
    return zend_hash_find_known_hash(ht, ZSTR_EMPTY_ALLOC());
3283
345
  } else if (Z_TYPE_P(offset) == IS_FALSE) {
3284
10
    hval = 0;
3285
10
    goto num_idx;
3286
335
  } else if (Z_TYPE_P(offset) == IS_TRUE) {
3287
10
    hval = 1;
3288
10
    goto num_idx;
3289
325
  } else if (Z_TYPE_P(offset) == IS_RESOURCE) {
3290
0
    zend_use_resource_as_offset(offset);
3291
0
    hval = Z_RES_HANDLE_P(offset);
3292
0
    goto num_idx;
3293
325
  } else if (/*OP2_TYPE == IS_CV &&*/ Z_TYPE_P(offset) == IS_UNDEF) {
3294
290
    ZVAL_UNDEFINED_OP2();
3295
290
    goto null_undef_idx;
3296
290
  } else {
3297
35
    zend_illegal_array_offset_isset(offset);
3298
35
    return NULL;
3299
35
  }
3300
373
}
3301
3302
static zend_never_inline bool ZEND_FASTCALL zend_isset_dim_slow(const zval *container, zval *offset EXECUTE_DATA_DC)
3303
2.45k
{
3304
2.45k
  if (/*OP2_TYPE == IS_CV &&*/ UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) {
3305
54
    offset = ZVAL_UNDEFINED_OP2();
3306
54
  }
3307
3308
2.45k
  if (/*OP1_TYPE != IS_CONST &&*/ EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
3309
429
    return Z_OBJ_HT_P(container)->has_dimension(Z_OBJ_P(container), offset, 0);
3310
2.03k
  } else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */
3311
534
    zend_long lval;
3312
3313
534
    if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
3314
155
      lval = Z_LVAL_P(offset);
3315
390
str_offset:
3316
390
      if (UNEXPECTED(lval < 0)) { /* Handle negative offset */
3317
77
        lval += (zend_long)Z_STRLEN_P(container);
3318
77
      }
3319
390
      if (EXPECTED(lval >= 0) && (size_t)lval < Z_STRLEN_P(container)) {
3320
299
        return 1;
3321
299
      } else {
3322
91
        return 0;
3323
91
      }
3324
390
    } else {
3325
      /*if (OP2_TYPE & (IS_CV|IS_VAR)) {*/
3326
379
        ZVAL_DEREF(offset);
3327
      /*}*/
3328
379
      if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
3329
305
          || (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
3330
285
            && IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
3331
235
        lval = zval_get_long_ex(offset, /* is_strict */ true);
3332
235
        goto str_offset;
3333
235
      }
3334
144
      return 0;
3335
379
    }
3336
1.49k
  } else {
3337
1.49k
    return 0;
3338
1.49k
  }
3339
2.45k
}
3340
3341
static zend_never_inline bool ZEND_FASTCALL zend_isempty_dim_slow(const zval *container, zval *offset EXECUTE_DATA_DC)
3342
520
{
3343
520
  if (/*OP2_TYPE == IS_CV &&*/ UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) {
3344
35
    offset = ZVAL_UNDEFINED_OP2();
3345
35
  }
3346
3347
520
  if (/*OP1_TYPE != IS_CONST &&*/ EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
3348
107
    return !Z_OBJ_HT_P(container)->has_dimension(Z_OBJ_P(container), offset, 1);
3349
413
  } else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */
3350
291
    zend_long lval;
3351
3352
291
    if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
3353
103
      lval = Z_LVAL_P(offset);
3354
218
str_offset:
3355
218
      if (UNEXPECTED(lval < 0)) { /* Handle negative offset */
3356
59
        lval += (zend_long)Z_STRLEN_P(container);
3357
59
      }
3358
218
      if (EXPECTED(lval >= 0) && (size_t)lval < Z_STRLEN_P(container)) {
3359
172
        return (Z_STRVAL_P(container)[lval] == '0');
3360
172
      } else {
3361
46
        return 1;
3362
46
      }
3363
218
    } else {
3364
      /*if (OP2_TYPE & (IS_CV|IS_VAR)) {*/
3365
188
        ZVAL_DEREF(offset);
3366
      /*}*/
3367
188
      if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
3368
123
          || (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
3369
115
            && IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
3370
115
        lval = zval_get_long_ex(offset, /* is_strict */ true);
3371
115
        goto str_offset;
3372
115
      }
3373
73
      return 1;
3374
188
    }
3375
291
  } else {
3376
122
    return 1;
3377
122
  }
3378
520
}
3379
3380
static zend_never_inline bool ZEND_FASTCALL zend_array_key_exists_fast(HashTable *ht, const zval *key OPLINE_DC EXECUTE_DATA_DC)
3381
419
{
3382
419
  zend_string *str;
3383
419
  zend_ulong hval;
3384
3385
419
try_again:
3386
419
  if (EXPECTED(Z_TYPE_P(key) == IS_STRING)) {
3387
287
    str = Z_STR_P(key);
3388
287
    if (ZEND_HANDLE_NUMERIC(str, hval)) {
3389
0
      goto num_key;
3390
0
    }
3391
298
str_key:
3392
298
    return zend_hash_exists(ht, str);
3393
287
  } else if (EXPECTED(Z_TYPE_P(key) == IS_LONG)) {
3394
118
    hval = Z_LVAL_P(key);
3395
121
num_key:
3396
121
    return zend_hash_index_exists(ht, hval);
3397
118
  } else if (EXPECTED(Z_ISREF_P(key))) {
3398
0
    key = Z_REFVAL_P(key);
3399
0
    goto try_again;
3400
14
  } else if (Z_TYPE_P(key) == IS_DOUBLE) {
3401
    /* The array may be destroyed while throwing a warning in case the float is not representable as an int.
3402
     * Temporarily increase the refcount to detect this situation. */
3403
3
    GC_TRY_ADDREF(ht);
3404
3
    hval = zend_dval_to_lval_safe(Z_DVAL_P(key));
3405
3
    if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) {
3406
0
      zend_array_destroy(ht);
3407
0
      return false;
3408
0
    }
3409
3
    if (EG(exception)) {
3410
0
      return false;
3411
0
    }
3412
3
    goto num_key;
3413
11
  } else if (Z_TYPE_P(key) == IS_FALSE) {
3414
0
    hval = 0;
3415
0
    goto num_key;
3416
11
  } else if (Z_TYPE_P(key) == IS_TRUE) {
3417
0
    hval = 1;
3418
0
    goto num_key;
3419
11
  } else if (Z_TYPE_P(key) == IS_RESOURCE) {
3420
0
    zend_use_resource_as_offset(key);
3421
0
    hval = Z_RES_HANDLE_P(key);
3422
0
    goto num_key;
3423
11
  } else if (Z_TYPE_P(key) <= IS_NULL) {
3424
11
    if (UNEXPECTED(Z_TYPE_P(key) == IS_UNDEF)) {
3425
0
      ZVAL_UNDEFINED_OP1();
3426
11
    } else {
3427
11
      ZEND_ASSERT(Z_TYPE_P(key) == IS_NULL);
3428
11
      zend_error(E_DEPRECATED, "Using null as the key parameter for array_key_exists() is deprecated, use an empty string instead");
3429
11
    }
3430
11
    str = ZSTR_EMPTY_ALLOC();
3431
11
    goto str_key;
3432
11
  } else {
3433
0
    zend_illegal_array_offset_access(key);
3434
0
    return 0;
3435
0
  }
3436
419
}
3437
3438
static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_array_key_exists_error(
3439
    const zval *subject, const zval *key OPLINE_DC EXECUTE_DATA_DC)
3440
30
{
3441
30
  if (Z_TYPE_P(key) == IS_UNDEF) {
3442
2
    ZVAL_UNDEFINED_OP1();
3443
2
  }
3444
30
  if (Z_TYPE_P(subject) == IS_UNDEF) {
3445
9
    ZVAL_UNDEFINED_OP2();
3446
9
  }
3447
30
  if (!EG(exception)) {
3448
30
    zend_type_error("array_key_exists(): Argument #2 ($array) must be of type array, %s given",
3449
30
      zend_zval_value_name(subject));
3450
30
  }
3451
30
}
3452
3453
170
static zend_always_inline bool promotes_to_array(const zval *val) {
3454
170
  return Z_TYPE_P(val) <= IS_FALSE
3455
89
    || (Z_ISREF_P(val) && Z_TYPE_P(Z_REFVAL_P(val)) <= IS_FALSE);
3456
170
}
3457
3458
105
static zend_always_inline bool check_type_array_assignable(zend_type type) {
3459
105
  if (!ZEND_TYPE_IS_SET(type)) {
3460
0
    return 1;
3461
0
  }
3462
105
  return (ZEND_TYPE_FULL_MASK(type) & MAY_BE_ARRAY) != 0;
3463
105
}
3464
3465
/* Checks whether an array can be assigned to the reference. Throws error if not assignable. */
3466
24
ZEND_API bool zend_verify_ref_array_assignable(zend_reference *ref) {
3467
24
  zend_property_info *prop;
3468
24
  ZEND_ASSERT(ZEND_REF_HAS_TYPE_SOURCES(ref));
3469
72
  ZEND_REF_FOREACH_TYPE_SOURCES(ref, prop) {
3470
72
    if (!check_type_array_assignable(prop->type)) {
3471
13
      zend_throw_auto_init_in_ref_error(prop);
3472
13
      return 0;
3473
13
    }
3474
72
  } ZEND_REF_FOREACH_TYPE_SOURCES_END();
3475
11
  return 1;
3476
24
}
3477
3478
static zend_never_inline bool zend_handle_fetch_obj_flags(
3479
    zval *result, zval *ptr, zend_object *obj, zend_property_info *prop_info, uint32_t flags)
3480
1.94k
{
3481
1.94k
  switch (flags) {
3482
170
    case ZEND_FETCH_DIM_WRITE:
3483
170
      if (promotes_to_array(ptr)) {
3484
81
        if (!prop_info) {
3485
0
          break;
3486
0
        }
3487
81
        if (!check_type_array_assignable(prop_info->type)) {
3488
35
          zend_throw_auto_init_in_prop_error(prop_info);
3489
35
          if (result) ZVAL_ERROR(result);
3490
35
          return 0;
3491
35
        }
3492
81
      }
3493
135
      break;
3494
1.77k
    case ZEND_FETCH_REF:
3495
1.77k
      if (Z_TYPE_P(ptr) != IS_REFERENCE) {
3496
1.10k
        if (!prop_info) {
3497
0
          break;
3498
0
        }
3499
1.10k
        if (Z_TYPE_P(ptr) == IS_UNDEF) {
3500
79
          if (!ZEND_TYPE_ALLOW_NULL(prop_info->type)) {
3501
17
            zend_throw_access_uninit_prop_by_ref_error(prop_info);
3502
17
            if (result) ZVAL_ERROR(result);
3503
17
            return 0;
3504
17
          }
3505
62
          ZVAL_NULL(ptr);
3506
62
        }
3507
3508
1.09k
        ZVAL_NEW_REF(ptr, ptr);
3509
1.09k
        ZEND_REF_ADD_TYPE_SOURCE(Z_REF_P(ptr), prop_info);
3510
1.09k
      }
3511
1.75k
      break;
3512
1.75k
    default: ZEND_UNREACHABLE();
3513
1.94k
  }
3514
1.88k
  return 1;
3515
1.94k
}
3516
3517
static zend_always_inline void zend_fetch_property_address(
3518
  zval *result,
3519
  const zval *container,
3520
  uint32_t container_op_type,
3521
  const zval *prop_ptr,
3522
  uint32_t prop_op_type,
3523
  void **cache_slot,
3524
  int type,
3525
  uint32_t flags,
3526
  zend_property_info **prop_info_p
3527
  OPLINE_DC EXECUTE_DATA_DC
3528
12.1k
) {
3529
12.1k
  zval *ptr;
3530
12.1k
  zend_object *zobj;
3531
12.1k
  zend_string *name, *tmp_name;
3532
12.1k
  void *_cache_slot[3] = {0};
3533
12.1k
  if (prop_op_type != IS_CONST) {
3534
2.41k
    cache_slot = _cache_slot;
3535
9.76k
  } else {
3536
9.76k
    ZEND_ASSERT(cache_slot);
3537
9.76k
  }
3538
3539
12.1k
  if (container_op_type != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
3540
595
    do {
3541
595
      if (Z_ISREF_P(container) && Z_TYPE_P(Z_REFVAL_P(container)) == IS_OBJECT) {
3542
239
        container = Z_REFVAL_P(container);
3543
239
        break;
3544
239
      }
3545
3546
356
      if (container_op_type == IS_CV
3547
204
       && type != BP_VAR_W
3548
60
       && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
3549
60
        ZVAL_UNDEFINED_OP1();
3550
60
      }
3551
3552
      /* this should modify object only if it's empty */
3553
356
      if (type == BP_VAR_UNSET) {
3554
72
        ZVAL_NULL(result);
3555
72
        return;
3556
72
      }
3557
3558
284
      zend_throw_non_object_error(container, prop_ptr OPLINE_CC EXECUTE_DATA_CC);
3559
284
      ZVAL_ERROR(result);
3560
284
      return;
3561
356
    } while (0);
3562
595
  }
3563
3564
11.8k
  zobj = Z_OBJ_P(container);
3565
11.8k
  if (prop_op_type == IS_CONST &&
3566
9.50k
      EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) {
3567
5.06k
    uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1);
3568
5.06k
    if (prop_info_p) {
3569
123
      *prop_info_p = CACHED_PTR_EX(cache_slot + 2);
3570
123
    }
3571
3572
5.06k
    if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) {
3573
3.35k
      ptr = OBJ_PROP(zobj, prop_offset);
3574
3.35k
      if (EXPECTED(Z_TYPE_P(ptr) != IS_UNDEF)) {
3575
3.15k
        ZVAL_INDIRECT(result, ptr);
3576
3.15k
        zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2);
3577
3.15k
        if (prop_info) {
3578
689
          if (UNEXPECTED(prop_info->flags & (ZEND_ACC_READONLY|ZEND_ACC_PPP_SET_MASK))
3579
63
           && ((prop_info->flags & ZEND_ACC_READONLY) || !zend_asymmetric_property_has_set_access(prop_info))) {
3580
            /* For objects, W/RW/UNSET fetch modes might not actually modify object.
3581
             * Similar as with magic __get() allow them, but return the value as a copy
3582
             * to make sure no actual modification is possible. */
3583
63
            ZEND_ASSERT(type == BP_VAR_W || type == BP_VAR_RW || type == BP_VAR_UNSET);
3584
63
            if (Z_TYPE_P(ptr) == IS_OBJECT) {
3585
25
              ZVAL_COPY(result, ptr);
3586
38
            } else {
3587
38
              if (prop_info->flags & ZEND_ACC_READONLY) {
3588
29
                zend_readonly_property_indirect_modification_error(prop_info);
3589
29
              } else {
3590
9
                zend_asymmetric_visibility_property_modification_error(prop_info, "indirectly modify");
3591
9
              }
3592
38
              ZVAL_ERROR(result);
3593
38
            }
3594
63
            return;
3595
63
          }
3596
626
          flags &= ZEND_FETCH_OBJ_FLAGS;
3597
626
          if (flags) {
3598
302
            zend_handle_fetch_obj_flags(result, ptr, NULL, prop_info, flags);
3599
302
          }
3600
626
        }
3601
3.08k
        return;
3602
3.15k
      }
3603
3.35k
    } else if (UNEXPECTED(IS_HOOKED_PROPERTY_OFFSET(prop_offset))) {
3604
      /* Fall through to read_property for hooks. */
3605
1.66k
    } else if (EXPECTED(zobj->properties != NULL)) {
3606
913
      ZEND_ASSERT(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset));
3607
913
      if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) {
3608
3
        if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) {
3609
3
          GC_DELREF(zobj->properties);
3610
3
        }
3611
3
        zobj->properties = zend_array_dup(zobj->properties);
3612
3
      }
3613
913
      ptr = zend_hash_find_known_hash(zobj->properties, Z_STR_P(prop_ptr));
3614
913
      if (EXPECTED(ptr)) {
3615
857
        ZVAL_INDIRECT(result, ptr);
3616
857
        return;
3617
857
      }
3618
913
    }
3619
6.76k
  } else if (prop_op_type == IS_CONST) {
3620
    /* CE mismatch, make cache slot consistent */
3621
4.44k
    cache_slot[0] = cache_slot[1] = cache_slot[2] = NULL;
3622
4.44k
  }
3623
3624
  /* Pointer on property callback is required */
3625
7.82k
  ZEND_ASSERT(zobj->handlers->get_property_ptr_ptr != NULL);
3626
3627
7.82k
  if (prop_op_type == IS_CONST) {
3628
5.49k
    name = Z_STR_P(prop_ptr);
3629
5.49k
  } else {
3630
2.32k
    name = zval_get_tmp_string(prop_ptr, &tmp_name);
3631
2.32k
  }
3632
7.82k
  ptr = zobj->handlers->get_property_ptr_ptr(zobj, name, type, cache_slot);
3633
7.82k
  if (NULL == ptr) {
3634
1.30k
    ptr = zobj->handlers->read_property(zobj, name, type, cache_slot, result);
3635
1.30k
    if (ptr == result) {
3636
930
      if (UNEXPECTED(Z_ISREF_P(ptr) && Z_REFCOUNT_P(ptr) == 1)) {
3637
37
        ZVAL_UNREF(ptr);
3638
37
      }
3639
930
      goto end;
3640
930
    }
3641
374
    if (UNEXPECTED(EG(exception))) {
3642
268
      ZVAL_ERROR(result);
3643
268
      goto end;
3644
268
    }
3645
6.51k
  } else if (UNEXPECTED(Z_ISERROR_P(ptr))) {
3646
26
    ZVAL_ERROR(result);
3647
26
    goto end;
3648
6.49k
  } else if (type == BP_VAR_UNSET && UNEXPECTED(Z_TYPE_P(ptr) == IS_UNDEF)) {
3649
18
    ZVAL_NULL(result);
3650
18
    goto end;
3651
18
  }
3652
3653
6.57k
  ZVAL_INDIRECT(result, ptr);
3654
6.57k
  flags &= ZEND_FETCH_OBJ_FLAGS;
3655
6.57k
  if (flags) {
3656
4.60k
    zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2);
3657
4.60k
    if (prop_info && ZEND_TYPE_IS_SET(prop_info->type)) {
3658
1.47k
      if (UNEXPECTED(!zend_handle_fetch_obj_flags(result, ptr, NULL, prop_info, flags))) {
3659
33
        goto end;
3660
33
      }
3661
1.47k
    }
3662
4.60k
  }
3663
3664
7.82k
end:
3665
7.82k
  if (prop_info_p) {
3666
1.55k
    *prop_info_p = CACHED_PTR_EX(cache_slot + 2);
3667
1.55k
  }
3668
7.82k
  if (prop_op_type != IS_CONST) {
3669
2.32k
    zend_tmp_string_release(tmp_name);
3670
2.32k
  }
3671
7.82k
}
3672
3673
static zend_always_inline void zend_assign_to_property_reference(
3674
  const zval *container,
3675
  uint32_t container_op_type,
3676
  const zval *prop_ptr,
3677
  uint32_t prop_op_type,
3678
  zval *value_ptr
3679
  OPLINE_DC EXECUTE_DATA_DC
3680
1.71k
) {
3681
1.71k
  zval variable, *variable_ptr = &variable;
3682
1.71k
  void **cache_addr = (prop_op_type == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_RETURNS_FUNCTION) : NULL;
3683
1.71k
  zend_refcounted *garbage = NULL;
3684
1.71k
  zend_property_info *prop_info = NULL;
3685
3686
1.71k
  zend_fetch_property_address(variable_ptr, container, container_op_type, prop_ptr, prop_op_type,
3687
1.71k
    cache_addr, BP_VAR_W, 0, &prop_info OPLINE_CC EXECUTE_DATA_CC);
3688
3689
1.71k
  if (EXPECTED(Z_TYPE_P(variable_ptr) == IS_INDIRECT)) {
3690
1.57k
    variable_ptr = Z_INDIRECT_P(variable_ptr);
3691
1.57k
    if (/*OP_DATA_TYPE == IS_VAR &&*/
3692
1.57k
           (opline->extended_value & ZEND_RETURNS_FUNCTION) &&
3693
4
           UNEXPECTED(!Z_ISREF_P(value_ptr))) {
3694
3695
4
      variable_ptr = zend_wrong_assign_to_variable_reference(
3696
4
        variable_ptr, value_ptr, &garbage OPLINE_CC EXECUTE_DATA_CC);
3697
1.56k
    } else if (prop_info && ZEND_TYPE_IS_SET(prop_info->type)) {
3698
834
      variable_ptr = zend_assign_to_typed_property_reference(prop_info, variable_ptr, value_ptr, &garbage EXECUTE_DATA_CC);
3699
834
    } else {
3700
734
      zend_assign_to_variable_reference(variable_ptr, value_ptr, &garbage);
3701
734
    }
3702
1.57k
  } else if (Z_ISERROR_P(variable_ptr)) {
3703
90
    variable_ptr = &EG(uninitialized_zval);
3704
90
  } else {
3705
52
    zend_throw_error(NULL, "Cannot assign by reference to overloaded object");
3706
52
    zval_ptr_dtor(&variable);
3707
52
    variable_ptr = &EG(uninitialized_zval);
3708
52
  }
3709
3710
1.71k
  if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
3711
324
    ZVAL_COPY(EX_VAR(opline->result.var), variable_ptr);
3712
324
  }
3713
1.71k
  if (garbage) {
3714
726
    GC_DTOR(garbage);
3715
726
  }
3716
1.71k
}
3717
3718
static zend_never_inline void zend_assign_to_property_reference_this_const(const zval *container, const zval *prop_ptr, zval *value_ptr OPLINE_DC EXECUTE_DATA_DC)
3719
169
{
3720
169
  zend_assign_to_property_reference(container, IS_UNUSED, prop_ptr, IS_CONST, value_ptr
3721
169
    OPLINE_CC EXECUTE_DATA_CC);
3722
169
}
3723
3724
static zend_never_inline void zend_assign_to_property_reference_var_const(const zval *container, const zval *prop_ptr, zval *value_ptr OPLINE_DC EXECUTE_DATA_DC)
3725
641
{
3726
641
  zend_assign_to_property_reference(container, IS_VAR, prop_ptr, IS_CONST, value_ptr
3727
641
    OPLINE_CC EXECUTE_DATA_CC);
3728
641
}
3729
3730
static zend_never_inline void zend_assign_to_property_reference_this_var(const zval *container, const zval *prop_ptr, zval *value_ptr OPLINE_DC EXECUTE_DATA_DC)
3731
7
{
3732
7
  zend_assign_to_property_reference(container, IS_UNUSED, prop_ptr, IS_VAR, value_ptr
3733
7
    OPLINE_CC EXECUTE_DATA_CC);
3734
7
}
3735
3736
static zend_never_inline void zend_assign_to_property_reference_var_var(const zval *container, const zval *prop_ptr, zval *value_ptr OPLINE_DC EXECUTE_DATA_DC)
3737
897
{
3738
897
  zend_assign_to_property_reference(container, IS_VAR, prop_ptr, IS_VAR, value_ptr
3739
897
    OPLINE_CC EXECUTE_DATA_CC);
3740
897
}
3741
3742
4.20k
static zend_never_inline zval* zend_fetch_static_property_address_ex(zend_property_info **prop_info, uint32_t cache_slot, int fetch_type OPLINE_DC EXECUTE_DATA_DC) {
3743
4.20k
  zval *result;
3744
4.20k
  zend_string *name;
3745
4.20k
  zend_class_entry *ce;
3746
4.20k
  zend_property_info *property_info;
3747
3748
4.20k
  uint8_t op1_type = opline->op1_type, op2_type = opline->op2_type;
3749
3750
4.20k
  if (EXPECTED(op2_type == IS_CONST)) {
3751
2.49k
    zval *class_name = RT_CONSTANT(opline, opline->op2);
3752
3753
2.49k
    ZEND_ASSERT(op1_type != IS_CONST || CACHED_PTR(cache_slot) == NULL);
3754
3755
2.49k
    if (EXPECTED((ce = CACHED_PTR(cache_slot)) == NULL)) {
3756
2.35k
      ce = zend_fetch_class_by_name(Z_STR_P(class_name), Z_STR_P(class_name + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
3757
2.35k
      if (UNEXPECTED(ce == NULL)) {
3758
150
        FREE_OP(op1_type, opline->op1.var);
3759
150
        return NULL;
3760
150
      }
3761
2.20k
      if (UNEXPECTED(op1_type != IS_CONST)) {
3762
61
        CACHE_PTR(cache_slot, ce);
3763
61
      }
3764
2.20k
    }
3765
2.49k
  } else {
3766
1.71k
    if (EXPECTED(op2_type == IS_UNUSED)) {
3767
1.60k
      ce = zend_fetch_class(NULL, opline->op2.num);
3768
1.60k
      if (UNEXPECTED(ce == NULL)) {
3769
31
        FREE_OP(op1_type, opline->op1.var);
3770
31
        return NULL;
3771
31
      }
3772
1.60k
    } else {
3773
112
      ce = Z_CE_P(EX_VAR(opline->op2.var));
3774
112
    }
3775
1.68k
    if (EXPECTED(op1_type == IS_CONST) && EXPECTED(CACHED_PTR(cache_slot) == ce)) {
3776
45
      result = CACHED_PTR(cache_slot + sizeof(void *));
3777
45
      *prop_info = CACHED_PTR(cache_slot + sizeof(void *) * 2);
3778
45
      return result;
3779
45
    }
3780
1.68k
  }
3781
3782
3.97k
  if (EXPECTED(op1_type == IS_CONST)) {
3783
3.77k
    name = Z_STR_P(RT_CONSTANT(opline, opline->op1));
3784
3.77k
    result = zend_std_get_static_property_with_info(ce, name, fetch_type, &property_info);
3785
3.77k
  } else {
3786
209
    zend_string *tmp_name;
3787
209
    zval *varname = get_zval_ptr_undef(opline->op1_type, opline->op1, BP_VAR_R);
3788
209
    if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) {
3789
171
      name = Z_STR_P(varname);
3790
171
      tmp_name = NULL;
3791
171
    } else {
3792
38
      if (op1_type == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) {
3793
20
        zval_undefined_cv(opline->op1.var EXECUTE_DATA_CC);
3794
20
      }
3795
38
      name = zval_get_tmp_string(varname, &tmp_name);
3796
38
    }
3797
209
    result = zend_std_get_static_property_with_info(ce, name, fetch_type, &property_info);
3798
3799
209
    zend_tmp_string_release(tmp_name);
3800
3801
209
    FREE_OP(op1_type, opline->op1.var);
3802
209
  }
3803
3804
3.97k
  if (UNEXPECTED(result == NULL)) {
3805
546
    return NULL;
3806
546
  }
3807
3808
3.43k
  if (UNEXPECTED(Z_TYPE_P(result) == IS_UNDEF)
3809
429
   && (fetch_type == BP_VAR_IS || fetch_type == BP_VAR_UNSET)) {
3810
38
    return NULL;
3811
38
   }
3812
3813
3.39k
  *prop_info = property_info;
3814
3815
3.39k
  if (EXPECTED(op1_type == IS_CONST)
3816
3.26k
      && EXPECTED(!(property_info->ce->ce_flags & ZEND_ACC_TRAIT))) {
3817
3.17k
    CACHE_POLYMORPHIC_PTR(cache_slot, ce, result);
3818
3.17k
    CACHE_PTR(cache_slot + sizeof(void *) * 2, property_info);
3819
3.17k
  }
3820
3821
3.39k
  return result;
3822
3.43k
}
3823
3824
3825
9.60k
static zend_always_inline zval* zend_fetch_static_property_address(zend_property_info **prop_info, uint32_t cache_slot, int fetch_type, int flags OPLINE_DC EXECUTE_DATA_DC) {
3826
9.60k
  zval *result;
3827
9.60k
  zend_property_info *property_info;
3828
3829
9.60k
  if (opline->op1_type == IS_CONST
3830
9.36k
   && (opline->op2_type == IS_CONST
3831
4.94k
    || (opline->op2_type == IS_UNUSED
3832
4.83k
     && ((opline->op2.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF
3833
275
      || (opline->op2.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT)))
3834
9.00k
   && EXPECTED(CACHED_PTR(cache_slot + sizeof(void *)) != NULL)) {
3835
5.40k
    result = CACHED_PTR(cache_slot + sizeof(void *));
3836
5.40k
    property_info = CACHED_PTR(cache_slot + sizeof(void *) * 2);
3837
3838
5.40k
    if ((fetch_type == BP_VAR_R || fetch_type == BP_VAR_RW)
3839
3.23k
        && UNEXPECTED(Z_TYPE_P(result) == IS_UNDEF)
3840
7
        && ZEND_TYPE_IS_SET(property_info->type)) {
3841
7
      zend_throw_error(NULL, "Typed static property %s::$%s must not be accessed before initialization",
3842
7
        ZSTR_VAL(property_info->ce->name),
3843
7
        zend_get_unmangled_property_name(property_info->name));
3844
7
      return NULL;
3845
7
    }
3846
5.40k
  } else {
3847
4.20k
    result = zend_fetch_static_property_address_ex(&property_info, cache_slot, fetch_type OPLINE_CC EXECUTE_DATA_CC);
3848
4.20k
    if (UNEXPECTED(!result)) {
3849
765
      return NULL;
3850
765
    }
3851
4.20k
  }
3852
3853
8.83k
  flags &= ZEND_FETCH_OBJ_FLAGS;
3854
8.83k
  if (flags && ZEND_TYPE_IS_SET(property_info->type)) {
3855
167
    zend_handle_fetch_obj_flags(NULL, result, NULL, property_info, flags);
3856
167
  }
3857
3858
8.83k
  if (prop_info) {
3859
8.68k
    *prop_info = property_info;
3860
8.68k
  }
3861
3862
8.83k
  return result;
3863
9.60k
}
3864
3865
0
ZEND_API zval* ZEND_FASTCALL zend_fetch_static_property(zend_execute_data *ex, int fetch_type) {
3866
0
  zval *result;
3867
0
  zend_property_info *property_info;
3868
#if defined(ZEND_VM_FP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID))
3869
  zend_execute_data *orig_execute_data = execute_data;
3870
#else
3871
0
  zend_execute_data *execute_data;
3872
0
#endif
3873
0
  execute_data = ex;
3874
#if defined(ZEND_VM_IP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID))
3875
  const zend_op *orig_opline = opline;
3876
#else
3877
0
  const zend_op *opline;
3878
0
#endif
3879
0
  opline = execute_data->opline;
3880
3881
0
  uint32_t cache_slot = opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS;
3882
0
  uint32_t flags = 0;
3883
3884
0
  if (fetch_type == BP_VAR_W) {
3885
0
    flags = opline->extended_value & ZEND_FETCH_OBJ_FLAGS;
3886
0
  }
3887
0
  result = zend_fetch_static_property_address_ex(&property_info, cache_slot, fetch_type OPLINE_CC EXECUTE_DATA_CC);
3888
0
  if (EXPECTED(result)) {
3889
0
    if (flags && ZEND_TYPE_IS_SET(property_info->type)) {
3890
0
      zend_handle_fetch_obj_flags(NULL, result, NULL, property_info, flags);
3891
0
    }
3892
0
  } else {
3893
0
    result = &EG(uninitialized_zval);
3894
0
  }
3895
3896
#if defined(ZEND_VM_IP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID))
3897
  EX(opline) = opline;
3898
  opline = orig_opline;
3899
#endif
3900
#if defined(ZEND_VM_FP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID))
3901
  execute_data = orig_execute_data;
3902
#endif
3903
3904
0
  return result;
3905
0
}
3906
3907
88
ZEND_API zend_never_inline ZEND_COLD void zend_throw_ref_type_error_type(const zend_property_info *prop1, const zend_property_info *prop2, const zval *zv) {
3908
88
  zend_string *type1_str = zend_type_to_string(prop1->type);
3909
88
  zend_string *type2_str = zend_type_to_string(prop2->type);
3910
88
  zend_type_error("Reference with value of type %s held by property %s::$%s of type %s is not compatible with property %s::$%s of type %s",
3911
88
    zend_zval_type_name(zv),
3912
88
    ZSTR_VAL(prop1->ce->name),
3913
88
    zend_get_unmangled_property_name(prop1->name),
3914
88
    ZSTR_VAL(type1_str),
3915
88
    ZSTR_VAL(prop2->ce->name),
3916
88
    zend_get_unmangled_property_name(prop2->name),
3917
88
    ZSTR_VAL(type2_str)
3918
88
  );
3919
88
  zend_string_release(type1_str);
3920
88
  zend_string_release(type2_str);
3921
88
}
3922
3923
516
ZEND_API zend_never_inline ZEND_COLD void zend_throw_ref_type_error_zval(const zend_property_info *prop, const zval *zv) {
3924
516
  zend_string *type_str = zend_type_to_string(prop->type);
3925
516
  zend_type_error("Cannot assign %s to reference held by property %s::$%s of type %s",
3926
516
    zend_zval_value_name(zv),
3927
516
    ZSTR_VAL(prop->ce->name),
3928
516
    zend_get_unmangled_property_name(prop->name),
3929
516
    ZSTR_VAL(type_str)
3930
516
  );
3931
516
  zend_string_release(type_str);
3932
516
}
3933
3934
54
static zend_never_inline ZEND_COLD void zend_throw_conflicting_coercion_error(const zend_property_info *prop1, const zend_property_info *prop2, const zval *zv) {
3935
54
  zend_string *type1_str = zend_type_to_string(prop1->type);
3936
54
  zend_string *type2_str = zend_type_to_string(prop2->type);
3937
54
  zend_type_error("Cannot assign %s to reference held by property %s::$%s of type %s and property %s::$%s of type %s, as this would result in an inconsistent type conversion",
3938
54
    zend_zval_value_name(zv),
3939
54
    ZSTR_VAL(prop1->ce->name),
3940
54
    zend_get_unmangled_property_name(prop1->name),
3941
54
    ZSTR_VAL(type1_str),
3942
54
    ZSTR_VAL(prop2->ce->name),
3943
54
    zend_get_unmangled_property_name(prop2->name),
3944
54
    ZSTR_VAL(type2_str)
3945
54
  );
3946
54
  zend_string_release(type1_str);
3947
54
  zend_string_release(type2_str);
3948
54
}
3949
3950
/* 1: valid, 0: invalid, -1: may be valid after type coercion */
3951
static zend_always_inline int i_zend_verify_type_assignable_zval(
3952
35.1k
    const zend_property_info *info, const zval *zv, bool strict) {
3953
35.1k
  zend_type type = info->type;
3954
35.1k
  uint32_t type_mask;
3955
35.1k
  uint8_t zv_type = Z_TYPE_P(zv);
3956
3957
35.1k
  if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(type, zv_type))) {
3958
15.6k
    return 1;
3959
15.6k
  }
3960
3961
19.4k
  if (ZEND_TYPE_IS_COMPLEX(type) && zv_type == IS_OBJECT
3962
18.6k
      && zend_check_and_resolve_property_or_class_constant_class_type(info->ce, info->type, Z_OBJCE_P(zv))) {
3963
18.5k
    return 1;
3964
18.5k
  }
3965
3966
867
  type_mask = ZEND_TYPE_FULL_MASK(type);
3967
867
  ZEND_ASSERT(!(type_mask & (MAY_BE_CALLABLE|MAY_BE_STATIC)));
3968
3969
  /* SSTH Exception: IS_LONG may be accepted as IS_DOUBLE (converted) */
3970
867
  if (strict) {
3971
27
    if ((type_mask & MAY_BE_DOUBLE) && zv_type == IS_LONG) {
3972
0
      return -1;
3973
0
    }
3974
27
    return 0;
3975
27
  }
3976
3977
  /* NULL may be accepted only by nullable hints (this is already checked) */
3978
840
  if (zv_type == IS_NULL) {
3979
154
    return 0;
3980
154
  }
3981
3982
  /* Does not contain any type to which a coercion is possible */
3983
686
  if (!(type_mask & (MAY_BE_LONG|MAY_BE_DOUBLE|MAY_BE_STRING))
3984
252
      && (type_mask & MAY_BE_BOOL) != MAY_BE_BOOL) {
3985
252
    return 0;
3986
252
  }
3987
3988
  /* Coercion may be necessary, check separately */
3989
434
  return -1;
3990
686
}
3991
3992
ZEND_API bool ZEND_FASTCALL zend_verify_ref_assignable_zval(zend_reference *ref, zval *zv, bool strict)
3993
2.13k
{
3994
2.13k
  const zend_property_info *prop;
3995
3996
  /* The value must satisfy each property type, and coerce to the same value for each property
3997
   * type. Remember the first coerced type and value we've seen for this purpose. */
3998
2.13k
  const zend_property_info *first_prop = NULL;
3999
2.13k
  zval coerced_value;
4000
2.13k
  ZVAL_UNDEF(&coerced_value);
4001
4002
2.13k
  ZEND_ASSERT(Z_TYPE_P(zv) != IS_REFERENCE);
4003
6.82k
  ZEND_REF_FOREACH_TYPE_SOURCES(ref, prop) {
4004
6.82k
    int result = i_zend_verify_type_assignable_zval(prop, zv, strict);
4005
6.82k
    if (result == 0) {
4006
516
type_error:
4007
516
      zend_throw_ref_type_error_zval(prop, zv);
4008
516
      zval_ptr_dtor(&coerced_value);
4009
516
      return 0;
4010
358
    }
4011
4012
2.19k
    if (result < 0) {
4013
344
      if (!first_prop) {
4014
318
        first_prop = prop;
4015
318
        ZVAL_COPY(&coerced_value, zv);
4016
318
        if (!zend_verify_weak_scalar_type_hint(
4017
318
            ZEND_TYPE_FULL_MASK(prop->type), &coerced_value)) {
4018
158
          goto type_error;
4019
158
        }
4020
318
      } else if (Z_ISUNDEF(coerced_value)) {
4021
        /* A previous property did not require coercion, but this one does,
4022
         * so they are incompatible. */
4023
20
        goto conflicting_coercion_error;
4024
20
      } else {
4025
6
        zval tmp;
4026
6
        ZVAL_COPY(&tmp, zv);
4027
6
        if (!zend_verify_weak_scalar_type_hint(ZEND_TYPE_FULL_MASK(prop->type), &tmp)) {
4028
0
          zval_ptr_dtor(&tmp);
4029
0
          goto type_error;
4030
0
        }
4031
6
        if (!zend_is_identical(&coerced_value, &tmp)) {
4032
0
          zval_ptr_dtor(&tmp);
4033
0
          goto conflicting_coercion_error;
4034
0
        }
4035
6
        zval_ptr_dtor(&tmp);
4036
6
      }
4037
1.84k
    } else {
4038
1.84k
      if (!first_prop) {
4039
1.55k
        first_prop = prop;
4040
1.55k
      } else if (!Z_ISUNDEF(coerced_value)) {
4041
        /* A previous property required coercion, but this one doesn't,
4042
         * so they are incompatible. */
4043
54
conflicting_coercion_error:
4044
54
        zend_throw_conflicting_coercion_error(first_prop, prop, zv);
4045
54
        zval_ptr_dtor(&coerced_value);
4046
54
        return 0;
4047
34
      }
4048
1.84k
    }
4049
2.19k
  } ZEND_REF_FOREACH_TYPE_SOURCES_END();
4050
4051
1.56k
  if (!Z_ISUNDEF(coerced_value)) {
4052
126
    zval_ptr_dtor(zv);
4053
126
    ZVAL_COPY_VALUE(zv, &coerced_value);
4054
126
  }
4055
4056
1.56k
  return 1;
4057
2.13k
}
4058
4059
1.16k
static zend_always_inline void i_zval_ptr_dtor_noref(zval *zval_ptr) {
4060
1.16k
  if (Z_REFCOUNTED_P(zval_ptr)) {
4061
465
    zend_refcounted *ref = Z_COUNTED_P(zval_ptr);
4062
465
    ZEND_ASSERT(Z_TYPE_P(zval_ptr) != IS_REFERENCE);
4063
465
    GC_DTOR_NO_REF(ref);
4064
465
  }
4065
1.16k
}
4066
4067
ZEND_API zval* zend_assign_to_typed_ref_ex(zval *variable_ptr, zval *orig_value, uint8_t value_type, bool strict, zend_refcounted **garbage_ptr)
4068
1.76k
{
4069
1.76k
  bool ret;
4070
1.76k
  zval value;
4071
1.76k
  zend_refcounted *ref = NULL;
4072
4073
1.76k
  if (Z_ISREF_P(orig_value)) {
4074
0
    ref = Z_COUNTED_P(orig_value);
4075
0
    orig_value = Z_REFVAL_P(orig_value);
4076
0
  }
4077
4078
1.76k
  ZVAL_COPY(&value, orig_value);
4079
1.76k
  ret = zend_verify_ref_assignable_zval(Z_REF_P(variable_ptr), &value, strict);
4080
1.76k
  variable_ptr = Z_REFVAL_P(variable_ptr);
4081
1.76k
  if (EXPECTED(ret)) {
4082
1.24k
    if (Z_REFCOUNTED_P(variable_ptr)) {
4083
400
      *garbage_ptr = Z_COUNTED_P(variable_ptr);
4084
400
    }
4085
1.24k
    ZVAL_COPY_VALUE(variable_ptr, &value);
4086
1.24k
  } else {
4087
519
    zval_ptr_dtor_nogc(&value);
4088
519
  }
4089
1.76k
  if (value_type & (IS_VAR|IS_TMP_VAR)) {
4090
1.16k
    if (UNEXPECTED(ref)) {
4091
0
      if (UNEXPECTED(GC_DELREF(ref) == 0)) {
4092
0
        zval_ptr_dtor(orig_value);
4093
0
        efree_size(ref, sizeof(zend_reference));
4094
0
      }
4095
1.16k
    } else {
4096
1.16k
      i_zval_ptr_dtor_noref(orig_value);
4097
1.16k
    }
4098
1.16k
  }
4099
1.76k
  return variable_ptr;
4100
1.76k
}
4101
4102
ZEND_API zval* zend_assign_to_typed_ref(zval *variable_ptr, zval *orig_value, uint8_t value_type, bool strict)
4103
416
{
4104
416
  zend_refcounted *garbage = NULL;
4105
416
  zval *result = zend_assign_to_typed_ref_ex(variable_ptr, orig_value, value_type, strict, &garbage);
4106
416
  if (garbage) {
4107
17
    GC_DTOR_NO_REF(garbage);
4108
17
  }
4109
416
  return result;
4110
416
}
4111
4112
199k
ZEND_API bool ZEND_FASTCALL zend_verify_prop_assignable_by_ref_ex(const zend_property_info *prop_info, zval *orig_val, bool strict, zend_verify_prop_assignable_by_ref_context context) {
4113
199k
  zval *val = orig_val;
4114
199k
  if (Z_ISREF_P(val) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(val))) {
4115
32.5k
    int result;
4116
4117
32.5k
    val = Z_REFVAL_P(val);
4118
32.5k
    result = i_zend_verify_type_assignable_zval(prop_info, val, strict);
4119
32.5k
    if (result > 0) {
4120
32.3k
      return 1;
4121
32.3k
    }
4122
4123
165
    if (result < 0) {
4124
      /* This is definitely an error, but we still need to determined why: Either because
4125
       * the value is simply illegal for the type, or because or a conflicting coercion. */
4126
90
      zval tmp;
4127
90
      ZVAL_COPY(&tmp, val);
4128
90
      if (zend_verify_weak_scalar_type_hint(ZEND_TYPE_FULL_MASK(prop_info->type), &tmp)) {
4129
88
        const zend_property_info *ref_prop = ZEND_REF_FIRST_SOURCE(Z_REF_P(orig_val));
4130
88
        zend_throw_ref_type_error_type(ref_prop, prop_info, val);
4131
88
        zval_ptr_dtor(&tmp);
4132
88
        return 0;
4133
88
      }
4134
2
      zval_ptr_dtor(&tmp);
4135
2
    }
4136
166k
  } else {
4137
166k
    ZVAL_DEREF(val);
4138
166k
    if (i_zend_check_property_type(prop_info, val, strict)) {
4139
166k
      return 1;
4140
166k
    }
4141
166k
  }
4142
4143
211
  if (EXPECTED(context == ZEND_VERIFY_PROP_ASSIGNABLE_BY_REF_CONTEXT_ASSIGNMENT)) {
4144
189
    zend_verify_property_type_error(prop_info, val);
4145
189
  } else {
4146
22
    ZEND_ASSERT(context == ZEND_VERIFY_PROP_ASSIGNABLE_BY_REF_CONTEXT_MAGIC_GET);
4147
22
    zend_magic_get_property_type_inconsistency_error(prop_info, val);
4148
22
  }
4149
4150
211
  return 0;
4151
211
}
4152
4153
199k
ZEND_API bool ZEND_FASTCALL zend_verify_prop_assignable_by_ref(const zend_property_info *prop_info, zval *orig_val, bool strict) {
4154
199k
  return zend_verify_prop_assignable_by_ref_ex(prop_info, orig_val, strict, ZEND_VERIFY_PROP_ASSIGNABLE_BY_REF_CONTEXT_ASSIGNMENT);
4155
199k
}
4156
4157
ZEND_API void ZEND_FASTCALL zend_ref_add_type_source(zend_property_info_source_list *source_list, zend_property_info *prop)
4158
35.0k
{
4159
35.0k
  zend_property_info_list *list;
4160
35.0k
  if (source_list->ptr == NULL) {
4161
2.74k
    source_list->ptr = prop;
4162
2.74k
    return;
4163
2.74k
  }
4164
4165
32.2k
  list = ZEND_PROPERTY_INFO_SOURCE_TO_LIST(source_list->list);
4166
32.2k
  if (!ZEND_PROPERTY_INFO_SOURCE_IS_LIST(source_list->list)) {
4167
562
    list = emalloc(sizeof(zend_property_info_list) + (4 - 1) * sizeof(zend_property_info *));
4168
562
    list->ptr[0] = source_list->ptr;
4169
562
    list->num_allocated = 4;
4170
562
    list->num = 1;
4171
31.7k
  } else if (list->num_allocated == list->num) {
4172
732
    list->num_allocated = list->num * 2;
4173
732
    list = erealloc(list, sizeof(zend_property_info_list) + (list->num_allocated - 1) * sizeof(zend_property_info *));
4174
732
  }
4175
4176
32.2k
  list->ptr[list->num++] = prop;
4177
32.2k
  source_list->list = ZEND_PROPERTY_INFO_SOURCE_FROM_LIST(list);
4178
32.2k
}
4179
4180
ZEND_API void ZEND_FASTCALL zend_ref_del_type_source(zend_property_info_source_list *source_list, const zend_property_info *prop)
4181
35.0k
{
4182
35.0k
  zend_property_info_list *list = ZEND_PROPERTY_INFO_SOURCE_TO_LIST(source_list->list);
4183
35.0k
  zend_property_info **ptr, **end;
4184
4185
35.0k
  ZEND_ASSERT(prop);
4186
35.0k
  if (!ZEND_PROPERTY_INFO_SOURCE_IS_LIST(source_list->list)) {
4187
2.18k
    ZEND_ASSERT(source_list->ptr == prop);
4188
2.18k
    source_list->ptr = NULL;
4189
2.18k
    return;
4190
2.18k
  }
4191
4192
32.8k
  if (list->num == 1) {
4193
560
    ZEND_ASSERT(*list->ptr == prop);
4194
560
    efree(list);
4195
560
    source_list->ptr = NULL;
4196
560
    return;
4197
560
  }
4198
4199
  /* Checking against end here to get a more graceful failure mode if we missed adding a type
4200
   * source at some point. */
4201
32.2k
  ptr = list->ptr;
4202
32.2k
  end = ptr + list->num;
4203
32.7k
  while (ptr < end && *ptr != prop) {
4204
463
    ptr++;
4205
463
  }
4206
32.2k
  ZEND_ASSERT(*ptr == prop);
4207
4208
  /* Copy the last list element into the deleted slot. */
4209
32.2k
  *ptr = list->ptr[--list->num];
4210
4211
32.2k
  if (list->num >= 4 && list->num * 4 == list->num_allocated) {
4212
537
    list->num_allocated = list->num * 2;
4213
537
    source_list->list = ZEND_PROPERTY_INFO_SOURCE_FROM_LIST(erealloc(list, sizeof(zend_property_info_list) + (list->num_allocated - 1) * sizeof(zend_property_info *)));
4214
537
  }
4215
32.2k
}
4216
4217
static zend_never_inline void zend_fetch_this_var(int type OPLINE_DC EXECUTE_DATA_DC)
4218
25
{
4219
25
  zval *result = EX_VAR(opline->result.var);
4220
4221
25
  switch (type) {
4222
21
    case BP_VAR_R:
4223
21
      if (EXPECTED(Z_TYPE(EX(This)) == IS_OBJECT)) {
4224
17
        ZVAL_OBJ(result, Z_OBJ(EX(This)));
4225
17
        Z_ADDREF_P(result);
4226
17
      } else {
4227
4
        ZVAL_NULL(result);
4228
4
        zend_error_unchecked(E_WARNING, "Undefined variable $this");
4229
4
      }
4230
21
      break;
4231
0
    case BP_VAR_IS:
4232
0
      if (EXPECTED(Z_TYPE(EX(This)) == IS_OBJECT)) {
4233
0
        ZVAL_OBJ(result, Z_OBJ(EX(This)));
4234
0
        Z_ADDREF_P(result);
4235
0
      } else {
4236
0
        ZVAL_NULL(result);
4237
0
      }
4238
0
      break;
4239
0
    case BP_VAR_RW:
4240
4
    case BP_VAR_W:
4241
4
      ZVAL_UNDEF(result);
4242
4
      zend_throw_error(NULL, "Cannot re-assign $this");
4243
4
      break;
4244
0
    case BP_VAR_UNSET:
4245
0
      ZVAL_UNDEF(result);
4246
0
      zend_throw_error(NULL, "Cannot unset $this");
4247
0
      break;
4248
0
    default: ZEND_UNREACHABLE();
4249
25
  }
4250
25
}
4251
4252
#if ZEND_INTENSIVE_DEBUGGING
4253
4254
#define CHECK_SYMBOL_TABLES()                         \
4255
  zend_hash_apply(&EG(symbol_table), zend_check_symbol);      \
4256
  if (&EG(symbol_table)!=EX(symbol_table)) {              \
4257
    zend_hash_apply(EX(symbol_table), zend_check_symbol); \
4258
  }
4259
4260
static void zend_check_symbol(zval *pz)
4261
{
4262
  if (Z_TYPE_P(pz) == IS_INDIRECT) {
4263
    pz = Z_INDIRECT_P(pz);
4264
  }
4265
  if (Z_TYPE_P(pz) > 10) {
4266
    fprintf(stderr, "Warning!  %x has invalid type!\n", *pz);
4267
/* See http://support.microsoft.com/kb/190351 */
4268
#ifdef ZEND_WIN32
4269
    fflush(stderr);
4270
#endif
4271
  } else if (Z_TYPE_P(pz) == IS_ARRAY) {
4272
    zend_hash_apply(Z_ARRVAL_P(pz), zend_check_symbol);
4273
  } else if (Z_TYPE_P(pz) == IS_OBJECT) {
4274
    /* OBJ-TBI - doesn't support new object model! */
4275
    zend_hash_apply(Z_OBJPROP_P(pz), zend_check_symbol);
4276
  }
4277
}
4278
4279
4280
#else
4281
#define CHECK_SYMBOL_TABLES()
4282
#endif
4283
4284
ZEND_API void execute_internal(zend_execute_data *execute_data, zval *return_value)
4285
1.03M
{
4286
1.03M
  execute_data->func->internal_function.handler(execute_data, return_value);
4287
1.03M
}
4288
4289
ZEND_API void zend_clean_and_cache_symbol_table(zend_array *symbol_table) /* {{{ */
4290
4.51k
{
4291
  /* Clean before putting into the cache, since clean could call dtors,
4292
   * which could use the cached hash. Also do this before the check for
4293
   * available cache slots, as those may be used by a dtor as well. */
4294
4.51k
  zend_symtable_clean(symbol_table);
4295
4.51k
  if (EG(symtable_cache_ptr) >= EG(symtable_cache_limit)) {
4296
208
    zend_array_destroy(symbol_table);
4297
4.31k
  } else {
4298
4.31k
    *(EG(symtable_cache_ptr)++) = symbol_table;
4299
4.31k
  }
4300
4.51k
}
4301
/* }}} */
4302
4303
static zend_always_inline void i_free_compiled_variables(zend_execute_data *execute_data) /* {{{ */
4304
162k
{
4305
162k
  zval *cv = EX_VAR_NUM(0);
4306
162k
  int count = EX(func)->op_array.last_var;
4307
432k
  while (EXPECTED(count != 0)) {
4308
270k
    i_zval_ptr_dtor(cv);
4309
270k
    cv++;
4310
270k
    count--;
4311
270k
  }
4312
162k
}
4313
/* }}} */
4314
4315
ZEND_API void ZEND_FASTCALL zend_free_compiled_variables(zend_execute_data *execute_data) /* {{{ */
4316
6.36k
{
4317
6.36k
  i_free_compiled_variables(execute_data);
4318
6.36k
}
4319
/* }}} */
4320
4321
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_fcall_interrupt(zend_execute_data *call)
4322
0
{
4323
0
  zend_atomic_bool_store_ex(&EG(vm_interrupt), false);
4324
0
  if (zend_atomic_bool_load_ex(&EG(timed_out))) {
4325
0
    zend_timeout();
4326
0
  } else if (zend_interrupt_function) {
4327
0
    zend_interrupt_function(call);
4328
0
  }
4329
0
}
4330
4331
1.22M
#define ZEND_VM_INTERRUPT_CHECK() do { \
4332
1.22M
    if (UNEXPECTED(zend_atomic_bool_load_ex(&EG(vm_interrupt)))) { \
4333
0
      ZEND_VM_INTERRUPT(); \
4334
0
    } \
4335
1.22M
  } while (0)
4336
4337
#if ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL
4338
0
# define ZEND_VM_KIND_TAILCALL_SAVE_OPLINE() SAVE_OPLINE()
4339
#else
4340
# define ZEND_VM_KIND_TAILCALL_SAVE_OPLINE()
4341
#endif
4342
4343
73.3k
#define ZEND_VM_LOOP_INTERRUPT_CHECK() do { \
4344
73.3k
    if (UNEXPECTED(zend_atomic_bool_load_ex(&EG(vm_interrupt)))) { \
4345
0
      ZEND_VM_KIND_TAILCALL_SAVE_OPLINE(); \
4346
0
      ZEND_VM_LOOP_INTERRUPT(); \
4347
0
    } \
4348
73.3k
  } while (0)
4349
4350
944k
#define ZEND_VM_FCALL_INTERRUPT_CHECK(call) do { \
4351
944k
    if (UNEXPECTED(zend_atomic_bool_load_ex(&EG(vm_interrupt)))) { \
4352
0
      zend_fcall_interrupt(call); \
4353
0
    } \
4354
944k
  } while (0)
4355
4356
/*
4357
 * Stack Frame Layout (the whole stack frame is allocated at once)
4358
 * ==================
4359
 *
4360
 *                             +========================================+
4361
 * EG(current_execute_data) -> | zend_execute_data                      |
4362
 *                             +----------------------------------------+
4363
 *     EX_VAR_NUM(0) --------> | VAR[0] = ARG[1]                        |
4364
 *                             | ...                                    |
4365
 *                             | VAR[op_array->num_args-1] = ARG[N]     |
4366
 *                             | ...                                    |
4367
 *                             | VAR[op_array->last_var-1]              |
4368
 *                             | VAR[op_array->last_var] = TMP[0]       |
4369
 *                             | ...                                    |
4370
 *                             | VAR[op_array->last_var+op_array->T-1]  |
4371
 *                             | ARG[N+1] (extra_args)                  |
4372
 *                             | ...                                    |
4373
 *                             +----------------------------------------+
4374
 */
4375
4376
/* zend_copy_extra_args is used when the actually passed number of arguments
4377
 * (EX_NUM_ARGS) is greater than what the function defined (op_array->num_args).
4378
 *
4379
 * The extra arguments will be copied into the call frame after all the compiled variables.
4380
 *
4381
 * If there are extra arguments copied, a flag "ZEND_CALL_FREE_EXTRA_ARGS" will be set
4382
 * on the zend_execute_data, and when the executor leaves the function, the
4383
 * args will be freed in zend_leave_helper.
4384
 */
4385
static zend_never_inline void zend_copy_extra_args(EXECUTE_DATA_D)
4386
9.56k
{
4387
9.56k
  const zend_op_array *op_array = &EX(func)->op_array;
4388
9.56k
  uint32_t first_extra_arg = op_array->num_args;
4389
9.56k
  uint32_t num_args = EX_NUM_ARGS();
4390
9.56k
  zval *src;
4391
9.56k
  size_t delta;
4392
9.56k
  uint32_t count;
4393
9.56k
  uint32_t type_flags = 0;
4394
4395
9.56k
  if (EXPECTED((op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) == 0)) {
4396
    /* Skip useless ZEND_RECV and ZEND_RECV_INIT opcodes */
4397
#if defined(ZEND_VM_IP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID))
4398
    opline += first_extra_arg;
4399
#else
4400
9.39k
    EX(opline) += first_extra_arg;
4401
9.39k
#endif
4402
4403
9.39k
  }
4404
4405
  /* move extra args into separate array after all CV and TMP vars */
4406
9.56k
  src = EX_VAR_NUM(num_args - 1);
4407
9.56k
  delta = op_array->last_var + op_array->T - first_extra_arg;
4408
9.56k
  count = num_args - first_extra_arg;
4409
9.56k
  if (EXPECTED(delta != 0)) {
4410
7.16k
    delta *= sizeof(zval);
4411
353k
    do {
4412
353k
      type_flags |= Z_TYPE_INFO_P(src);
4413
353k
      ZVAL_COPY_VALUE((zval*)(((char*)src) + delta), src);
4414
353k
      ZVAL_UNDEF(src);
4415
353k
      src--;
4416
353k
    } while (--count);
4417
7.16k
    if (Z_TYPE_INFO_REFCOUNTED(type_flags)) {
4418
5.53k
      ZEND_ADD_CALL_FLAG(execute_data, ZEND_CALL_FREE_EXTRA_ARGS);
4419
5.53k
    }
4420
7.16k
  } else {
4421
1.02M
    do {
4422
1.02M
      if (Z_REFCOUNTED_P(src)) {
4423
949
        ZEND_ADD_CALL_FLAG(execute_data, ZEND_CALL_FREE_EXTRA_ARGS);
4424
949
        break;
4425
949
      }
4426
1.02M
      src--;
4427
1.02M
    } while (--count);
4428
2.40k
  }
4429
9.56k
}
4430
4431
static zend_always_inline void zend_init_cvs(uint32_t first, uint32_t last EXECUTE_DATA_DC)
4432
194k
{
4433
194k
  if (EXPECTED(first < last)) {
4434
96.9k
    uint32_t count = last - first;
4435
96.9k
    zval *var = EX_VAR_NUM(first);
4436
4437
431k
    do {
4438
431k
      ZVAL_UNDEF(var);
4439
431k
      var++;
4440
431k
    } while (--count);
4441
96.9k
  }
4442
194k
}
4443
4444
static zend_always_inline void i_init_func_execute_data(zend_op_array *op_array, zval *return_value, bool may_be_trampoline EXECUTE_DATA_DC) /* {{{ */
4445
194k
{
4446
194k
  uint32_t first_extra_arg, num_args;
4447
194k
  ZEND_ASSERT(EX(func) == (zend_function*)op_array);
4448
4449
#if defined(ZEND_VM_IP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID))
4450
  opline = op_array->opcodes;
4451
#else
4452
194k
  EX(opline) = op_array->opcodes;
4453
194k
#endif
4454
194k
  EX(call) = NULL;
4455
194k
  EX(return_value) = return_value;
4456
4457
  /* Handle arguments */
4458
194k
  first_extra_arg = op_array->num_args;
4459
194k
  num_args = EX_NUM_ARGS();
4460
194k
  if (UNEXPECTED(num_args > first_extra_arg)) {
4461
10.7k
    if (!may_be_trampoline || EXPECTED(!(op_array->fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE))) {
4462
9.56k
      zend_copy_extra_args(EXECUTE_DATA_C);
4463
9.56k
    }
4464
184k
  } else if (EXPECTED((op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) == 0)) {
4465
    /* Skip useless ZEND_RECV and ZEND_RECV_INIT opcodes */
4466
#if defined(ZEND_VM_IP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID))
4467
    opline += num_args;
4468
#else
4469
166k
    EX(opline) += num_args;
4470
166k
#endif
4471
166k
  }
4472
4473
  /* Initialize CV variables (skip arguments) */
4474
194k
  zend_init_cvs(num_args, op_array->last_var EXECUTE_DATA_CC);
4475
4476
194k
  EX(run_time_cache) = RUN_TIME_CACHE(op_array);
4477
4478
194k
  EG(current_execute_data) = execute_data;
4479
194k
}
4480
/* }}} */
4481
4482
static zend_always_inline void init_func_run_time_cache_i(zend_op_array *op_array) /* {{{ */
4483
40.5k
{
4484
40.5k
  void **run_time_cache;
4485
4486
40.5k
  ZEND_ASSERT(RUN_TIME_CACHE(op_array) == NULL);
4487
40.5k
  run_time_cache = zend_arena_alloc(&CG(arena), op_array->cache_size);
4488
40.5k
  memset(run_time_cache, 0, op_array->cache_size);
4489
40.5k
  ZEND_MAP_PTR_SET(op_array->run_time_cache, run_time_cache);
4490
40.5k
}
4491
/* }}} */
4492
4493
static zend_never_inline void ZEND_FASTCALL init_func_run_time_cache(zend_op_array *op_array) /* {{{ */
4494
40.0k
{
4495
40.0k
  init_func_run_time_cache_i(op_array);
4496
40.0k
}
4497
/* }}} */
4498
4499
ZEND_API zend_function * ZEND_FASTCALL zend_fetch_function(zend_string *name) /* {{{ */
4500
6.26k
{
4501
6.26k
  zval *zv = zend_hash_find(EG(function_table), name);
4502
4503
6.26k
  if (EXPECTED(zv != NULL)) {
4504
4.09k
    zend_function *fbc = Z_FUNC_P(zv);
4505
4506
4.09k
    if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
4507
518
      init_func_run_time_cache_i(&fbc->op_array);
4508
518
    }
4509
4.09k
    return fbc;
4510
4.09k
  }
4511
2.16k
  return NULL;
4512
6.26k
} /* }}} */
4513
4514
ZEND_API zend_function * ZEND_FASTCALL zend_fetch_function_str(const char *name, size_t len) /* {{{ */
4515
20
{
4516
20
  const zval *zv = zend_hash_str_find(EG(function_table), name, len);
4517
4518
20
  if (EXPECTED(zv != NULL)) {
4519
17
    zend_function *fbc = Z_FUNC_P(zv);
4520
4521
17
    if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
4522
0
      init_func_run_time_cache_i(&fbc->op_array);
4523
0
    }
4524
17
    return fbc;
4525
17
  }
4526
3
  return NULL;
4527
20
} /* }}} */
4528
4529
ZEND_API void ZEND_FASTCALL zend_init_func_run_time_cache(zend_op_array *op_array) /* {{{ */
4530
0
{
4531
0
  if (!RUN_TIME_CACHE(op_array)) {
4532
0
    init_func_run_time_cache_i(op_array);
4533
0
  }
4534
0
} /* }}} */
4535
4536
static zend_always_inline void i_init_code_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value) /* {{{ */
4537
205k
{
4538
205k
  ZEND_ASSERT(EX(func) == (zend_function*)op_array);
4539
4540
205k
  EX(opline) = op_array->opcodes;
4541
205k
  EX(call) = NULL;
4542
205k
  EX(return_value) = return_value;
4543
4544
205k
  if (op_array->last_var) {
4545
131k
    zend_attach_symbol_table(execute_data);
4546
131k
  }
4547
4548
205k
  if (!ZEND_MAP_PTR(op_array->run_time_cache)) {
4549
204k
    void *ptr;
4550
4551
204k
    ZEND_ASSERT(op_array->fn_flags & ZEND_ACC_HEAP_RT_CACHE);
4552
204k
    ptr = emalloc(op_array->cache_size);
4553
204k
    ZEND_MAP_PTR_INIT(op_array->run_time_cache, ptr);
4554
204k
    memset(ptr, 0, op_array->cache_size);
4555
204k
  }
4556
205k
  EX(run_time_cache) = RUN_TIME_CACHE(op_array);
4557
4558
205k
  EG(current_execute_data) = execute_data;
4559
205k
}
4560
/* }}} */
4561
4562
ZEND_API void zend_init_func_execute_data(zend_execute_data *ex, zend_op_array *op_array, zval *return_value) /* {{{ */
4563
94.0k
{
4564
#if defined(ZEND_VM_FP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID))
4565
  zend_execute_data *orig_execute_data = execute_data;
4566
#endif
4567
#if defined(ZEND_VM_IP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID))
4568
  const zend_op *orig_opline = opline;
4569
#endif
4570
#if defined(ZEND_VM_FP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID))
4571
  execute_data = ex;
4572
#else
4573
94.0k
  zend_execute_data *execute_data = ex;
4574
94.0k
#endif
4575
4576
94.0k
  EX(prev_execute_data) = EG(current_execute_data);
4577
94.0k
  if (!RUN_TIME_CACHE(op_array)) {
4578
8.82k
    init_func_run_time_cache(op_array);
4579
8.82k
  }
4580
94.0k
  i_init_func_execute_data(op_array, return_value, 1 EXECUTE_DATA_CC);
4581
4582
#if defined(ZEND_VM_IP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID))
4583
  EX(opline) = opline;
4584
  opline = orig_opline;
4585
#endif
4586
#if defined(ZEND_VM_FP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID))
4587
  execute_data = orig_execute_data;
4588
#endif
4589
94.0k
}
4590
/* }}} */
4591
4592
ZEND_API void zend_init_code_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value) /* {{{ */
4593
0
{
4594
0
  EX(prev_execute_data) = EG(current_execute_data);
4595
0
  i_init_code_execute_data(execute_data, op_array, return_value);
4596
0
}
4597
/* }}} */
4598
4599
ZEND_API void zend_init_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value) /* {{{ */
4600
0
{
4601
0
  if (EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE) {
4602
0
    zend_init_code_execute_data(execute_data, op_array, return_value);
4603
0
  } else {
4604
0
    zend_init_func_execute_data(execute_data, op_array, return_value);
4605
0
  }
4606
0
}
4607
/* }}} */
4608
4609
zend_execute_data *zend_vm_stack_copy_call_frame(zend_execute_data *call, uint32_t passed_args, uint32_t additional_args) /* {{{ */
4610
59
{
4611
59
  zend_execute_data *new_call;
4612
59
  int used_stack = (EG(vm_stack_top) - (zval*)call) + additional_args;
4613
4614
  /* copy call frame into new stack segment */
4615
59
  new_call = zend_vm_stack_extend(used_stack * sizeof(zval));
4616
59
  *new_call = *call;
4617
59
  ZEND_ADD_CALL_FLAG(new_call, ZEND_CALL_ALLOCATED);
4618
4619
59
  if (passed_args) {
4620
10
    zval *src = ZEND_CALL_ARG(call, 1);
4621
10
    zval *dst = ZEND_CALL_ARG(new_call, 1);
4622
100k
    do {
4623
100k
      ZVAL_COPY_VALUE(dst, src);
4624
100k
      passed_args--;
4625
100k
      src++;
4626
100k
      dst++;
4627
100k
    } while (passed_args);
4628
10
  }
4629
4630
  /* delete old call_frame from previous stack segment */
4631
59
  EG(vm_stack)->prev->top = (zval*)call;
4632
4633
  /* delete previous stack segment if it became empty */
4634
59
  if (UNEXPECTED(EG(vm_stack)->prev->top == ZEND_VM_STACK_ELEMENTS(EG(vm_stack)->prev))) {
4635
0
    zend_vm_stack r = EG(vm_stack)->prev;
4636
4637
0
    EG(vm_stack)->prev = r->prev;
4638
0
    efree(r);
4639
0
  }
4640
4641
59
  return new_call;
4642
59
}
4643
/* }}} */
4644
4645
static zend_always_inline zend_generator *zend_get_running_generator(EXECUTE_DATA_D) /* {{{ */
4646
12.5k
{
4647
  /* The generator object is stored in EX(return_value) */
4648
12.5k
  zend_generator *generator = (zend_generator *) EX(return_value);
4649
  /* However control may currently be delegated to another generator.
4650
   * That's the one we're interested in. */
4651
12.5k
  return generator;
4652
12.5k
}
4653
/* }}} */
4654
4655
ZEND_API void zend_unfinished_calls_gc(zend_execute_data *execute_data, zend_execute_data *call, uint32_t op_num, zend_get_gc_buffer *buf) /* {{{ */
4656
376
{
4657
376
  zend_op *opline = EX(func)->op_array.opcodes + op_num;
4658
376
  int level;
4659
376
  int do_exit;
4660
376
  uint32_t num_args;
4661
4662
376
  if (UNEXPECTED(opline->opcode == ZEND_INIT_FCALL ||
4663
376
    opline->opcode == ZEND_INIT_FCALL_BY_NAME ||
4664
376
    opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME ||
4665
376
    opline->opcode == ZEND_INIT_DYNAMIC_CALL ||
4666
376
    opline->opcode == ZEND_INIT_USER_CALL ||
4667
376
    opline->opcode == ZEND_INIT_METHOD_CALL ||
4668
376
    opline->opcode == ZEND_INIT_STATIC_METHOD_CALL ||
4669
376
    opline->opcode == ZEND_NEW)) {
4670
0
    ZEND_ASSERT(op_num);
4671
0
    opline--;
4672
0
  }
4673
4674
416
  do {
4675
    /* find the number of actually passed arguments */
4676
416
    level = 0;
4677
416
    do_exit = 0;
4678
416
    num_args = ZEND_CALL_NUM_ARGS(call);
4679
1.36k
    do {
4680
1.36k
      switch (opline->opcode) {
4681
160
        case ZEND_DO_FCALL:
4682
160
        case ZEND_DO_ICALL:
4683
210
        case ZEND_DO_UCALL:
4684
210
        case ZEND_DO_FCALL_BY_NAME:
4685
210
        case ZEND_CALLABLE_CONVERT:
4686
210
        case ZEND_CALLABLE_CONVERT_PARTIAL:
4687
210
          level++;
4688
210
          break;
4689
408
        case ZEND_INIT_FCALL:
4690
408
        case ZEND_INIT_FCALL_BY_NAME:
4691
408
        case ZEND_INIT_NS_FCALL_BY_NAME:
4692
428
        case ZEND_INIT_DYNAMIC_CALL:
4693
428
        case ZEND_INIT_USER_CALL:
4694
476
        case ZEND_INIT_METHOD_CALL:
4695
486
        case ZEND_INIT_STATIC_METHOD_CALL:
4696
522
        case ZEND_NEW:
4697
522
          if (level == 0) {
4698
312
            num_args = 0;
4699
312
            do_exit = 1;
4700
312
          }
4701
522
          level--;
4702
522
          break;
4703
120
        case ZEND_SEND_VAL:
4704
128
        case ZEND_SEND_VAL_EX:
4705
132
        case ZEND_SEND_VAR:
4706
208
        case ZEND_SEND_VAR_EX:
4707
208
        case ZEND_SEND_FUNC_ARG:
4708
208
        case ZEND_SEND_REF:
4709
208
        case ZEND_SEND_VAR_NO_REF:
4710
208
        case ZEND_SEND_VAR_NO_REF_EX:
4711
208
        case ZEND_SEND_USER:
4712
208
          if (level == 0) {
4713
            /* For named args, the number of arguments is up to date. */
4714
104
            if (opline->op2_type != IS_CONST) {
4715
60
              num_args = opline->op2.num;
4716
60
            }
4717
104
            do_exit = 1;
4718
104
          }
4719
208
          break;
4720
0
        case ZEND_SEND_ARRAY:
4721
0
        case ZEND_SEND_UNPACK:
4722
0
        case ZEND_CHECK_UNDEF_ARGS:
4723
0
          if (level == 0) {
4724
0
            do_exit = 1;
4725
0
          }
4726
0
          break;
4727
1.36k
      }
4728
1.36k
      if (!do_exit) {
4729
950
        opline--;
4730
950
      }
4731
1.36k
    } while (!do_exit);
4732
416
    if (call->prev_execute_data) {
4733
      /* skip current call region */
4734
40
      level = 0;
4735
40
      do_exit = 0;
4736
66
      do {
4737
66
        switch (opline->opcode) {
4738
0
          case ZEND_DO_FCALL:
4739
0
          case ZEND_DO_ICALL:
4740
0
          case ZEND_DO_UCALL:
4741
0
          case ZEND_DO_FCALL_BY_NAME:
4742
0
          case ZEND_CALLABLE_CONVERT:
4743
0
          case ZEND_CALLABLE_CONVERT_PARTIAL:
4744
0
            level++;
4745
0
            break;
4746
28
          case ZEND_INIT_FCALL:
4747
28
          case ZEND_INIT_FCALL_BY_NAME:
4748
28
          case ZEND_INIT_NS_FCALL_BY_NAME:
4749
28
          case ZEND_INIT_DYNAMIC_CALL:
4750
28
          case ZEND_INIT_USER_CALL:
4751
40
          case ZEND_INIT_METHOD_CALL:
4752
40
          case ZEND_INIT_STATIC_METHOD_CALL:
4753
40
          case ZEND_NEW:
4754
40
            if (level == 0) {
4755
40
              do_exit = 1;
4756
40
            }
4757
40
            level--;
4758
40
            break;
4759
66
        }
4760
66
        opline--;
4761
66
      } while (!do_exit);
4762
40
    }
4763
4764
416
    if (EXPECTED(num_args > 0)) {
4765
60
      zval *p = ZEND_CALL_ARG(call, 1);
4766
62
      do {
4767
62
        zend_get_gc_buffer_add_zval(buf, p);
4768
62
        p++;
4769
62
      } while (--num_args);
4770
60
    }
4771
416
    if (ZEND_CALL_INFO(call) & ZEND_CALL_RELEASE_THIS) {
4772
64
      zend_get_gc_buffer_add_obj(buf, Z_OBJ(call->This));
4773
64
    }
4774
416
    if (ZEND_CALL_INFO(call) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS) {
4775
44
      zval *val;
4776
132
      ZEND_HASH_FOREACH_VAL(call->extra_named_params, val) {
4777
132
        zend_get_gc_buffer_add_zval(buf, val);
4778
132
      } ZEND_HASH_FOREACH_END();
4779
44
    }
4780
416
    if (call->func->common.fn_flags & ZEND_ACC_CLOSURE) {
4781
20
      zend_get_gc_buffer_add_obj(buf, ZEND_CLOSURE_OBJECT(call->func));
4782
20
    }
4783
4784
416
    call = call->prev_execute_data;
4785
416
  } while (call);
4786
376
}
4787
/* }}} */
4788
4789
static void cleanup_unfinished_calls(zend_execute_data *execute_data, uint32_t op_num) /* {{{ */
4790
414k
{
4791
414k
  if (UNEXPECTED(EX(call))) {
4792
9.52k
    zend_execute_data *call = EX(call);
4793
9.52k
    zend_op *opline = EX(func)->op_array.opcodes + op_num;
4794
9.52k
    int level;
4795
9.52k
    int do_exit;
4796
4797
9.52k
    if (UNEXPECTED(opline->opcode == ZEND_INIT_FCALL ||
4798
9.52k
      opline->opcode == ZEND_INIT_FCALL_BY_NAME ||
4799
9.52k
      opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME ||
4800
9.52k
      opline->opcode == ZEND_INIT_DYNAMIC_CALL ||
4801
9.52k
      opline->opcode == ZEND_INIT_USER_CALL ||
4802
9.52k
      opline->opcode == ZEND_INIT_METHOD_CALL ||
4803
9.52k
      opline->opcode == ZEND_INIT_STATIC_METHOD_CALL ||
4804
9.52k
      opline->opcode == ZEND_INIT_PARENT_PROPERTY_HOOK_CALL ||
4805
9.52k
      opline->opcode == ZEND_NEW)) {
4806
1.00k
      ZEND_ASSERT(op_num);
4807
1.00k
      opline--;
4808
1.00k
    }
4809
4810
10.2k
    do {
4811
      /* If the exception was thrown during a function call there might be
4812
       * arguments pushed to the stack that have to be dtor'ed. */
4813
4814
      /* find the number of actually passed arguments */
4815
10.2k
      level = 0;
4816
10.2k
      do_exit = 0;
4817
26.8k
      do {
4818
26.8k
        switch (opline->opcode) {
4819
2.00k
          case ZEND_DO_FCALL:
4820
2.00k
          case ZEND_DO_ICALL:
4821
2.34k
          case ZEND_DO_UCALL:
4822
2.34k
          case ZEND_DO_FCALL_BY_NAME:
4823
2.34k
          case ZEND_CALLABLE_CONVERT:
4824
2.35k
          case ZEND_CALLABLE_CONVERT_PARTIAL:
4825
2.35k
            level++;
4826
2.35k
            break;
4827
9.98k
          case ZEND_INIT_FCALL:
4828
10.0k
          case ZEND_INIT_FCALL_BY_NAME:
4829
10.1k
          case ZEND_INIT_NS_FCALL_BY_NAME:
4830
10.4k
          case ZEND_INIT_DYNAMIC_CALL:
4831
10.4k
          case ZEND_INIT_USER_CALL:
4832
10.9k
          case ZEND_INIT_METHOD_CALL:
4833
11.1k
          case ZEND_INIT_STATIC_METHOD_CALL:
4834
11.1k
          case ZEND_INIT_PARENT_PROPERTY_HOOK_CALL:
4835
11.5k
          case ZEND_NEW:
4836
11.5k
            if (level == 0) {
4837
9.17k
              ZEND_CALL_NUM_ARGS(call) = 0;
4838
9.17k
              do_exit = 1;
4839
9.17k
            }
4840
11.5k
            level--;
4841
11.5k
            break;
4842
1.49k
          case ZEND_SEND_VAL:
4843
1.96k
          case ZEND_SEND_VAL_EX:
4844
2.49k
          case ZEND_SEND_VAR:
4845
2.56k
          case ZEND_SEND_VAR_EX:
4846
2.58k
          case ZEND_SEND_FUNC_ARG:
4847
2.61k
          case ZEND_SEND_REF:
4848
2.61k
          case ZEND_SEND_VAR_NO_REF:
4849
2.62k
          case ZEND_SEND_VAR_NO_REF_EX:
4850
2.64k
          case ZEND_SEND_USER:
4851
2.64k
            if (level == 0) {
4852
              /* For named args, the number of arguments is up to date. */
4853
784
              if (opline->op2_type != IS_CONST) {
4854
621
                ZEND_CALL_NUM_ARGS(call) = opline->op2.num;
4855
621
              }
4856
784
              do_exit = 1;
4857
784
            }
4858
2.64k
            break;
4859
93
          case ZEND_SEND_ARRAY:
4860
217
          case ZEND_SEND_UNPACK:
4861
301
          case ZEND_CHECK_UNDEF_ARGS:
4862
301
            if (level == 0) {
4863
264
              do_exit = 1;
4864
264
            }
4865
301
            break;
4866
26.8k
        }
4867
26.8k
        if (!do_exit) {
4868
16.6k
          opline--;
4869
16.6k
        }
4870
26.8k
      } while (!do_exit);
4871
10.2k
      if (call->prev_execute_data) {
4872
        /* skip current call region */
4873
689
        level = 0;
4874
689
        do_exit = 0;
4875
1.50k
        do {
4876
1.50k
          switch (opline->opcode) {
4877
2
            case ZEND_DO_FCALL:
4878
2
            case ZEND_DO_ICALL:
4879
2
            case ZEND_DO_UCALL:
4880
2
            case ZEND_DO_FCALL_BY_NAME:
4881
2
            case ZEND_CALLABLE_CONVERT:
4882
2
            case ZEND_CALLABLE_CONVERT_PARTIAL:
4883
2
              level++;
4884
2
              break;
4885
634
            case ZEND_INIT_FCALL:
4886
634
            case ZEND_INIT_FCALL_BY_NAME:
4887
648
            case ZEND_INIT_NS_FCALL_BY_NAME:
4888
653
            case ZEND_INIT_DYNAMIC_CALL:
4889
653
            case ZEND_INIT_USER_CALL:
4890
674
            case ZEND_INIT_METHOD_CALL:
4891
680
            case ZEND_INIT_STATIC_METHOD_CALL:
4892
680
            case ZEND_INIT_PARENT_PROPERTY_HOOK_CALL:
4893
691
            case ZEND_NEW:
4894
691
              if (level == 0) {
4895
689
                do_exit = 1;
4896
689
              }
4897
691
              level--;
4898
691
              break;
4899
1.50k
          }
4900
1.50k
          opline--;
4901
1.50k
        } while (!do_exit);
4902
689
      }
4903
4904
10.2k
      zend_vm_stack_free_args(EX(call));
4905
4906
10.2k
      if (ZEND_CALL_INFO(call) & ZEND_CALL_RELEASE_THIS) {
4907
277
        OBJ_RELEASE(Z_OBJ(call->This));
4908
277
      }
4909
10.2k
      if (ZEND_CALL_INFO(call) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS) {
4910
20
        zend_free_extra_named_params(call->extra_named_params);
4911
20
      }
4912
10.2k
      if (call->func->common.fn_flags & ZEND_ACC_CLOSURE) {
4913
66
        zend_object_release(ZEND_CLOSURE_OBJECT(call->func));
4914
10.1k
      } else if (call->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) {
4915
61
        zend_string_release_ex(call->func->common.function_name, 0);
4916
61
        zend_free_trampoline(call->func);
4917
61
      }
4918
4919
10.2k
      EX(call) = call->prev_execute_data;
4920
10.2k
      zend_vm_stack_free_call_frame(call);
4921
10.2k
      call = EX(call);
4922
10.2k
    } while (call);
4923
9.52k
  }
4924
414k
}
4925
/* }}} */
4926
4927
static void cleanup_live_vars(zend_execute_data *execute_data, uint32_t op_num, uint32_t catch_op_num) /* {{{ */
4928
414k
{
4929
1.56M
  for (uint32_t i = 0; i < EX(func)->op_array.last_live_range; i++) {
4930
1.31M
    const zend_live_range *range = &EX(func)->op_array.live_range[i];
4931
1.31M
    if (range->start > op_num) {
4932
      /* further blocks will not be relevant... */
4933
165k
      break;
4934
1.14M
    } else if (op_num < range->end) {
4935
545k
      if (!catch_op_num || catch_op_num >= range->end) {
4936
323k
        uint32_t kind = range->var & ZEND_LIVE_MASK;
4937
323k
        uint32_t var_num = range->var & ~ZEND_LIVE_MASK;
4938
323k
        zval *var = EX_VAR(var_num);
4939
4940
        /* Handle the split range for loop vars */
4941
323k
        if (catch_op_num) {
4942
315k
          const zend_op *final_op = EX(func)->op_array.opcodes + range->end;
4943
315k
          if (final_op->extended_value & ZEND_FREE_ON_RETURN && (final_op->opcode == ZEND_FE_FREE || final_op->opcode == ZEND_FREE)) {
4944
65
            if (catch_op_num < range->end + final_op->op2.num) {
4945
49
              continue;
4946
49
            }
4947
65
          }
4948
315k
        }
4949
4950
323k
        if (kind == ZEND_LIVE_TMPVAR) {
4951
2.48k
          zval_ptr_dtor_nogc(var);
4952
320k
        } else if (kind == ZEND_LIVE_NEW) {
4953
315k
          zend_object *obj;
4954
315k
          ZEND_ASSERT(Z_TYPE_P(var) == IS_OBJECT);
4955
315k
          obj = Z_OBJ_P(var);
4956
315k
          zend_object_store_ctor_failed(obj);
4957
315k
          OBJ_RELEASE(obj);
4958
315k
        } else if (kind == ZEND_LIVE_LOOP) {
4959
1.21k
          if (Z_TYPE_P(var) != IS_ARRAY && Z_FE_ITER_P(var) != (uint32_t)-1) {
4960
156
            zend_hash_iterator_del(Z_FE_ITER_P(var));
4961
156
          }
4962
1.21k
          zval_ptr_dtor_nogc(var);
4963
4.25k
        } else if (kind == ZEND_LIVE_ROPE) {
4964
158
          zend_string **rope = (zend_string **)var;
4965
158
          const zend_op *last = EX(func)->op_array.opcodes + op_num;
4966
283
          while ((last->opcode != ZEND_ROPE_ADD && last->opcode != ZEND_ROPE_INIT)
4967
168
              || last->result.var != var_num) {
4968
125
            ZEND_ASSERT(last >= EX(func)->op_array.opcodes);
4969
125
            last--;
4970
125
          }
4971
158
          if (last->opcode == ZEND_ROPE_INIT) {
4972
34
            zend_string_release_ex(*rope, 0);
4973
124
          } else {
4974
124
            uint32_t j = last->extended_value;
4975
1.77k
            do {
4976
1.77k
              zend_string_release_ex(rope[j], 0);
4977
1.77k
            } while (j--);
4978
124
          }
4979
4.09k
        } else if (kind == ZEND_LIVE_SILENCE) {
4980
          /* restore previous error_reporting value */
4981
4.09k
          if (E_HAS_ONLY_FATAL_ERRORS(EG(error_reporting))
4982
4.04k
              && !E_HAS_ONLY_FATAL_ERRORS(Z_LVAL_P(var))) {
4983
35
            EG(error_reporting) = Z_LVAL_P(var);
4984
35
          }
4985
4.09k
        }
4986
323k
      }
4987
545k
    }
4988
1.31M
  }
4989
414k
}
4990
/* }}} */
4991
4992
1.71k
ZEND_API void zend_cleanup_unfinished_execution(zend_execute_data *execute_data, uint32_t op_num, uint32_t catch_op_num) {
4993
1.71k
  cleanup_unfinished_calls(execute_data, op_num);
4994
1.71k
  cleanup_live_vars(execute_data, op_num, catch_op_num);
4995
1.71k
}
4996
4997
ZEND_API ZEND_ATTRIBUTE_DEPRECATED HashTable *zend_unfinished_execution_gc(zend_execute_data *execute_data, zend_execute_data *call, zend_get_gc_buffer *gc_buffer)
4998
0
{
4999
0
  return zend_unfinished_execution_gc_ex(execute_data, call, gc_buffer, false);
5000
0
}
5001
5002
ZEND_API HashTable *zend_unfinished_execution_gc_ex(zend_execute_data *execute_data, zend_execute_data *call, zend_get_gc_buffer *gc_buffer, bool suspended_by_yield)
5003
8.74k
{
5004
8.74k
  if (!EX(func)) {
5005
140
    return NULL;
5006
140
  }
5007
5008
8.60k
  if (EX_CALL_INFO() & ZEND_CALL_RELEASE_THIS) {
5009
386
    zend_get_gc_buffer_add_obj(gc_buffer, Z_OBJ(execute_data->This));
5010
386
  }
5011
5012
8.60k
  if (EX_CALL_INFO() & ZEND_CALL_CLOSURE) {
5013
1.78k
    zend_get_gc_buffer_add_obj(gc_buffer, ZEND_CLOSURE_OBJECT(EX(func)));
5014
1.78k
  }
5015
5016
8.60k
  if (!ZEND_USER_CODE(EX(func)->common.type)) {
5017
3.54k
    ZEND_ASSERT(!(EX_CALL_INFO() & (ZEND_CALL_HAS_SYMBOL_TABLE|ZEND_CALL_FREE_EXTRA_ARGS|ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)));
5018
3.54k
    return NULL;
5019
3.54k
  }
5020
5021
5.05k
  const zend_op_array *op_array = &EX(func)->op_array;
5022
5023
5.05k
  if (!(EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE)) {
5024
4.71k
    uint32_t i, num_cvs = EX(func)->op_array.last_var;
5025
10.2k
    for (i = 0; i < num_cvs; i++) {
5026
5.57k
      zend_get_gc_buffer_add_zval(gc_buffer, EX_VAR_NUM(i));
5027
5.57k
    }
5028
4.71k
  }
5029
5030
5.05k
  if (EX_CALL_INFO() & ZEND_CALL_FREE_EXTRA_ARGS) {
5031
60
    zval *zv = EX_VAR_NUM(op_array->last_var + op_array->T);
5032
60
    const zval *end = zv + (EX_NUM_ARGS() - op_array->num_args);
5033
122
    while (zv != end) {
5034
62
      zend_get_gc_buffer_add_zval(gc_buffer, zv++);
5035
62
    }
5036
60
  }
5037
5038
5.05k
  if (EX_CALL_INFO() & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS) {
5039
0
    zval extra_named_params;
5040
0
    ZVAL_ARR(&extra_named_params, EX(extra_named_params));
5041
0
    zend_get_gc_buffer_add_zval(gc_buffer, &extra_named_params);
5042
0
  }
5043
5044
5.05k
  uint32_t op_num;
5045
5.05k
  if (UNEXPECTED(execute_data->opline->opcode == ZEND_HANDLE_EXCEPTION)) {
5046
0
    op_num = EG(opline_before_exception) - op_array->opcodes;
5047
5.05k
  } else {
5048
5.05k
    op_num = execute_data->opline - op_array->opcodes;
5049
5.05k
  }
5050
5.05k
  ZEND_ASSERT(op_num < op_array->last);
5051
5052
5.05k
  if (call) {
5053
376
    zend_unfinished_calls_gc(execute_data, call, op_num, gc_buffer);
5054
376
  }
5055
5056
5.05k
  if (execute_data->opline != op_array->opcodes) {
5057
4.88k
    uint32_t i;
5058
6.35k
    for (i = 0; i < op_array->last_live_range; i++) {
5059
2.06k
      const zend_live_range *range = &op_array->live_range[i];
5060
2.06k
      if (range->start > op_num) {
5061
587
        break;
5062
1.47k
      } else if (op_num < range->end) {
5063
144
        uint32_t kind = range->var & ZEND_LIVE_MASK;
5064
144
        uint32_t var_num = range->var & ~ZEND_LIVE_MASK;
5065
144
        zval *var = EX_VAR(var_num);
5066
144
        if (kind == ZEND_LIVE_TMPVAR || kind == ZEND_LIVE_LOOP) {
5067
118
          zend_get_gc_buffer_add_zval(gc_buffer, var);
5068
118
        }
5069
144
      }
5070
2.06k
    }
5071
4.88k
  }
5072
5073
5.05k
  if (EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE) {
5074
344
    return execute_data->symbol_table;
5075
4.71k
  } else {
5076
4.71k
    return NULL;
5077
4.71k
  }
5078
5.05k
}
5079
5080
#if ZEND_VM_SPEC
5081
static void zend_swap_operands(zend_op *op) /* {{{ */
5082
37.9k
{
5083
37.9k
  znode_op     tmp;
5084
37.9k
  uint8_t   tmp_type;
5085
5086
37.9k
  tmp          = op->op1;
5087
37.9k
  tmp_type     = op->op1_type;
5088
37.9k
  op->op1      = op->op2;
5089
37.9k
  op->op1_type = op->op2_type;
5090
37.9k
  op->op2      = tmp;
5091
37.9k
  op->op2_type = tmp_type;
5092
5093
#ifdef ZEND_VERIFY_TYPE_INFERENCE
5094
  uint32_t tmp_info;
5095
  tmp_info = op->op1_use_type;
5096
  op->op1_use_type = op->op2_use_type;
5097
  op->op2_use_type = tmp_info;
5098
  tmp_info = op->op1_def_type;
5099
  op->op1_def_type = op->op2_def_type;
5100
  op->op2_def_type = tmp_info;
5101
#endif
5102
37.9k
}
5103
/* }}} */
5104
#endif
5105
5106
static zend_never_inline zend_execute_data *zend_init_dynamic_call_string(zend_string *function, uint32_t num_args) /* {{{ */
5107
1.69k
{
5108
1.69k
  zend_function *fbc;
5109
1.69k
  zval *func;
5110
1.69k
  zend_class_entry *called_scope;
5111
1.69k
  zend_string *lcname;
5112
1.69k
  const char *colon;
5113
5114
1.69k
  if ((colon = zend_memrchr(ZSTR_VAL(function), ':', ZSTR_LEN(function))) != NULL &&
5115
167
    colon > ZSTR_VAL(function) &&
5116
154
    *(colon-1) == ':'
5117
1.69k
  ) {
5118
133
    zend_string *mname;
5119
133
    size_t cname_length = colon - ZSTR_VAL(function) - 1;
5120
133
    size_t mname_length = ZSTR_LEN(function) - cname_length - (sizeof("::") - 1);
5121
5122
133
    lcname = zend_string_init(ZSTR_VAL(function), cname_length, 0);
5123
5124
133
    called_scope = zend_fetch_class_by_name(lcname, NULL, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
5125
133
    if (UNEXPECTED(called_scope == NULL)) {
5126
21
      zend_string_release_ex(lcname, 0);
5127
21
      return NULL;
5128
21
    }
5129
5130
112
    mname = zend_string_init(ZSTR_VAL(function) + (cname_length + sizeof("::") - 1), mname_length, 0);
5131
5132
112
    if (called_scope->get_static_method) {
5133
0
      fbc = called_scope->get_static_method(called_scope, mname);
5134
112
    } else {
5135
112
      fbc = zend_std_get_static_method(called_scope, mname, NULL);
5136
112
    }
5137
112
    if (UNEXPECTED(fbc == NULL)) {
5138
9
      if (EXPECTED(!EG(exception))) {
5139
9
        zend_undefined_method(called_scope, mname);
5140
9
      }
5141
9
      zend_string_release_ex(lcname, 0);
5142
9
      zend_string_release_ex(mname, 0);
5143
9
      return NULL;
5144
9
    }
5145
5146
103
    zend_string_release_ex(lcname, 0);
5147
103
    zend_string_release_ex(mname, 0);
5148
5149
103
    if (UNEXPECTED(!(fbc->common.fn_flags & ZEND_ACC_STATIC))) {
5150
18
      zend_non_static_method_call(fbc);
5151
18
      if (fbc->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) {
5152
13
        zend_string_release_ex(fbc->common.function_name, 0);
5153
13
        zend_free_trampoline(fbc);
5154
13
      }
5155
18
      return NULL;
5156
18
    }
5157
85
    if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
5158
36
      init_func_run_time_cache(&fbc->op_array);
5159
36
    }
5160
1.55k
  } else {
5161
1.55k
    if (ZSTR_VAL(function)[0] == '\\') {
5162
5
      lcname = zend_string_alloc(ZSTR_LEN(function) - 1, 0);
5163
5
      zend_str_tolower_copy(ZSTR_VAL(lcname), ZSTR_VAL(function) + 1, ZSTR_LEN(function) - 1);
5164
1.55k
    } else {
5165
1.55k
      lcname = zend_string_tolower(function);
5166
1.55k
    }
5167
1.55k
    if (UNEXPECTED((func = zend_hash_find(EG(function_table), lcname)) == NULL)) {
5168
77
      zend_throw_error(NULL, "Call to undefined function %s()", ZSTR_VAL(function));
5169
77
      zend_string_release_ex(lcname, 0);
5170
77
      return NULL;
5171
77
    }
5172
1.48k
    zend_string_release_ex(lcname, 0);
5173
5174
1.48k
    fbc = Z_FUNC_P(func);
5175
1.48k
    if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
5176
389
      init_func_run_time_cache(&fbc->op_array);
5177
389
    }
5178
1.48k
    called_scope = NULL;
5179
1.48k
  }
5180
5181
1.56k
  return zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_DYNAMIC,
5182
1.56k
    fbc, num_args, called_scope);
5183
1.69k
}
5184
/* }}} */
5185
5186
static zend_never_inline zend_execute_data *zend_init_dynamic_call_object(zend_object *function, uint32_t num_args) /* {{{ */
5187
7.30k
{
5188
7.30k
  zend_function *fbc;
5189
7.30k
  void *object_or_called_scope;
5190
7.30k
  zend_class_entry *called_scope;
5191
7.30k
  zend_object *object;
5192
7.30k
  uint32_t call_info;
5193
5194
7.30k
  if (EXPECTED(function->handlers->get_closure) &&
5195
7.30k
      EXPECTED(function->handlers->get_closure(function, &called_scope, &fbc, &object, 0) == SUCCESS)) {
5196
5197
7.29k
    object_or_called_scope = called_scope;
5198
7.29k
    if (EXPECTED(fbc->common.fn_flags & ZEND_ACC_CLOSURE)) {
5199
      /* Delay closure destruction until its invocation */
5200
7.14k
      GC_ADDREF(ZEND_CLOSURE_OBJECT(fbc));
5201
7.14k
      ZEND_ASSERT(ZEND_ACC_FAKE_CLOSURE == ZEND_CALL_FAKE_CLOSURE);
5202
7.14k
      call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_DYNAMIC | ZEND_CALL_CLOSURE |
5203
7.14k
        (fbc->common.fn_flags & ZEND_ACC_FAKE_CLOSURE);
5204
7.14k
      if (object) {
5205
1.47k
        call_info |= ZEND_CALL_HAS_THIS;
5206
1.47k
        object_or_called_scope = object;
5207
1.47k
      }
5208
7.14k
    } else {
5209
150
      call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_DYNAMIC;
5210
150
      if (object) {
5211
150
        call_info |= ZEND_CALL_RELEASE_THIS | ZEND_CALL_HAS_THIS;
5212
150
        GC_ADDREF(object); /* For $this pointer */
5213
150
        object_or_called_scope = object;
5214
150
      }
5215
150
    }
5216
7.29k
  } else {
5217
11
    zend_throw_error(NULL, "Object of type %s is not callable", ZSTR_VAL(function->ce->name));
5218
11
    return NULL;
5219
11
  }
5220
5221
7.29k
  if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
5222
103
    init_func_run_time_cache(&fbc->op_array);
5223
103
  }
5224
5225
7.29k
  return zend_vm_stack_push_call_frame(call_info,
5226
7.29k
    fbc, num_args, object_or_called_scope);
5227
7.30k
}
5228
/* }}} */
5229
5230
static zend_never_inline zend_execute_data *zend_init_dynamic_call_array(const zend_array *function, uint32_t num_args) /* {{{ */
5231
410
{
5232
410
  zend_function *fbc;
5233
410
  void *object_or_called_scope;
5234
410
  uint32_t call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_DYNAMIC;
5235
5236
410
  if (zend_hash_num_elements(function) == 2) {
5237
398
    zval *obj;
5238
398
    zval *method;
5239
398
    obj = zend_hash_index_find(function, 0);
5240
398
    method = zend_hash_index_find(function, 1);
5241
5242
398
    if (UNEXPECTED(!obj) || UNEXPECTED(!method)) {
5243
4
      zend_throw_error(NULL, "Array callback has to contain indices 0 and 1");
5244
4
      return NULL;
5245
4
    }
5246
5247
394
    ZVAL_DEREF(obj);
5248
394
    if (UNEXPECTED(Z_TYPE_P(obj) != IS_STRING) && UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT)) {
5249
6
      zend_throw_error(NULL, "First array member is not a valid class name or object");
5250
6
      return NULL;
5251
6
    }
5252
5253
388
    ZVAL_DEREF(method);
5254
388
    if (UNEXPECTED(Z_TYPE_P(method) != IS_STRING)) {
5255
0
      zend_throw_error(NULL, "Second array member is not a valid method");
5256
0
      return NULL;
5257
0
    }
5258
5259
388
    if (Z_TYPE_P(obj) == IS_STRING) {
5260
165
      zend_class_entry *called_scope = zend_fetch_class_by_name(Z_STR_P(obj), NULL, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
5261
5262
165
      if (UNEXPECTED(called_scope == NULL)) {
5263
27
        return NULL;
5264
27
      }
5265
5266
138
      if (called_scope->get_static_method) {
5267
0
        fbc = called_scope->get_static_method(called_scope, Z_STR_P(method));
5268
138
      } else {
5269
138
        fbc = zend_std_get_static_method(called_scope, Z_STR_P(method), NULL);
5270
138
      }
5271
138
      if (UNEXPECTED(fbc == NULL)) {
5272
4
        if (EXPECTED(!EG(exception))) {
5273
4
          zend_undefined_method(called_scope, Z_STR_P(method));
5274
4
        }
5275
4
        return NULL;
5276
4
      }
5277
134
      if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
5278
16
        zend_non_static_method_call(fbc);
5279
16
        if (fbc->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) {
5280
11
          zend_string_release_ex(fbc->common.function_name, 0);
5281
11
          zend_free_trampoline(fbc);
5282
11
        }
5283
16
        return NULL;
5284
16
      }
5285
118
      object_or_called_scope = called_scope;
5286
223
    } else {
5287
223
      zend_object *object = Z_OBJ_P(obj);
5288
5289
223
      fbc = Z_OBJ_HT_P(obj)->get_method(&object, Z_STR_P(method), NULL);
5290
223
      if (UNEXPECTED(fbc == NULL)) {
5291
8
        if (EXPECTED(!EG(exception))) {
5292
8
          zend_undefined_method(object->ce, Z_STR_P(method));
5293
8
        }
5294
8
        return NULL;
5295
8
      }
5296
5297
215
      if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
5298
24
        object_or_called_scope = object->ce;
5299
191
      } else {
5300
191
        call_info |= ZEND_CALL_RELEASE_THIS | ZEND_CALL_HAS_THIS;
5301
191
        GC_ADDREF(object); /* For $this pointer */
5302
191
        object_or_called_scope = object;
5303
191
      }
5304
215
    }
5305
388
  } else {
5306
12
    zend_throw_error(NULL, "Array callback must have exactly two elements");
5307
12
    return NULL;
5308
12
  }
5309
5310
333
  if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
5311
102
    init_func_run_time_cache(&fbc->op_array);
5312
102
  }
5313
5314
333
  return zend_vm_stack_push_call_frame(call_info,
5315
333
    fbc, num_args, object_or_called_scope);
5316
410
}
5317
/* }}} */
5318
5319
105k
#define ZEND_FAKE_OP_ARRAY ((zend_op_array*)(intptr_t)-1)
5320
5321
static zend_never_inline zend_op_array* ZEND_FASTCALL zend_include_or_eval(const zval *inc_filename_zv, int type) /* {{{ */
5322
102k
{
5323
102k
  zend_op_array *new_op_array = NULL;
5324
102k
  zend_string *tmp_inc_filename;
5325
102k
  zend_string *inc_filename = zval_try_get_tmp_string(inc_filename_zv, &tmp_inc_filename);
5326
102k
  if (UNEXPECTED(!inc_filename)) {
5327
20
    return NULL;
5328
20
  }
5329
5330
102k
  switch (type) {
5331
22
    case ZEND_INCLUDE_ONCE:
5332
2.20k
    case ZEND_REQUIRE_ONCE: {
5333
2.20k
        zend_file_handle file_handle;
5334
2.20k
        zend_string *resolved_path;
5335
5336
2.20k
        resolved_path = zend_resolve_path(inc_filename);
5337
2.20k
        if (EXPECTED(resolved_path)) {
5338
23
          if (zend_hash_exists(&EG(included_files), resolved_path)) {
5339
4
            new_op_array = ZEND_FAKE_OP_ARRAY;
5340
4
            zend_string_release_ex(resolved_path, 0);
5341
4
            break;
5342
4
          }
5343
2.17k
        } else if (UNEXPECTED(EG(exception))) {
5344
23
          break;
5345
2.15k
        } else if (UNEXPECTED(zend_str_has_nul_byte(inc_filename))) {
5346
10
          zend_message_dispatcher(
5347
10
            (type == ZEND_INCLUDE_ONCE) ?
5348
6
              ZMSG_FAILED_INCLUDE_FOPEN : ZMSG_FAILED_REQUIRE_FOPEN,
5349
10
              ZSTR_VAL(inc_filename));
5350
10
          break;
5351
2.14k
        } else {
5352
2.14k
          resolved_path = zend_string_copy(inc_filename);
5353
2.14k
        }
5354
5355
2.16k
        zend_stream_init_filename_ex(&file_handle, resolved_path);
5356
2.16k
        if (SUCCESS == zend_stream_open(&file_handle)) {
5357
5358
11
          if (!file_handle.opened_path) {
5359
0
            file_handle.opened_path = zend_string_copy(resolved_path);
5360
0
          }
5361
5362
11
          if (zend_hash_add_empty_element(&EG(included_files), file_handle.opened_path)) {
5363
11
            new_op_array = zend_compile_file(&file_handle, (type==ZEND_INCLUDE_ONCE?ZEND_INCLUDE:ZEND_REQUIRE));
5364
11
          } else {
5365
0
            new_op_array = ZEND_FAKE_OP_ARRAY;
5366
0
          }
5367
2.15k
        } else if (!EG(exception)) {
5368
171
          zend_message_dispatcher(
5369
171
            (type == ZEND_INCLUDE_ONCE) ?
5370
160
              ZMSG_FAILED_INCLUDE_FOPEN : ZMSG_FAILED_REQUIRE_FOPEN,
5371
171
              ZSTR_VAL(inc_filename));
5372
171
        }
5373
2.16k
        zend_destroy_file_handle(&file_handle);
5374
2.16k
        zend_string_release_ex(resolved_path, 0);
5375
2.16k
      }
5376
0
      break;
5377
1.51k
    case ZEND_INCLUDE:
5378
93.2k
    case ZEND_REQUIRE:
5379
93.2k
      if (UNEXPECTED(zend_str_has_nul_byte(inc_filename))) {
5380
109
        zend_message_dispatcher(
5381
109
          (type == ZEND_INCLUDE) ?
5382
103
            ZMSG_FAILED_INCLUDE_FOPEN : ZMSG_FAILED_REQUIRE_FOPEN,
5383
109
            ZSTR_VAL(inc_filename));
5384
109
        break;
5385
109
      }
5386
93.0k
      new_op_array = compile_filename(type, inc_filename);
5387
93.0k
      break;
5388
6.89k
    case ZEND_EVAL: {
5389
6.89k
        char *eval_desc = zend_make_compiled_string_description("eval()'d code");
5390
6.89k
        new_op_array = zend_compile_string(inc_filename, eval_desc, ZEND_COMPILE_POSITION_AFTER_OPEN_TAG);
5391
6.89k
        efree(eval_desc);
5392
6.89k
      }
5393
6.89k
      break;
5394
0
    default: ZEND_UNREACHABLE();
5395
102k
  }
5396
5397
97.5k
  zend_tmp_string_release(tmp_inc_filename);
5398
97.5k
  return new_op_array;
5399
102k
}
5400
/* }}} */
5401
5402
static zend_never_inline bool ZEND_FASTCALL zend_fe_reset_iterator(zval *array_ptr, int by_ref OPLINE_DC EXECUTE_DATA_DC) /* {{{ */
5403
2.03k
{
5404
2.03k
  zend_class_entry *ce = Z_OBJCE_P(array_ptr);
5405
2.03k
  zend_object_iterator *iter = ce->get_iterator(ce, array_ptr, by_ref);
5406
2.03k
  bool is_empty;
5407
5408
2.03k
  if (UNEXPECTED(!iter) || UNEXPECTED(EG(exception))) {
5409
35
    if (iter) {
5410
0
      OBJ_RELEASE(&iter->std);
5411
0
    }
5412
35
    if (!EG(exception)) {
5413
0
      zend_throw_exception_ex(NULL, 0, "Object of type %s did not create an Iterator", ZSTR_VAL(ce->name));
5414
0
    }
5415
35
    ZVAL_UNDEF(EX_VAR(opline->result.var));
5416
35
    return 1;
5417
35
  }
5418
5419
1.99k
  iter->index = 0;
5420
1.99k
  if (iter->funcs->rewind) {
5421
1.99k
    iter->funcs->rewind(iter);
5422
1.99k
    if (UNEXPECTED(EG(exception) != NULL)) {
5423
163
      OBJ_RELEASE(&iter->std);
5424
163
      ZVAL_UNDEF(EX_VAR(opline->result.var));
5425
163
      return 1;
5426
163
    }
5427
1.99k
  }
5428
5429
1.83k
  is_empty = iter->funcs->valid(iter) != SUCCESS;
5430
5431
1.83k
  if (UNEXPECTED(EG(exception) != NULL)) {
5432
81
    OBJ_RELEASE(&iter->std);
5433
81
    ZVAL_UNDEF(EX_VAR(opline->result.var));
5434
81
    return 1;
5435
81
  }
5436
1.75k
  iter->index = -1; /* will be set to 0 before using next handler */
5437
5438
1.75k
  ZVAL_OBJ(EX_VAR(opline->result.var), &iter->std);
5439
1.75k
  Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1;
5440
5441
1.75k
  return is_empty;
5442
1.83k
}
5443
/* }}} */
5444
5445
static zend_always_inline zend_result _zend_quick_get_constant(
5446
    const zval *key, uint32_t flags, bool check_defined_only OPLINE_DC EXECUTE_DATA_DC) /* {{{ */
5447
22.1k
{
5448
22.1k
  zval *zv;
5449
22.1k
  zend_constant *c = NULL;
5450
5451
  /* null/true/false are resolved during compilation, so don't check for them here. */
5452
22.1k
  zv = zend_hash_find_known_hash(EG(zend_constants), Z_STR_P(key));
5453
22.1k
  if (zv) {
5454
1.83k
    c = (zend_constant*)Z_PTR_P(zv);
5455
20.3k
  } else if (flags & IS_CONSTANT_UNQUALIFIED_IN_NAMESPACE) {
5456
190
    key++;
5457
190
    zv = zend_hash_find_known_hash(EG(zend_constants), Z_STR_P(key));
5458
190
    if (zv) {
5459
88
      c = (zend_constant*)Z_PTR_P(zv);
5460
88
    }
5461
190
  }
5462
5463
22.1k
  if (!c) {
5464
20.2k
    if (!check_defined_only) {
5465
20.1k
      zend_throw_error(NULL, "Undefined constant \"%s\"", Z_STRVAL_P(RT_CONSTANT(opline, opline->op2)));
5466
20.1k
      ZVAL_UNDEF(EX_VAR(opline->result.var));
5467
20.1k
    }
5468
20.2k
    return FAILURE;
5469
20.2k
  }
5470
5471
1.91k
  if (!check_defined_only) {
5472
1.89k
    ZVAL_COPY_OR_DUP(EX_VAR(opline->result.var), &c->value);
5473
1.89k
    if (ZEND_CONSTANT_FLAGS(c) & CONST_DEPRECATED) {
5474
148
      if (!CONST_IS_RECURSIVE(c)) {
5475
148
        CONST_PROTECT_RECURSION(c);
5476
148
        zend_deprecated_constant(c, c->name);
5477
148
        CONST_UNPROTECT_RECURSION(c);
5478
148
      }
5479
148
      return SUCCESS;
5480
148
    }
5481
1.89k
  }
5482
5483
1.77k
  CACHE_PTR(opline->extended_value, c);
5484
1.77k
  return SUCCESS;
5485
1.91k
}
5486
/* }}} */
5487
5488
static zend_never_inline void ZEND_FASTCALL zend_quick_get_constant(
5489
    const zval *key, uint32_t flags OPLINE_DC EXECUTE_DATA_DC) /* {{{ */
5490
22.0k
{
5491
22.0k
  _zend_quick_get_constant(key, flags, 0 OPLINE_CC EXECUTE_DATA_CC);
5492
22.0k
} /* }}} */
5493
5494
static zend_never_inline zend_result ZEND_FASTCALL zend_quick_check_constant(
5495
    const zval *key OPLINE_DC EXECUTE_DATA_DC) /* {{{ */
5496
106
{
5497
106
  return _zend_quick_get_constant(key, 0, 1 OPLINE_CC EXECUTE_DATA_CC);
5498
106
} /* }}} */
5499
5500
static zend_always_inline uint32_t zend_get_arg_offset_by_name(
5501
9.41k
    const zend_function *fbc, const zend_string *arg_name, void **cache_slot) {
5502
  /* Due to closures, the `fbc` address isn't unique if the memory address is reused.
5503
   * The argument info will be however and uniquely positions the arguments.
5504
   * We do support NULL arg_info, so we have to distinguish that from an uninitialized cache slot. */
5505
9.41k
  void *unique_id = (void *) ((uintptr_t) fbc->common.arg_info | 1);
5506
5507
9.41k
  if (EXPECTED(*cache_slot == unique_id)) {
5508
827
    return *(uintptr_t *)(cache_slot + 1);
5509
827
  }
5510
5511
  // TODO: Use a hash table?
5512
8.59k
  uint32_t num_args = fbc->common.num_args;
5513
21.3k
  for (uint32_t i = 0; i < num_args; i++) {
5514
16.4k
    const zend_arg_info *arg_info = &fbc->common.arg_info[i];
5515
16.4k
    if (zend_string_equals(arg_name, arg_info->name)) {
5516
3.70k
      if ((fbc->type == ZEND_USER_FUNCTION
5517
3.02k
        && (!fbc->op_array.refcount || !(fbc->op_array.fn_flags & ZEND_ACC_CLOSURE)))
5518
679
       || (fbc->type == ZEND_INTERNAL_FUNCTION
5519
3.67k
        && !(fbc->common.fn_flags & ZEND_ACC_NEVER_CACHE))) {
5520
3.67k
        *cache_slot = unique_id;
5521
3.67k
        *(uintptr_t *)(cache_slot + 1) = i;
5522
3.67k
      }
5523
3.70k
      return i;
5524
3.70k
    }
5525
16.4k
  }
5526
5527
4.89k
  if (fbc->common.fn_flags & ZEND_ACC_VARIADIC) {
5528
4.77k
    if ((fbc->type == ZEND_USER_FUNCTION
5529
4.31k
      && (!fbc->op_array.refcount || !(fbc->op_array.fn_flags & ZEND_ACC_CLOSURE)))
5530
455
     || (fbc->type == ZEND_INTERNAL_FUNCTION
5531
4.75k
      && !(fbc->common.fn_flags & ZEND_ACC_NEVER_CACHE))) {
5532
4.75k
      *cache_slot = unique_id;
5533
4.75k
      *(uintptr_t *)(cache_slot + 1) = fbc->common.num_args;
5534
4.75k
    }
5535
4.77k
    return fbc->common.num_args;
5536
4.77k
  }
5537
5538
120
  return (uint32_t) -1;
5539
4.89k
}
5540
5541
zval * ZEND_FASTCALL zend_handle_named_arg(
5542
    zend_execute_data **call_ptr, zend_string *arg_name,
5543
7.10k
    uint32_t *arg_num_ptr, void **cache_slot) {
5544
7.10k
  zend_execute_data *call = *call_ptr;
5545
7.10k
  const zend_function *fbc = call->func;
5546
7.10k
  uint32_t arg_offset = zend_get_arg_offset_by_name(fbc, arg_name, cache_slot);
5547
7.10k
  if (UNEXPECTED(arg_offset == (uint32_t) -1)) {
5548
114
    zend_throw_error(NULL, "Unknown named parameter $%s", ZSTR_VAL(arg_name));
5549
114
    return NULL;
5550
114
  }
5551
5552
6.99k
  zval *arg;
5553
6.99k
  if (UNEXPECTED(arg_offset == fbc->common.num_args)) {
5554
    /* Unknown named parameter that will be collected into a variadic. */
5555
2.88k
    if (!(ZEND_CALL_INFO(call) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) {
5556
2.04k
      ZEND_ADD_CALL_FLAG(call, ZEND_CALL_HAS_EXTRA_NAMED_PARAMS);
5557
2.04k
      call->extra_named_params = zend_new_array(0);
5558
2.04k
    }
5559
5560
2.88k
    arg = zend_hash_add_empty_element(call->extra_named_params, arg_name);
5561
2.88k
    if (!arg) {
5562
3
      zend_throw_error(NULL, "Named parameter $%s overwrites previous argument",
5563
3
        ZSTR_VAL(arg_name));
5564
3
      return NULL;
5565
3
    }
5566
2.88k
    *arg_num_ptr = arg_offset + 1;
5567
2.88k
    return arg;
5568
2.88k
  }
5569
5570
4.11k
  uint32_t current_num_args = ZEND_CALL_NUM_ARGS(call);
5571
  // TODO: We may wish to optimize the arg_offset == current_num_args case,
5572
  // which is probably common (if the named parameters are in order of declaration).
5573
4.11k
  if (arg_offset >= current_num_args) {
5574
2.97k
    uint32_t new_num_args = arg_offset + 1;
5575
2.97k
    ZEND_CALL_NUM_ARGS(call) = new_num_args;
5576
5577
2.97k
    uint32_t num_extra_args = new_num_args - current_num_args;
5578
2.97k
    zend_vm_stack_extend_call_frame(call_ptr, current_num_args, num_extra_args);
5579
2.97k
    call = *call_ptr;
5580
5581
2.97k
    arg = ZEND_CALL_VAR_NUM(call, arg_offset);
5582
2.97k
    if (num_extra_args > 1) {
5583
1.45k
      zval *zv = ZEND_CALL_VAR_NUM(call, current_num_args);
5584
4.55k
      do {
5585
4.55k
        ZVAL_UNDEF(zv);
5586
4.55k
        zv++;
5587
4.55k
      } while (zv != arg);
5588
1.45k
      ZEND_ADD_CALL_FLAG(call, ZEND_CALL_MAY_HAVE_UNDEF);
5589
1.45k
    }
5590
2.97k
  } else {
5591
1.13k
    arg = ZEND_CALL_VAR_NUM(call, arg_offset);
5592
5593
1.13k
    if (UNEXPECTED(!Z_ISUNDEF_P(arg))) {
5594
71
      zend_throw_error(NULL, "Named parameter $%s overwrites previous %s",
5595
71
        ZSTR_VAL(arg_name), Z_TYPE_P(arg) == _IS_PLACEHOLDER ? "placeholder" : "argument");
5596
71
      return NULL;
5597
71
    }
5598
1.13k
  }
5599
5600
4.03k
  *arg_num_ptr = arg_offset + 1;
5601
4.03k
  return arg;
5602
4.11k
}
5603
5604
131
static zend_execute_data *start_fake_frame(zend_execute_data *call, const zend_op *opline) {
5605
131
  zend_execute_data *old_prev_execute_data = call->prev_execute_data;
5606
131
  call->prev_execute_data = EG(current_execute_data);
5607
131
  call->opline = opline;
5608
131
  EG(current_execute_data) = call;
5609
131
  return old_prev_execute_data;
5610
131
}
5611
5612
131
static void end_fake_frame(zend_execute_data *call, zend_execute_data *old_prev_execute_data) {
5613
131
  zend_execute_data *prev_execute_data = call->prev_execute_data;
5614
131
  EG(current_execute_data) = prev_execute_data;
5615
131
  call->prev_execute_data = old_prev_execute_data;
5616
131
  if (UNEXPECTED(EG(exception)) && ZEND_USER_CODE(prev_execute_data->func->common.type)) {
5617
56
    zend_rethrow_exception(prev_execute_data);
5618
56
  }
5619
131
}
5620
5621
1.26k
ZEND_API zend_result ZEND_FASTCALL zend_handle_undef_args(zend_execute_data *call) {
5622
1.26k
  zend_function *fbc = call->func;
5623
1.26k
  if (fbc->type == ZEND_USER_FUNCTION) {
5624
888
    zend_op_array *op_array = &fbc->op_array;
5625
888
    uint32_t num_args = ZEND_CALL_NUM_ARGS(call);
5626
6.19k
    for (uint32_t i = 0; i < num_args; i++) {
5627
5.36k
      zval *arg = ZEND_CALL_VAR_NUM(call, i);
5628
5.36k
      if (!Z_ISUNDEF_P(arg)) {
5629
2.67k
        continue;
5630
2.67k
      }
5631
5632
2.69k
      const zend_op *opline = &op_array->opcodes[i];
5633
2.69k
      if (EXPECTED(opline->opcode == ZEND_RECV_INIT)) {
5634
2.65k
        zval *default_value = RT_CONSTANT(opline, opline->op2);
5635
2.65k
        if (Z_OPT_TYPE_P(default_value) == IS_CONSTANT_AST) {
5636
42
          if (UNEXPECTED(!RUN_TIME_CACHE(op_array))) {
5637
11
            init_func_run_time_cache(op_array);
5638
11
          }
5639
5640
42
          void *run_time_cache = RUN_TIME_CACHE(op_array);
5641
42
          zval *cache_val =
5642
42
            (zval *) ((char *) run_time_cache + Z_CACHE_SLOT_P(default_value));
5643
5644
42
          if (Z_TYPE_P(cache_val) != IS_UNDEF) {
5645
            /* We keep in cache only not refcounted values */
5646
0
            ZVAL_COPY_VALUE(arg, cache_val);
5647
42
          } else {
5648
            /* Update constant inside a temporary zval, to make sure the CONSTANT_AST
5649
             * value is not accessible through back traces. */
5650
42
            zval tmp;
5651
42
            ZVAL_COPY(&tmp, default_value);
5652
42
            zend_execute_data *old = start_fake_frame(call, opline);
5653
42
            zend_result ret = zval_update_constant_ex(&tmp, fbc->op_array.scope);
5654
42
            end_fake_frame(call, old);
5655
42
            if (UNEXPECTED(ret == FAILURE)) {
5656
25
              zval_ptr_dtor_nogc(&tmp);
5657
25
              return FAILURE;
5658
25
            }
5659
17
            ZVAL_COPY_VALUE(arg, &tmp);
5660
17
            if (!Z_REFCOUNTED(tmp)) {
5661
17
              ZVAL_COPY_VALUE(cache_val, &tmp);
5662
17
            }
5663
17
          }
5664
2.61k
        } else {
5665
2.61k
          ZVAL_COPY(arg, default_value);
5666
2.61k
        }
5667
2.65k
      } else {
5668
35
        ZEND_ASSERT(opline->opcode == ZEND_RECV);
5669
35
        zend_execute_data *old = start_fake_frame(call, opline);
5670
35
        zend_argument_error(zend_ce_argument_count_error, i + 1, "not passed");
5671
35
        end_fake_frame(call, old);
5672
35
        return FAILURE;
5673
35
      }
5674
2.69k
    }
5675
5676
828
    return SUCCESS;
5677
888
  } else {
5678
372
    if (fbc->common.fn_flags & ZEND_ACC_USER_ARG_INFO) {
5679
      /* Magic function, let it deal with it. */
5680
15
      return SUCCESS;
5681
15
    }
5682
5683
357
    uint32_t num_args = ZEND_CALL_NUM_ARGS(call);
5684
1.16k
    for (uint32_t i = 0; i < num_args; i++) {
5685
845
      zval *arg = ZEND_CALL_VAR_NUM(call, i);
5686
845
      if (!Z_ISUNDEF_P(arg)) {
5687
628
        continue;
5688
628
      }
5689
5690
217
      zend_arg_info *arg_info = &fbc->internal_function.arg_info[i];
5691
217
      if (i < fbc->common.required_num_args) {
5692
29
        zend_execute_data *old = start_fake_frame(call, NULL);
5693
29
        zend_argument_error(zend_ce_argument_count_error, i + 1, "not passed");
5694
29
        end_fake_frame(call, old);
5695
29
        return FAILURE;
5696
29
      }
5697
5698
188
      zval default_value;
5699
188
      if (zend_get_default_from_internal_arg_info(&default_value, arg_info) == FAILURE) {
5700
9
        zend_execute_data *old = start_fake_frame(call, NULL);
5701
9
        zend_argument_error(zend_ce_argument_count_error, i + 1,
5702
9
          "must be passed explicitly, because the default value is not known");
5703
9
        end_fake_frame(call, old);
5704
9
        return FAILURE;
5705
9
      }
5706
5707
179
      if (Z_TYPE(default_value) == IS_CONSTANT_AST) {
5708
16
        zend_execute_data *old = start_fake_frame(call, NULL);
5709
16
        zend_result ret = zval_update_constant_ex(&default_value, fbc->common.scope);
5710
16
        end_fake_frame(call, old);
5711
16
        if (ret == FAILURE) {
5712
0
          return FAILURE;
5713
0
        }
5714
16
      }
5715
5716
179
      ZVAL_COPY_VALUE(arg, &default_value);
5717
179
      if (ZEND_ARG_SEND_MODE(arg_info) & ZEND_SEND_BY_REF) {
5718
0
        ZVAL_NEW_REF(arg, arg);
5719
0
      }
5720
179
    }
5721
357
  }
5722
5723
319
  return SUCCESS;
5724
1.26k
}
5725
5726
ZEND_API void ZEND_FASTCALL zend_free_extra_named_params(zend_array *extra_named_params)
5727
763
{
5728
  /* Extra named params may be shared. */
5729
763
  zend_array_release(extra_named_params);
5730
763
}
5731
5732
#if defined(ZEND_VM_IP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID))
5733
/* Special versions of functions that sets EX(opline) before calling zend_vm_stack_extend() */
5734
static zend_always_inline zend_execute_data *_zend_vm_stack_push_call_frame_ex(uint32_t used_stack, uint32_t call_info, zend_function *func, uint32_t num_args, void *object_or_called_scope) /* {{{ */
5735
{
5736
  zend_execute_data *call = (zend_execute_data*)EG(vm_stack_top);
5737
5738
  ZEND_ASSERT_VM_STACK_GLOBAL;
5739
5740
  if (UNEXPECTED(used_stack > (size_t)(((char*)EG(vm_stack_end)) - (char*)call))) {
5741
    EX(opline) = opline; /* this is the only difference */
5742
    call = (zend_execute_data*)zend_vm_stack_extend(used_stack);
5743
    ZEND_ASSERT_VM_STACK_GLOBAL;
5744
    zend_vm_init_call_frame(call, call_info | ZEND_CALL_ALLOCATED, func, num_args, object_or_called_scope);
5745
    return call;
5746
  } else {
5747
    EG(vm_stack_top) = (zval*)((char*)call + used_stack);
5748
    zend_vm_init_call_frame(call, call_info, func, num_args, object_or_called_scope);
5749
    return call;
5750
  }
5751
} /* }}} */
5752
5753
static zend_always_inline zend_execute_data *_zend_vm_stack_push_call_frame(uint32_t call_info, zend_function *func, uint32_t num_args, void *object_or_called_scope) /* {{{ */
5754
{
5755
  uint32_t used_stack = zend_vm_calc_used_stack(num_args, func);
5756
5757
  return _zend_vm_stack_push_call_frame_ex(used_stack, call_info,
5758
    func, num_args, object_or_called_scope);
5759
} /* }}} */
5760
#else
5761
498k
# define _zend_vm_stack_push_call_frame_ex zend_vm_stack_push_call_frame_ex
5762
4.08k
# define _zend_vm_stack_push_call_frame    zend_vm_stack_push_call_frame
5763
#endif
5764
5765
#ifdef ZEND_VM_TRACE_HANDLERS
5766
# include "zend_vm_trace_handlers.h"
5767
#elif defined(ZEND_VM_TRACE_LINES)
5768
# include "zend_vm_trace_lines.h"
5769
#elif defined(ZEND_VM_TRACE_MAP)
5770
# include "zend_vm_trace_map.h"
5771
#elif defined(ZEND_VERIFY_TYPE_INFERENCE)
5772
# include "zend_verify_type_inference.h"
5773
#endif
5774
5775
#define ZEND_VM_NEXT_OPCODE_EX(check_exception, skip) \
5776
11.0M
  CHECK_SYMBOL_TABLES() \
5777
11.0M
  if (check_exception) { \
5778
6.38M
    OPLINE = EX(opline) + (skip); \
5779
6.38M
  } else { \
5780
4.70M
    ZEND_ASSERT(!EG(exception)); \
5781
4.70M
    OPLINE = opline + (skip); \
5782
4.61M
  } \
5783
11.0M
  ZEND_VM_CONTINUE()
5784
5785
#define ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION() \
5786
6.17M
  ZEND_VM_NEXT_OPCODE_EX(1, 1)
5787
5788
#define ZEND_VM_NEXT_OPCODE() \
5789
5.34M
  ZEND_VM_NEXT_OPCODE_EX(0, 1)
5790
5791
#define ZEND_VM_SET_NEXT_OPCODE(new_op) \
5792
356k
  CHECK_SYMBOL_TABLES() \
5793
356k
  OPLINE = new_op
5794
5795
#define ZEND_VM_SET_OPCODE_NO_INTERRUPT(new_op) \
5796
2.18M
  CHECK_SYMBOL_TABLES() \
5797
2.18M
  OPLINE = new_op
5798
5799
#define ZEND_VM_SET_OPCODE(new_op) \
5800
1.18M
  ZEND_VM_SET_OPCODE_NO_INTERRUPT(new_op); \
5801
1.18M
  ZEND_VM_INTERRUPT_CHECK()
5802
5803
#define ZEND_VM_SET_RELATIVE_OPCODE(opline, offset) \
5804
14.9k
  ZEND_VM_SET_OPCODE(ZEND_OFFSET_TO_OPLINE(opline, offset))
5805
5806
924k
#define ZEND_VM_JMP_EX(new_op, check_exception) do { \
5807
924k
    if (check_exception && UNEXPECTED(EG(exception))) { \
5808
0
      HANDLE_EXCEPTION(); \
5809
0
    } \
5810
924k
    ZEND_VM_SET_OPCODE(new_op); \
5811
924k
    ZEND_VM_CONTINUE(); \
5812
924k
  } while (0)
5813
5814
#define ZEND_VM_JMP(new_op) \
5815
102k
  ZEND_VM_JMP_EX(new_op, 1)
5816
5817
#define ZEND_VM_INC_OPCODE() \
5818
2.98k
  OPLINE++
5819
5820
5821
#define ZEND_VM_REPEATABLE_OPCODE \
5822
9.10k
  do {
5823
#define ZEND_VM_REPEAT_OPCODE(_opcode) \
5824
9.10k
  } while (UNEXPECTED((++opline)->opcode == _opcode)); \
5825
7.48k
  OPLINE = opline; \
5826
7.70k
  ZEND_VM_CONTINUE()
5827
374k
#define ZEND_VM_SMART_BRANCH(_result, _check) do { \
5828
374k
    if ((_check) && UNEXPECTED(EG(exception))) { \
5829
196
      OPLINE = EX(opline); \
5830
374k
    } else if (EXPECTED(opline->result_type == (IS_SMART_BRANCH_JMPZ|IS_TMP_VAR))) { \
5831
219k
      if (_result) { \
5832
195k
        ZEND_VM_SET_NEXT_OPCODE(opline + 2); \
5833
195k
      } else { \
5834
24.6k
        ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline + 1, (opline+1)->op2)); \
5835
24.6k
      } \
5836
219k
    } else if (EXPECTED(opline->result_type == (IS_SMART_BRANCH_JMPNZ|IS_TMP_VAR))) { \
5837
53.9k
      if (!(_result)) { \
5838
10.5k
        ZEND_VM_SET_NEXT_OPCODE(opline + 2); \
5839
43.4k
      } else { \
5840
43.4k
        ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline + 1, (opline+1)->op2)); \
5841
43.4k
      } \
5842
100k
    } else { \
5843
100k
      ZVAL_BOOL(EX_VAR(opline->result.var), _result); \
5844
100k
      ZEND_VM_SET_NEXT_OPCODE(opline + 1); \
5845
100k
    } \
5846
374k
    ZEND_VM_CONTINUE(); \
5847
374k
  } while (0)
5848
6.22k
#define ZEND_VM_SMART_BRANCH_JMPZ(_result, _check) do { \
5849
6.22k
    if ((_check) && UNEXPECTED(EG(exception))) { \
5850
0
      OPLINE = EX(opline); \
5851
6.22k
    } else if (_result) { \
5852
2.01k
      ZEND_VM_SET_NEXT_OPCODE(opline + 2); \
5853
4.20k
    } else { \
5854
4.20k
      ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline + 1, (opline+1)->op2)); \
5855
4.20k
    } \
5856
6.22k
    ZEND_VM_CONTINUE(); \
5857
6.22k
  } while (0)
5858
32.0k
#define ZEND_VM_SMART_BRANCH_JMPNZ(_result, _check) do { \
5859
32.0k
    if ((_check) && UNEXPECTED(EG(exception))) { \
5860
0
      OPLINE = EX(opline); \
5861
32.0k
    } else if (!(_result)) { \
5862
3.11k
      ZEND_VM_SET_NEXT_OPCODE(opline + 2); \
5863
28.8k
    } else { \
5864
28.8k
      ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline + 1, (opline+1)->op2)); \
5865
28.8k
    } \
5866
32.0k
    ZEND_VM_CONTINUE(); \
5867
32.0k
  } while (0)
5868
2.92k
#define ZEND_VM_SMART_BRANCH_NONE(_result, _check) do { \
5869
2.92k
    ZVAL_BOOL(EX_VAR(opline->result.var), _result); \
5870
2.92k
    ZEND_VM_NEXT_OPCODE_EX(_check, 1); \
5871
2.92k
    ZEND_VM_CONTINUE(); \
5872
2.92k
  } while (0)
5873
171
#define ZEND_VM_SMART_BRANCH_TRUE() do { \
5874
171
    if (EXPECTED(opline->result_type == (IS_SMART_BRANCH_JMPNZ|IS_TMP_VAR))) { \
5875
2
      ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline + 1, (opline+1)->op2)); \
5876
169
    } else if (EXPECTED(opline->result_type == (IS_SMART_BRANCH_JMPZ|IS_TMP_VAR))) { \
5877
145
      ZEND_VM_SET_NEXT_OPCODE(opline + 2); \
5878
145
    } else { \
5879
24
      ZVAL_TRUE(EX_VAR(opline->result.var)); \
5880
24
      ZEND_VM_SET_NEXT_OPCODE(opline + 1); \
5881
24
    } \
5882
171
    ZEND_VM_CONTINUE(); \
5883
171
  } while (0)
5884
30.5k
#define ZEND_VM_SMART_BRANCH_TRUE_JMPZ() do { \
5885
30.5k
    ZEND_VM_SET_NEXT_OPCODE(opline + 2); \
5886
30.5k
    ZEND_VM_CONTINUE(); \
5887
30.5k
  } while (0)
5888
132k
#define ZEND_VM_SMART_BRANCH_TRUE_JMPNZ() do { \
5889
132k
    ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline + 1, (opline+1)->op2)); \
5890
132k
    ZEND_VM_CONTINUE(); \
5891
132k
  } while (0)
5892
9.58k
#define ZEND_VM_SMART_BRANCH_TRUE_NONE() do { \
5893
9.58k
    ZVAL_TRUE(EX_VAR(opline->result.var)); \
5894
9.58k
    ZEND_VM_NEXT_OPCODE(); \
5895
9.58k
  } while (0)
5896
4.06k
#define ZEND_VM_SMART_BRANCH_FALSE() do { \
5897
4.06k
    if (EXPECTED(opline->result_type == (IS_SMART_BRANCH_JMPNZ|IS_TMP_VAR))) { \
5898
452
      ZEND_VM_SET_NEXT_OPCODE(opline + 2); \
5899
3.61k
    } else if (EXPECTED(opline->result_type == (IS_SMART_BRANCH_JMPZ|IS_TMP_VAR))) { \
5900
2.22k
      ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline + 1, (opline+1)->op2)); \
5901
2.22k
    } else { \
5902
1.38k
      ZVAL_FALSE(EX_VAR(opline->result.var)); \
5903
1.38k
      ZEND_VM_SET_NEXT_OPCODE(opline + 1); \
5904
1.38k
    } \
5905
4.06k
    ZEND_VM_CONTINUE(); \
5906
4.06k
  } while (0)
5907
12.3k
#define ZEND_VM_SMART_BRANCH_FALSE_JMPZ() do { \
5908
12.3k
    ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline + 1, (opline+1)->op2)); \
5909
12.3k
    ZEND_VM_CONTINUE(); \
5910
12.3k
  } while (0)
5911
12.3k
#define ZEND_VM_SMART_BRANCH_FALSE_JMPNZ() do { \
5912
12.3k
    ZEND_VM_SET_NEXT_OPCODE(opline + 2); \
5913
12.3k
    ZEND_VM_CONTINUE(); \
5914
12.3k
  } while (0)
5915
13.4k
#define ZEND_VM_SMART_BRANCH_FALSE_NONE() do { \
5916
13.4k
    ZVAL_FALSE(EX_VAR(opline->result.var)); \
5917
13.4k
    ZEND_VM_NEXT_OPCODE(); \
5918
13.4k
  } while (0)
5919
5920
#ifdef __GNUC__
5921
# define ZEND_VM_GUARD(name) __asm__("#" #name)
5922
#else
5923
# define ZEND_VM_GUARD(name)
5924
#endif
5925
5926
4.73k
#define UNDEF_RESULT() do { \
5927
4.73k
    if (opline->result_type & (IS_VAR | IS_TMP_VAR)) { \
5928
2.85k
      ZVAL_UNDEF(EX_VAR(opline->result.var)); \
5929
2.85k
    } \
5930
4.73k
  } while (0)
5931
5932
/* This callback disables optimization of "vm_stack_data" variable in VM */
5933
ZEND_API void (ZEND_FASTCALL *zend_touch_vm_stack_data)(void *vm_stack_data) = NULL;
5934
5935
#include "zend_vm_execute.h"
5936
5937
ZEND_API zend_result zend_set_user_opcode_handler(zend_uchar opcode, user_opcode_handler_t handler)
5938
0
{
5939
0
  if (opcode != ZEND_USER_OPCODE) {
5940
0
    if (handler == NULL) {
5941
      /* restore the original handler */
5942
0
      zend_user_opcodes[opcode] = opcode;
5943
0
    } else {
5944
0
      zend_user_opcodes[opcode] = ZEND_USER_OPCODE;
5945
0
    }
5946
0
    zend_user_opcode_handlers[opcode] = handler;
5947
0
    return SUCCESS;
5948
0
  }
5949
0
  return FAILURE;
5950
0
}
5951
5952
ZEND_API user_opcode_handler_t zend_get_user_opcode_handler(zend_uchar opcode)
5953
4.09k
{
5954
4.09k
  return zend_user_opcode_handlers[opcode];
5955
4.09k
}
5956
5957
ZEND_API zval *zend_get_zval_ptr(const zend_op *opline, int op_type, const znode_op *node, const zend_execute_data *execute_data)
5958
0
{
5959
0
  zval *ret;
5960
5961
0
  switch (op_type) {
5962
0
    case IS_CONST:
5963
0
      ret = RT_CONSTANT(opline, *node);
5964
0
      break;
5965
0
    case IS_TMP_VAR:
5966
0
    case IS_VAR:
5967
0
    case IS_CV:
5968
0
      ret = EX_VAR(node->var);
5969
0
      break;
5970
0
    default:
5971
0
      ret = NULL;
5972
0
      break;
5973
0
  }
5974
0
  return ret;
5975
0
}
5976
5977
ZEND_API void zend_return_unwrap_ref(zend_execute_data *execute_data, zval *return_value)
5978
3.81k
{
5979
3.81k
  if (!return_value || !Z_ISREF_P(return_value)) {
5980
444
    return;
5981
444
  }
5982
5983
3.36k
  zend_execute_data *prev_ex = EX(prev_execute_data);
5984
3.36k
  if (!prev_ex || !prev_ex->func || !ZEND_USER_CODE(prev_ex->func->type)) {
5985
125
    return;
5986
125
  }
5987
5988
3.24k
  const zend_op *do_opline = prev_ex->opline;
5989
3.24k
  if (do_opline->result_type != IS_TMP_VAR) {
5990
1.83k
    return;
5991
1.83k
  }
5992
5993
1.40k
  if (do_opline->opcode != ZEND_DO_FCALL
5994
1.09k
   && do_opline->opcode != ZEND_DO_FCALL_BY_NAME
5995
1.09k
   && do_opline->opcode != ZEND_DO_ICALL
5996
1.09k
   && do_opline->opcode != ZEND_DO_UCALL) {
5997
851
    return;
5998
851
  }
5999
6000
553
  zend_unwrap_reference(return_value);
6001
553
}