Coverage Report

Created: 2026-07-25 06:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/php-src/Zend/Optimizer/zend_inference.c
Line
Count
Source
1
/*
2
   +----------------------------------------------------------------------+
3
   | Zend Engine, e-SSA based Type & Range Inference                      |
4
   +----------------------------------------------------------------------+
5
   | Copyright © The PHP Group and Contributors.                          |
6
   +----------------------------------------------------------------------+
7
   | This source file is subject to the Modified BSD License that is      |
8
   | bundled with this package in the file LICENSE, and is available      |
9
   | through the World Wide Web at <https://www.php.net/license/>.        |
10
   |                                                                      |
11
   | SPDX-License-Identifier: BSD-3-Clause                                |
12
   +----------------------------------------------------------------------+
13
   | Authors: Dmitry Stogov <dmitry@php.net>                              |
14
   +----------------------------------------------------------------------+
15
*/
16
17
#include "zend_compile.h"
18
#include "zend_generators.h"
19
#include "zend_inference.h"
20
#include "zend_func_info.h"
21
#include "zend_call_graph.h"
22
#include "zend_closures.h"
23
#include "zend_worklist.h"
24
#include "zend_optimizer_internal.h"
25
26
/* The used range inference algorithm is described in:
27
 *     V. Campos, R. Rodrigues, I. de Assis Costa and F. Pereira.
28
 *     "Speed and Precision in Range Analysis", SBLP'12.
29
 *
30
 * There are a couple degrees of freedom, we use:
31
 *  * Propagation on SCCs.
32
 *  * e-SSA for live range splitting.
33
 *  * Only intra-procedural inference.
34
 *  * Widening with warmup passes, but without jump sets.
35
 */
36
37
/* Whether to handle symbolic range constraints */
38
#define SYM_RANGE
39
40
/* Whether to handle negative range constraints */
41
/* Negative range inference is buggy, so disabled for now */
42
#undef NEG_RANGE
43
44
/* Number of warmup passes to use prior to widening */
45
401k
#define RANGE_WARMUP_PASSES 16
46
47
/* Logging for range inference in general */
48
#if 0
49
#define LOG_SSA_RANGE(...) fprintf(stderr, __VA_ARGS__)
50
#else
51
#define LOG_SSA_RANGE(...)
52
#endif
53
54
/* Logging for negative range constraints */
55
#if 0
56
#define LOG_NEG_RANGE(...) fprintf(stderr, __VA_ARGS__)
57
#else
58
#define LOG_NEG_RANGE(...)
59
#endif
60
61
/* Pop elements in unspecified order from worklist until it is empty */
62
587k
#define WHILE_WORKLIST(worklist, len, i) do { \
63
587k
  bool _done = 0; \
64
1.63M
  while (!_done) { \
65
1.04M
    _done = 1; \
66
12.2M
    ZEND_BITSET_FOREACH(worklist, len, i) { \
67
1.80M
      zend_bitset_excl(worklist, i); \
68
1.80M
      _done = 0;
69
70
#define WHILE_WORKLIST_END() \
71
1.80M
    } ZEND_BITSET_FOREACH_END(); \
72
1.04M
  } \
73
587k
} while (0)
74
75
#define CHECK_SCC_VAR(var2) \
76
  do { \
77
    if (!ssa->vars[var2].no_val) { \
78
      if (ssa->vars[var2].scc < 0) { \
79
        zend_ssa_check_scc_var(op_array, ssa, var2, index, stack); \
80
      } \
81
      if (ssa->vars[var2].scc < ssa->vars[var].scc) { \
82
        ssa->vars[var].scc = ssa->vars[var2].scc; \
83
        is_root = 0; \
84
      } \
85
    } \
86
  } while (0)
87
88
#define CHECK_SCC_ENTRY(var2) \
89
1.48M
  do { \
90
1.48M
    if (ssa->vars[var2].scc != ssa->vars[var].scc) { \
91
1.26M
      ssa->vars[var2].scc_entry = 1; \
92
1.26M
    } \
93
1.48M
  } while (0)
94
95
#define ADD_SCC_VAR(_var) \
96
225k
  do { \
97
225k
    if (ssa->vars[_var].scc == scc && \
98
225k
        !(ssa->var_info[_var].type & MAY_BE_REF)) { \
99
94.6k
      zend_bitset_incl(worklist, _var); \
100
94.6k
    } \
101
225k
  } while (0)
102
103
#define ADD_SCC_VAR_1(_var) \
104
217k
  do { \
105
217k
    if (ssa->vars[_var].scc == scc && \
106
217k
        !(ssa->var_info[_var].type & MAY_BE_REF) && \
107
217k
        !zend_bitset_in(visited, _var)) { \
108
109k
      zend_bitset_incl(worklist, _var); \
109
109k
    } \
110
217k
  } while (0)
111
112
#define FOR_EACH_DEFINED_VAR(line, MACRO) \
113
1.67M
  do { \
114
1.67M
    if (ssa->ops[line].op1_def >= 0) { \
115
276k
      MACRO(ssa->ops[line].op1_def); \
116
276k
    } \
117
1.67M
    if (ssa->ops[line].op2_def >= 0) { \
118
16.4k
      MACRO(ssa->ops[line].op2_def); \
119
16.4k
    } \
120
1.67M
    if (ssa->ops[line].result_def >= 0) { \
121
1.13M
      MACRO(ssa->ops[line].result_def); \
122
1.13M
    } \
123
1.67M
    if (op_array->opcodes[line].opcode == ZEND_OP_DATA) { \
124
22.1k
      if (ssa->ops[line-1].op1_def >= 0) { \
125
14.5k
        MACRO(ssa->ops[line-1].op1_def); \
126
14.5k
      } \
127
22.1k
      if (ssa->ops[line-1].op2_def >= 0) { \
128
0
        MACRO(ssa->ops[line-1].op2_def); \
129
0
      } \
130
22.1k
      if (ssa->ops[line-1].result_def >= 0) { \
131
6.82k
        MACRO(ssa->ops[line-1].result_def); \
132
6.82k
      } \
133
1.65M
    } else if ((uint32_t)line+1 < op_array->last && \
134
1.65M
               op_array->opcodes[line+1].opcode == ZEND_OP_DATA) { \
135
38.3k
      if (ssa->ops[line+1].op1_def >= 0) { \
136
232
        MACRO(ssa->ops[line+1].op1_def); \
137
232
      } \
138
38.3k
      if (ssa->ops[line+1].op2_def >= 0) { \
139
0
        MACRO(ssa->ops[line+1].op2_def); \
140
0
      } \
141
38.3k
      if (ssa->ops[line+1].result_def >= 0) { \
142
0
        MACRO(ssa->ops[line+1].result_def); \
143
0
      } \
144
38.3k
    } \
145
1.67M
  } while (0)
146
147
148
#define FOR_EACH_VAR_USAGE(_var, MACRO) \
149
1.63M
  do { \
150
1.63M
    zend_ssa_phi *p = ssa->vars[_var].phi_use_chain; \
151
1.63M
    int use = ssa->vars[_var].use_chain; \
152
3.31M
    while (use >= 0) { \
153
1.67M
      FOR_EACH_DEFINED_VAR(use, MACRO); \
154
1.67M
      use = zend_ssa_next_use(ssa->ops, _var, use); \
155
1.67M
    } \
156
1.63M
    p = ssa->vars[_var].phi_use_chain; \
157
2.10M
    while (p) { \
158
472k
      MACRO(p->ssa_var); \
159
472k
      p = zend_ssa_next_use_phi(ssa, _var, p); \
160
472k
    } \
161
1.63M
  } while (0)
162
163
5.49k
static inline bool add_will_overflow(zend_long a, zend_long b) {
164
5.49k
  return (b > 0 && a > ZEND_LONG_MAX - b)
165
5.46k
    || (b < 0 && a < ZEND_LONG_MIN - b);
166
5.49k
}
167
#if 0
168
static inline bool sub_will_overflow(zend_long a, zend_long b) {
169
  return (b > 0 && a < ZEND_LONG_MIN + b)
170
    || (b < 0 && a > ZEND_LONG_MAX + b);
171
}
172
#endif
173
174
#if 0
175
/* Recursive Pearce's SCC algorithm implementation */
176
static void zend_ssa_check_scc_var(const zend_op_array *op_array, zend_ssa *ssa, int var, int *index, zend_worklist_stack *stack) /* {{{ */
177
{
178
  int is_root = 1;
179
#ifdef SYM_RANGE
180
  zend_ssa_phi *p;
181
#endif
182
183
  ssa->vars[var].scc = *index;
184
  (*index)++;
185
186
  FOR_EACH_VAR_USAGE(var, CHECK_SCC_VAR);
187
188
#ifdef SYM_RANGE
189
  /* Process symbolic control-flow constraints */
190
  p = ssa->vars[var].sym_use_chain;
191
  while (p) {
192
    CHECK_SCC_VAR(p->ssa_var);
193
    p = p->sym_use_chain;
194
  }
195
#endif
196
197
  if (is_root) {
198
    ssa->sccs--;
199
    while (stack->len > 0) {
200
      int var2 = zend_worklist_stack_peek(stack);
201
      if (ssa->vars[var2].scc < ssa->vars[var].scc) {
202
        break;
203
      }
204
      zend_worklist_stack_pop(stack);
205
      ssa->vars[var2].scc = ssa->sccs;
206
      (*index)--;
207
    }
208
    ssa->vars[var].scc = ssa->sccs;
209
    ssa->vars[var].scc_entry = 1;
210
    (*index)--;
211
  } else {
212
    zend_worklist_stack_push(stack, var);
213
  }
214
}
215
/* }}} */
216
217
ZEND_API void zend_ssa_find_sccs(const zend_op_array *op_array, zend_ssa *ssa) /* {{{ */
218
{
219
  int index = 0;
220
  zend_worklist_stack stack;
221
  int j;
222
  ALLOCA_FLAG(stack_use_heap)
223
224
  ZEND_WORKLIST_STACK_ALLOCA(&stack, ssa->vars_count, stack_use_heap);
225
226
  /* Find SCCs using Pearce's algorithm. */
227
  ssa->sccs = ssa->vars_count;
228
  for (j = 0; j < ssa->vars_count; j++) {
229
    if (!ssa->vars[j].no_val && ssa->vars[j].scc < 0) {
230
      zend_ssa_check_scc_var(op_array, ssa, j, &index, &stack);
231
    }
232
  }
233
234
  if (ssa->sccs) {
235
    /* Shift SCC indexes. */
236
    for (j = 0; j < ssa->vars_count; j++) {
237
      if (ssa->vars[j].scc >= 0) {
238
        ssa->vars[j].scc -= ssa->sccs;
239
      }
240
    }
241
  }
242
  ssa->sccs = ssa->vars_count - ssa->sccs;
243
244
  for (j = 0; j < ssa->vars_count; j++) {
245
    if (ssa->vars[j].scc >= 0) {
246
      int var = j;
247
      FOR_EACH_VAR_USAGE(var, CHECK_SCC_ENTRY);
248
    }
249
  }
250
251
  ZEND_WORKLIST_STACK_FREE_ALLOCA(&stack, stack_use_heap);
252
}
253
/* }}} */
254
255
#else
256
/* Iterative Pearce's SCC algorithm implementation */
257
258
typedef struct _zend_scc_iterator {
259
  int               state;
260
  int               last;
261
  union {
262
    int           use;
263
    zend_ssa_phi *phi;
264
  };
265
} zend_scc_iterator;
266
267
static int zend_scc_next(const zend_op_array *op_array, const zend_ssa *ssa, int var, zend_scc_iterator *iterator) /* {{{ */
268
2.84M
{
269
2.84M
  zend_ssa_phi *phi;
270
2.84M
  int use, var2;
271
272
2.84M
  switch (iterator->state) {
273
1.37M
    case 0:                       goto state_0;
274
169k
    case 1:  use = iterator->use; goto state_1;
275
11.4k
    case 2:  use = iterator->use; goto state_2;
276
950k
    case 3:  use = iterator->use; goto state_3;
277
9.71k
    case 4:  use = iterator->use; goto state_4;
278
0
    case 5:  use = iterator->use; goto state_5;
279
114
    case 6:  use = iterator->use; goto state_6;
280
0
    case 7:  use = iterator->use; goto state_7;
281
5.40k
    case 8:  use = iterator->use; goto state_8;
282
313k
    case 9:  phi = iterator->phi; goto state_9;
283
0
#ifdef SYM_RANGE
284
6.64k
    case 10: phi = iterator->phi; goto state_10;
285
0
#endif
286
0
    case 11:                      goto state_11;
287
2.84M
  }
288
289
1.37M
state_0:
290
1.37M
  use = ssa->vars[var].use_chain;
291
2.79M
  while (use >= 0) {
292
1.41M
    iterator->use = use;
293
1.41M
    var2 = ssa->ops[use].op1_def;
294
1.41M
    if (var2 >= 0 && !ssa->vars[var2].no_val) {
295
169k
      iterator->state = 1;
296
169k
      return var2;
297
169k
    }
298
1.41M
state_1:
299
1.41M
    var2 = ssa->ops[use].op2_def;
300
1.41M
    if (var2 >= 0 && !ssa->vars[var2].no_val) {
301
11.4k
      iterator->state = 2;
302
11.4k
      return var2;
303
11.4k
    }
304
1.41M
state_2:
305
1.41M
    var2 = ssa->ops[use].result_def;
306
1.41M
    if (var2 >= 0 && !ssa->vars[var2].no_val) {
307
950k
      iterator->state = 3;
308
950k
      return var2;
309
950k
    }
310
1.41M
state_3:
311
1.41M
    if (op_array->opcodes[use].opcode == ZEND_OP_DATA) {
312
18.2k
      var2 = ssa->ops[use-1].op1_def;
313
18.2k
      if (var2 >= 0 && !ssa->vars[var2].no_val) {
314
9.71k
        iterator->state = 4;
315
9.71k
        return var2;
316
9.71k
      }
317
18.2k
state_4:
318
18.2k
      var2 = ssa->ops[use-1].op2_def;
319
18.2k
      if (var2 >= 0 && !ssa->vars[var2].no_val) {
320
0
        iterator->state = 5;
321
0
        return var2;
322
0
      }
323
18.2k
state_5:
324
18.2k
      var2 = ssa->ops[use-1].result_def;
325
18.2k
      if (var2 >= 0 && !ssa->vars[var2].no_val) {
326
5.40k
        iterator->state = 8;
327
5.40k
        return var2;
328
5.40k
      }
329
1.39M
    } else if ((uint32_t)use+1 < op_array->last &&
330
1.38M
               op_array->opcodes[use+1].opcode == ZEND_OP_DATA) {
331
31.1k
      var2 = ssa->ops[use+1].op1_def;
332
31.1k
      if (var2 >= 0 && !ssa->vars[var2].no_val) {
333
114
        iterator->state = 6;
334
114
        return var2;
335
114
      }
336
31.1k
state_6:
337
31.1k
      var2 = ssa->ops[use+1].op2_def;
338
31.1k
      if (var2 >= 0 && !ssa->vars[var2].no_val) {
339
0
        iterator->state = 7;
340
0
        return var2;
341
0
      }
342
31.1k
state_7:
343
31.1k
      var2 = ssa->ops[use+1].result_def;
344
31.1k
      if (var2 >= 0 && !ssa->vars[var2].no_val) {
345
0
        iterator->state = 8;
346
0
        return var2;
347
0
      }
348
31.1k
    }
349
1.41M
state_8:
350
1.41M
    use = zend_ssa_next_use(ssa->ops, var, use);
351
1.41M
  }
352
353
1.37M
  phi = ssa->vars[var].phi_use_chain;
354
1.69M
  while (phi) {
355
316k
    var2 = phi->ssa_var;
356
316k
    if (!ssa->vars[var2].no_val) {
357
313k
      iterator->state = 9;
358
313k
      iterator->phi = phi;
359
313k
      return var2;
360
313k
    }
361
316k
state_9:
362
316k
    phi = zend_ssa_next_use_phi(ssa, var, phi);
363
316k
  }
364
365
1.37M
#ifdef SYM_RANGE
366
  /* Process symbolic control-flow constraints */
367
1.37M
  phi = ssa->vars[var].sym_use_chain;
368
1.38M
  while (phi) {
369
6.89k
    var2 = phi->ssa_var;
370
6.89k
    if (!ssa->vars[var2].no_val) {
371
6.64k
      iterator->state = 10;
372
6.64k
      iterator->phi = phi;
373
6.64k
      return var2;
374
6.64k
    }
375
6.89k
state_10:
376
6.89k
    phi = phi->sym_use_chain;
377
6.89k
  }
378
1.37M
#endif
379
380
1.37M
  iterator->state = 11;
381
1.37M
state_11:
382
1.37M
  return -1;
383
1.37M
}
384
/* }}} */
385
386
static void zend_ssa_check_scc_var(const zend_op_array *op_array, zend_ssa *ssa, int var, int *index, zend_worklist_stack *stack, zend_worklist_stack *vstack, zend_scc_iterator *iterators) /* {{{ */
387
376k
{
388
1.37M
restart:
389
1.37M
  zend_worklist_stack_push(vstack, var);
390
1.37M
  iterators[var].state = 0;
391
1.37M
  iterators[var].last = -1;
392
1.37M
  ssa->vars[var].scc_entry = 1;
393
1.37M
  ssa->vars[var].scc = *index;
394
1.37M
  (*index)++;
395
396
2.75M
  while (vstack->len > 0) {
397
2.38M
    var = zend_worklist_stack_peek(vstack);
398
2.84M
    while (1) {
399
2.84M
      int var2;
400
401
2.84M
      if (iterators[var].last >= 0) {
402
        /* finish edge */
403
1.46M
        var2 = iterators[var].last;
404
1.46M
        if (ssa->vars[var2].scc < ssa->vars[var].scc) {
405
151k
          ssa->vars[var].scc = ssa->vars[var2].scc;
406
151k
          ssa->vars[var].scc_entry = 0;
407
151k
        }
408
1.46M
      }
409
2.84M
      var2 = zend_scc_next(op_array, ssa, var, iterators + var);
410
2.84M
      iterators[var].last = var2;
411
2.84M
      if (var2 < 0) break;
412
      /* begin edge */
413
1.46M
      if (ssa->vars[var2].scc < 0) {
414
1.00M
        var = var2;
415
1.00M
        goto restart;
416
1.00M
      }
417
1.46M
    }
418
419
    /* finish visiting */
420
1.37M
    zend_worklist_stack_pop(vstack);
421
1.37M
    if (ssa->vars[var].scc_entry) {
422
1.23M
      ssa->sccs--;
423
1.37M
      while (stack->len > 0) {
424
178k
        int var2 = zend_worklist_stack_peek(stack);
425
178k
        if (ssa->vars[var2].scc < ssa->vars[var].scc) {
426
30.7k
          break;
427
30.7k
        }
428
148k
        zend_worklist_stack_pop(stack);
429
148k
        ssa->vars[var2].scc = ssa->sccs;
430
148k
        (*index)--;
431
148k
      }
432
1.23M
      ssa->vars[var].scc = ssa->sccs;
433
1.23M
      (*index)--;
434
1.23M
    } else {
435
148k
      zend_worklist_stack_push(stack, var);
436
148k
    }
437
1.37M
  }
438
1.37M
}
439
/* }}} */
440
441
ZEND_API void zend_ssa_find_sccs(const zend_op_array *op_array, zend_ssa *ssa) /* {{{ */
442
89.1k
{
443
89.1k
  int index = 0;
444
89.1k
  zend_worklist_stack stack, vstack;
445
89.1k
  zend_scc_iterator *iterators;
446
89.1k
  int j;
447
89.1k
  ALLOCA_FLAG(stack_use_heap)
448
89.1k
  ALLOCA_FLAG(vstack_use_heap)
449
89.1k
  ALLOCA_FLAG(iterators_use_heap)
450
451
89.1k
  iterators = do_alloca(sizeof(zend_scc_iterator) * ssa->vars_count, iterators_use_heap);
452
89.1k
  ZEND_WORKLIST_STACK_ALLOCA(&vstack, ssa->vars_count, vstack_use_heap);
453
89.1k
  ZEND_WORKLIST_STACK_ALLOCA(&stack, ssa->vars_count, stack_use_heap);
454
455
  /* Find SCCs using Pearce's algorithm. */
456
89.1k
  ssa->sccs = ssa->vars_count;
457
1.57M
  for (j = 0; j < ssa->vars_count; j++) {
458
1.48M
    if (!ssa->vars[j].no_val && ssa->vars[j].scc < 0) {
459
376k
      zend_ssa_check_scc_var(op_array, ssa, j, &index, &stack, &vstack, iterators);
460
376k
    }
461
1.48M
  }
462
463
89.1k
  if (ssa->sccs) {
464
    /* Shift SCC indexes. */
465
956k
    for (j = 0; j < ssa->vars_count; j++) {
466
919k
      if (ssa->vars[j].scc >= 0) {
467
816k
        ssa->vars[j].scc -= ssa->sccs;
468
816k
      }
469
919k
    }
470
37.0k
  }
471
89.1k
  ssa->sccs = ssa->vars_count - ssa->sccs;
472
473
1.57M
  for (j = 0; j < ssa->vars_count; j++) {
474
1.48M
    if (ssa->vars[j].scc >= 0) {
475
1.37M
      int var = j;
476
1.48M
      FOR_EACH_VAR_USAGE(var, CHECK_SCC_ENTRY);
477
1.37M
    }
478
1.48M
  }
479
480
89.1k
  ZEND_WORKLIST_STACK_FREE_ALLOCA(&stack, stack_use_heap);
481
89.1k
  ZEND_WORKLIST_STACK_FREE_ALLOCA(&vstack, vstack_use_heap);
482
89.1k
  free_alloca(iterators, iterators_use_heap);
483
89.1k
}
484
/* }}} */
485
486
#endif
487
488
ZEND_API void zend_ssa_find_false_dependencies(const zend_op_array *op_array, const zend_ssa *ssa) /* {{{ */
489
89.1k
{
490
89.1k
  zend_ssa_var *ssa_vars = ssa->vars;
491
89.1k
  const zend_ssa_op *ssa_ops = ssa->ops;
492
89.1k
  int ssa_vars_count = ssa->vars_count;
493
89.1k
  zend_bitset worklist;
494
89.1k
  int i, use;
495
89.1k
  const zend_ssa_phi *p;
496
89.1k
  ALLOCA_FLAG(use_heap);
497
498
89.1k
  if (!op_array->function_name || !ssa->vars || !ssa->ops) {
499
39.5k
    return;
500
39.5k
  }
501
502
49.5k
  worklist = do_alloca(sizeof(zend_ulong) * zend_bitset_len(ssa_vars_count), use_heap);
503
49.5k
  memset(worklist, 0, sizeof(zend_ulong) * zend_bitset_len(ssa_vars_count));
504
505
584k
  for (i = 0; i < ssa_vars_count; i++) {
506
535k
    ssa_vars[i].no_val = 1; /* mark as unused */
507
535k
    use = ssa->vars[i].use_chain;
508
574k
    while (use >= 0) {
509
405k
      if (!zend_ssa_is_no_val_use(&op_array->opcodes[use], &ssa->ops[use], i)) {
510
366k
        ssa_vars[i].no_val = 0; /* used directly */
511
366k
        zend_bitset_incl(worklist, i);
512
366k
        break;
513
366k
      }
514
39.3k
      use = zend_ssa_next_use(ssa_ops, i, use);
515
39.3k
    }
516
535k
  }
517
518
1.62M
  WHILE_WORKLIST(worklist, zend_bitset_len(ssa_vars_count), i) {
519
1.62M
    if (ssa_vars[i].definition_phi) {
520
      /* mark all possible sources as used */
521
68.6k
      p = ssa_vars[i].definition_phi;
522
68.6k
      if (p->pi >= 0) {
523
21.9k
        if (ssa_vars[p->sources[0]].no_val) {
524
114
          ssa_vars[p->sources[0]].no_val = 0; /* used indirectly */
525
114
          zend_bitset_incl(worklist, p->sources[0]);
526
114
        }
527
46.7k
      } else {
528
143k
        for (uint32_t j = 0; j < ssa->cfg.blocks[p->block].predecessors_count; j++) {
529
96.8k
          ZEND_ASSERT(p->sources[j] >= 0);
530
96.8k
          if (ssa->vars[p->sources[j]].no_val) {
531
65.3k
            ssa_vars[p->sources[j]].no_val = 0; /* used indirectly */
532
65.3k
            zend_bitset_incl(worklist, p->sources[j]);
533
65.3k
          }
534
96.8k
        }
535
46.7k
      }
536
68.6k
    }
537
1.62M
  } WHILE_WORKLIST_END();
538
539
49.5k
  free_alloca(worklist, use_heap);
540
49.5k
}
541
/* }}} */
542
543
/* From "Hacker's Delight" */
544
static zend_ulong minOR(zend_ulong a, zend_ulong b, zend_ulong c, zend_ulong d)
545
143
{
546
143
  zend_ulong m, temp;
547
548
143
  m = Z_UL(1) << (sizeof(zend_ulong) * 8 - 1);
549
8.57k
  while (m != 0) {
550
8.48k
    if (~a & c & m) {
551
339
      temp = (a | m) & -m;
552
339
      if (temp <= b) {
553
54
        a = temp;
554
54
        break;
555
54
      }
556
8.14k
    } else if (a & ~c & m) {
557
742
      temp = (c | m) & -m;
558
742
      if (temp <= d) {
559
0
        c = temp;
560
0
        break;
561
0
      }
562
742
    }
563
8.43k
    m = m >> 1;
564
8.43k
  }
565
143
  return a | c;
566
143
}
567
568
static zend_ulong maxOR(zend_ulong a, zend_ulong b, zend_ulong c, zend_ulong d)
569
280
{
570
280
  zend_ulong m, temp;
571
572
280
  m = Z_UL(1) << (sizeof(zend_ulong) * 8 - 1);
573
9.97k
  while (m != 0) {
574
9.91k
    if (b & d & m) {
575
239
      temp = (b - m) | (m - 1);
576
239
      if (temp >= a) {
577
215
        b = temp;
578
215
        break;
579
215
      }
580
24
      temp = (d - m) | (m - 1);
581
24
      if (temp >= c) {
582
0
        d = temp;
583
0
        break;
584
0
      }
585
24
    }
586
9.69k
    m = m >> 1;
587
9.69k
  }
588
280
  return b | d;
589
280
}
590
591
static zend_ulong minAND(zend_ulong a, zend_ulong b, zend_ulong c, zend_ulong d)
592
1.89k
{
593
1.89k
  zend_ulong m, temp;
594
595
1.89k
  m = Z_UL(1) << (sizeof(zend_ulong) * 8 - 1);
596
73.7k
  while (m != 0) {
597
73.1k
    if (~a & ~c & m) {
598
57.3k
      temp = (a | m) & -m;
599
57.3k
      if (temp <= b) {
600
814
        a = temp;
601
814
        break;
602
814
      }
603
56.5k
      temp = (c | m) & -m;
604
56.5k
      if (temp <= d) {
605
476
        c = temp;
606
476
        break;
607
476
      }
608
56.5k
    }
609
71.8k
    m = m >> 1;
610
71.8k
  }
611
1.89k
  return a & c;
612
1.89k
}
613
614
static zend_ulong maxAND(zend_ulong a, zend_ulong b, zend_ulong c, zend_ulong d)
615
1.29k
{
616
1.29k
  zend_ulong m, temp;
617
618
1.29k
  m = Z_UL(1) << (sizeof(zend_ulong) * 8 - 1);
619
55.6k
  while (m != 0) {
620
55.1k
    if (b & ~d & m) {
621
166
      temp = (b | ~m) | (m - 1);
622
166
      if (temp >= a) {
623
166
        b = temp;
624
166
        break;
625
166
      }
626
54.9k
    } else if (~b & d & m) {
627
604
      temp = (d | ~m) | (m - 1);
628
604
      if (temp >= c) {
629
604
        d = temp;
630
604
        break;
631
604
      }
632
604
    }
633
54.3k
    m = m >> 1;
634
54.3k
  }
635
1.29k
  return b & d;
636
1.29k
}
637
638
/* Based on "Hacker's Delight" */
639
640
/*
641
0: + + + + 0 0 0 0 => 0 0 + min/max
642
2: + + - + 0 0 1 0 => 1 0 ? min(a,b,c,-1)/max(a,b,0,d)
643
3: + + - - 0 0 1 1 => 1 1 - min/max
644
8: - + + + 1 0 0 0 => 1 0 ? min(a,-1,b,d)/max(0,b,c,d)
645
a: - + - + 1 0 1 0 => 1 0 ? MIN(a,c)/max(0,b,0,d)
646
b: - + - - 1 0 1 1 => 1 1 - c/-1
647
c: - - + + 1 1 0 0 => 1 1 - min/max
648
e: - - - + 1 1 1 0 => 1 1 - a/-1
649
f  - - - - 1 1 1 1 => 1 1 - min/max
650
*/
651
static void zend_ssa_range_or(zend_long a, zend_long b, zend_long c, zend_long d, zend_ssa_range *tmp)
652
296
{
653
296
  int x = ((a < 0) ? 8 : 0) |
654
296
          ((b < 0) ? 4 : 0) |
655
296
          ((c < 0) ? 2 : 0) |
656
296
          ((d < 0) ? 1 : 0);
657
296
  switch (x) {
658
51
    case 0x0:
659
51
    case 0x3:
660
59
    case 0xc:
661
59
    case 0xf:
662
59
      tmp->min = minOR(a, b, c, d);
663
59
      tmp->max = maxOR(a, b, c, d);
664
59
      break;
665
6
    case 0x2:
666
6
      tmp->min = minOR(a, b, c, -1);
667
6
      tmp->max = maxOR(a, b, 0, d);
668
6
      break;
669
78
    case 0x8:
670
78
      tmp->min = minOR(a, -1, c, d);
671
78
      tmp->max = maxOR(0, b, c, d);
672
78
      break;
673
137
    case 0xa:
674
137
      tmp->min = MIN(a, c);
675
137
      tmp->max = maxOR(0, b, 0, d);
676
137
      break;
677
16
    case 0xb:
678
16
      tmp->min = c;
679
16
      tmp->max = -1;
680
16
      break;
681
0
    case 0xe:
682
0
      tmp->min = a;
683
0
      tmp->max = -1;
684
0
      break;
685
296
  }
686
296
}
687
688
/*
689
0: + + + + 0 0 0 0 => 0 0 + min/max
690
2: + + - + 0 0 1 0 => 0 0 + 0/b
691
3: + + - - 0 0 1 1 => 0 0 + min/max
692
8: - + + + 1 0 0 0 => 0 0 + 0/d
693
a: - + - + 1 0 1 0 => 1 0 ? min(a,-1,c,-1)/NAX(b,d)
694
b: - + - - 1 0 1 1 => 1 0 ? min(a,-1,c,d)/max(0,b,c,d)
695
c: - - + + 1 1 0 0 => 1 1 - min/max
696
e: - - - + 1 1 1 0 => 1 0 ? min(a,b,c,-1)/max(a,b,0,d)
697
f  - - - - 1 1 1 1 => 1 1 - min/max
698
*/
699
static void zend_ssa_range_and(zend_long a, zend_long b, zend_long c, zend_long d, zend_ssa_range *tmp)
700
2.54k
{
701
2.54k
  int x = ((a < 0) ? 8 : 0) |
702
2.54k
          ((b < 0) ? 4 : 0) |
703
2.54k
          ((c < 0) ? 2 : 0) |
704
2.54k
          ((d < 0) ? 1 : 0);
705
2.54k
  switch (x) {
706
1.11k
    case 0x0:
707
1.13k
    case 0x3:
708
1.13k
    case 0xc:
709
1.13k
    case 0xf:
710
1.13k
      tmp->min = minAND(a, b, c, d);
711
1.13k
      tmp->max = maxAND(a, b, c, d);
712
1.13k
      break;
713
224
    case 0x2:
714
224
      tmp->min = 0;
715
224
      tmp->max = b;
716
224
      break;
717
427
    case 0x8:
718
427
      tmp->min = 0;
719
427
      tmp->max = d;
720
427
      break;
721
604
    case 0xa:
722
604
      tmp->min = minAND(a, -1, c, -1);
723
604
      tmp->max = MAX(b, d);
724
604
      break;
725
18
    case 0xb:
726
18
      tmp->min = minAND(a, -1, c, d);
727
18
      tmp->max = maxAND(0, b, c, d);
728
18
      break;
729
136
    case 0xe:
730
136
      tmp->min = minAND(a, b, c, -1);
731
136
      tmp->max = maxAND(a, b, 0, d);
732
136
      break;
733
2.54k
  }
734
2.54k
}
735
736
static inline bool zend_abs_range(
737
470
    zend_long min, zend_long max, zend_long *abs_min, zend_long *abs_max) {
738
470
  if (min == ZEND_LONG_MIN) {
739
    /* Cannot take absolute value of LONG_MIN  */
740
47
    return 0;
741
47
  }
742
743
423
  if (min >= 0) {
744
379
    *abs_min = min;
745
379
    *abs_max = max;
746
379
  } else if (max <= 0) {
747
44
    *abs_min = -max;
748
44
    *abs_max = -min;
749
44
  } else {
750
    /* Range crossing zero */
751
0
    *abs_min = 0;
752
0
    *abs_max = MAX(max, -min);
753
0
  }
754
755
423
  return 1;
756
470
}
757
758
1.07k
static inline zend_long safe_shift_left(zend_long n, zend_long s) {
759
1.07k
  return (zend_long) ((zend_ulong) n << (zend_ulong) s);
760
1.07k
}
761
762
446
static inline bool shift_left_overflows(zend_long n, zend_long s) {
763
  /* This considers shifts that shift in the sign bit to be overflowing as well */
764
446
  if (n >= 0) {
765
324
    return s >= SIZEOF_ZEND_LONG * 8 - 1 || safe_shift_left(n, s) < n;
766
324
  } else {
767
122
    return s >= SIZEOF_ZEND_LONG * 8 || safe_shift_left(n, s) > n;
768
122
  }
769
446
}
770
771
/* If b does not divide a exactly, return the two adjacent values between which the real result
772
 * lies. */
773
1.01k
static void float_div(zend_long a, zend_long b, zend_long *r1, zend_long *r2) {
774
1.01k
  *r1 = *r2 = a / b;
775
1.01k
  if (a % b != 0) {
776
876
    if (*r2 < 0) {
777
380
      (*r2)--;
778
496
    } else {
779
496
      (*r2)++;
780
496
    }
781
876
  }
782
1.01k
}
783
784
static bool zend_inference_calc_binary_op_range(
785
    const zend_op_array *op_array, const zend_ssa *ssa,
786
121k
    const zend_op *opline, const zend_ssa_op *ssa_op, uint8_t opcode, zend_ssa_range *tmp) {
787
121k
  zend_long op1_min, op2_min, op1_max, op2_max, t1, t2, t3, t4;
788
789
121k
  switch (opcode) {
790
43.2k
    case ZEND_ADD:
791
43.2k
      if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) {
792
27.8k
        op1_min = OP1_MIN_RANGE();
793
27.8k
        op2_min = OP2_MIN_RANGE();
794
27.8k
        op1_max = OP1_MAX_RANGE();
795
27.8k
        op2_max = OP2_MAX_RANGE();
796
27.8k
        if (OP1_RANGE_UNDERFLOW() ||
797
5.61k
          OP2_RANGE_UNDERFLOW() ||
798
25.6k
          zend_add_will_overflow(op1_min, op2_min)) {
799
25.6k
          tmp->underflow = 1;
800
25.6k
          tmp->min = ZEND_LONG_MIN;
801
25.6k
        } else {
802
2.15k
          tmp->min = op1_min + op2_min;
803
2.15k
        }
804
27.8k
        if (OP1_RANGE_OVERFLOW() ||
805
7.93k
          OP2_RANGE_OVERFLOW() ||
806
25.9k
          zend_add_will_overflow(op1_max, op2_max)) {
807
25.9k
          tmp->overflow = 1;
808
25.9k
          tmp->max = ZEND_LONG_MAX;
809
25.9k
        } else {
810
1.87k
          tmp->max = op1_max + op2_max;
811
1.87k
        }
812
27.8k
        return 1;
813
27.8k
      }
814
15.4k
      break;
815
21.5k
    case ZEND_SUB:
816
21.5k
      if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) {
817
17.5k
        op1_min = OP1_MIN_RANGE();
818
17.5k
        op2_min = OP2_MIN_RANGE();
819
17.5k
        op1_max = OP1_MAX_RANGE();
820
17.5k
        op2_max = OP2_MAX_RANGE();
821
17.5k
        if (OP1_RANGE_UNDERFLOW() ||
822
7.21k
          OP2_RANGE_OVERFLOW() ||
823
12.9k
          zend_sub_will_overflow(op1_min, op2_max)) {
824
12.9k
          tmp->underflow = 1;
825
12.9k
          tmp->min = ZEND_LONG_MIN;
826
12.9k
        } else {
827
4.66k
          tmp->min = op1_min - op2_max;
828
4.66k
        }
829
17.5k
        if (OP1_RANGE_OVERFLOW() ||
830
7.07k
          OP2_RANGE_UNDERFLOW() ||
831
12.4k
          zend_sub_will_overflow(op1_max, op2_min)) {
832
12.4k
          tmp->overflow = 1;
833
12.4k
          tmp->max = ZEND_LONG_MAX;
834
12.4k
        } else {
835
5.11k
          tmp->max = op1_max - op2_min;
836
5.11k
        }
837
17.5k
        return 1;
838
17.5k
      }
839
3.99k
      break;
840
13.7k
    case ZEND_MUL:
841
13.7k
      if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) {
842
9.23k
        double dummy;
843
9.23k
        zend_long t1_overflow, t2_overflow, t3_overflow, t4_overflow;
844
9.23k
        op1_min = OP1_MIN_RANGE();
845
9.23k
        op2_min = OP2_MIN_RANGE();
846
9.23k
        op1_max = OP1_MAX_RANGE();
847
9.23k
        op2_max = OP2_MAX_RANGE();
848
        /* Suppress uninit variable warnings, these will only be used if the overflow
849
         * flags are all false. */
850
9.23k
        t1 = t2 = t3 = t4 = 0;
851
9.23k
        ZEND_SIGNED_MULTIPLY_LONG(op1_min, op2_min, t1, dummy, t1_overflow);
852
9.23k
        ZEND_SIGNED_MULTIPLY_LONG(op1_min, op2_max, t2, dummy, t2_overflow);
853
9.23k
        ZEND_SIGNED_MULTIPLY_LONG(op1_max, op2_min, t3, dummy, t3_overflow);
854
9.23k
        ZEND_SIGNED_MULTIPLY_LONG(op1_max, op2_max, t4, dummy, t4_overflow);
855
9.23k
        (void) dummy;
856
857
        // FIXME: more careful overflow checks?
858
9.23k
        if (OP1_RANGE_UNDERFLOW() || OP2_RANGE_UNDERFLOW() ||
859
866
          OP1_RANGE_OVERFLOW() || OP2_RANGE_OVERFLOW()  ||
860
857
          t1_overflow || t2_overflow || t3_overflow || t4_overflow
861
9.23k
        ) {
862
8.71k
          tmp->underflow = 1;
863
8.71k
          tmp->overflow = 1;
864
8.71k
          tmp->min = ZEND_LONG_MIN;
865
8.71k
          tmp->max = ZEND_LONG_MAX;
866
8.71k
        } else {
867
528
          tmp->min = MIN(MIN(t1, t2), MIN(t3, t4));
868
528
          tmp->max = MAX(MAX(t1, t2), MAX(t3, t4));
869
528
        }
870
9.23k
        return 1;
871
9.23k
      }
872
4.55k
      break;
873
6.50k
    case ZEND_DIV:
874
6.50k
      if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) {
875
4.05k
        op1_min = OP1_MIN_RANGE();
876
4.05k
        op2_min = OP2_MIN_RANGE();
877
4.05k
        op1_max = OP1_MAX_RANGE();
878
4.05k
        op2_max = OP2_MAX_RANGE();
879
880
        /* If op2 crosses zero, then floating point values close to zero might be
881
         * possible, which will result in arbitrarily large results (overflow). Also
882
         * avoid dividing LONG_MIN by -1, which is UB. */
883
4.05k
        if (OP1_RANGE_UNDERFLOW() || OP2_RANGE_UNDERFLOW() ||
884
303
          OP1_RANGE_OVERFLOW() || OP2_RANGE_OVERFLOW() ||
885
293
          (op2_min <= 0 && op2_max >= 0) ||
886
253
          (op1_min == ZEND_LONG_MIN && op2_max == -1)
887
4.05k
        ) {
888
3.80k
          tmp->underflow = 1;
889
3.80k
          tmp->overflow = 1;
890
3.80k
          tmp->min = ZEND_LONG_MIN;
891
3.80k
          tmp->max = ZEND_LONG_MAX;
892
3.80k
        } else {
893
253
          zend_long t1_, t2_, t3_, t4_;
894
253
          float_div(op1_min, op2_min, &t1, &t1_);
895
253
          float_div(op1_min, op2_max, &t2, &t2_);
896
253
          float_div(op1_max, op2_min, &t3, &t3_);
897
253
          float_div(op1_max, op2_max, &t4, &t4_);
898
899
253
          tmp->min = MIN(MIN(MIN(t1, t2), MIN(t3, t4)), MIN(MIN(t1_, t2_), MIN(t3_, t4_)));
900
253
          tmp->max = MAX(MAX(MAX(t1, t2), MAX(t3, t4)), MAX(MAX(t1_, t2_), MAX(t3_, t4_)));
901
253
        }
902
4.05k
        return 1;
903
4.05k
      }
904
2.45k
      break;
905
4.49k
    case ZEND_MOD:
906
4.49k
      if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) {
907
2.14k
        if (OP1_RANGE_UNDERFLOW() ||
908
830
          OP2_RANGE_UNDERFLOW() ||
909
480
          OP1_RANGE_OVERFLOW()  ||
910
1.67k
          OP2_RANGE_OVERFLOW()) {
911
1.67k
          tmp->min = ZEND_LONG_MIN;
912
1.67k
          tmp->max = ZEND_LONG_MAX;
913
1.67k
        } else {
914
470
          zend_long op2_abs_min, op2_abs_max;
915
916
470
          op1_min = OP1_MIN_RANGE();
917
470
          op2_min = OP2_MIN_RANGE();
918
470
          op1_max = OP1_MAX_RANGE();
919
470
          op2_max = OP2_MAX_RANGE();
920
470
          if (!zend_abs_range(op2_min, op2_max, &op2_abs_min, &op2_abs_max)) {
921
47
            break;
922
47
          }
923
924
423
          if (op2_abs_max == 0) {
925
            /* Always modulus by zero, nothing we can do */
926
110
            break;
927
110
          }
928
313
          if (op2_abs_min == 0) {
929
            /* Ignore the modulus by zero case, which will throw */
930
0
            op2_abs_min++;
931
0
          }
932
933
313
          if (op1_min >= 0) {
934
43
            tmp->min = op1_max < op2_abs_min ? op1_min : 0;
935
43
            tmp->max = MIN(op1_max, op2_abs_max - 1);
936
270
          } else if (op1_max <= 0) {
937
0
            tmp->min = MAX(op1_min, -op2_abs_max + 1);
938
0
            tmp->max = op1_min > -op2_abs_min ? op1_max : 0;
939
270
          } else {
940
270
            tmp->min = MAX(op1_min, -op2_abs_max + 1);
941
270
            tmp->max = MIN(op1_max, op2_abs_max - 1);
942
270
          }
943
313
        }
944
1.98k
        return 1;
945
2.14k
      }
946
2.35k
      break;
947
2.53k
    case ZEND_SL:
948
2.53k
      if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) {
949
1.10k
        if (OP1_RANGE_UNDERFLOW() ||
950
924
          OP2_RANGE_UNDERFLOW() ||
951
306
          OP1_RANGE_OVERFLOW() ||
952
824
          OP2_RANGE_OVERFLOW()) {
953
824
          tmp->min = ZEND_LONG_MIN;
954
824
          tmp->max = ZEND_LONG_MAX;
955
824
        } else {
956
278
          op1_min = OP1_MIN_RANGE();
957
278
          op2_min = OP2_MIN_RANGE();
958
278
          op1_max = OP1_MAX_RANGE();
959
278
          op2_max = OP2_MAX_RANGE();
960
961
          /* Shifts by negative numbers will throw, ignore them */
962
278
          if (op2_min < 0) {
963
18
            op2_min = 0;
964
18
          }
965
278
          if (op2_max < 0) {
966
6
            op2_max = 0;
967
6
          }
968
969
278
          if (shift_left_overflows(op1_min, op2_max)
970
168
              || shift_left_overflows(op1_max, op2_max)) {
971
110
            tmp->min = ZEND_LONG_MIN;
972
110
            tmp->max = ZEND_LONG_MAX;
973
168
          } else {
974
168
            t1 = safe_shift_left(op1_min, op2_min);
975
168
            t2 = safe_shift_left(op1_min, op2_max);
976
168
            t3 = safe_shift_left(op1_max, op2_min);
977
168
            t4 = safe_shift_left(op1_max, op2_max);
978
168
            tmp->min = MIN(MIN(t1, t2), MIN(t3, t4));
979
168
            tmp->max = MAX(MAX(t1, t2), MAX(t3, t4));
980
168
          }
981
278
        }
982
1.10k
        return 1;
983
1.10k
      }
984
1.43k
      break;
985
1.70k
    case ZEND_SR:
986
1.70k
      if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) {
987
810
        if (OP1_RANGE_UNDERFLOW() ||
988
528
          OP2_RANGE_UNDERFLOW() ||
989
237
          OP1_RANGE_OVERFLOW() ||
990
630
          OP2_RANGE_OVERFLOW()) {
991
630
          tmp->min = ZEND_LONG_MIN;
992
630
          tmp->max = ZEND_LONG_MAX;
993
630
        } else {
994
180
          op1_min = OP1_MIN_RANGE();
995
180
          op2_min = OP2_MIN_RANGE();
996
180
          op1_max = OP1_MAX_RANGE();
997
180
          op2_max = OP2_MAX_RANGE();
998
999
          /* Shifts by negative numbers will throw, ignore them */
1000
180
          if (op2_min < 0) {
1001
108
            op2_min = 0;
1002
108
          }
1003
180
          if (op2_max < 0) {
1004
12
            op2_max = 0;
1005
12
          }
1006
1007
          /* Shifts by more than the integer size will be 0 or -1 */
1008
180
          if (op2_min >= SIZEOF_ZEND_LONG * 8) {
1009
22
            op2_min = SIZEOF_ZEND_LONG * 8 - 1;
1010
22
          }
1011
180
          if (op2_max >= SIZEOF_ZEND_LONG * 8) {
1012
34
            op2_max = SIZEOF_ZEND_LONG * 8 - 1;
1013
34
          }
1014
1015
180
          t1 = op1_min >> op2_min;
1016
180
          t2 = op1_min >> op2_max;
1017
180
          t3 = op1_max >> op2_min;
1018
180
          t4 = op1_max >> op2_max;
1019
180
          tmp->min = MIN(MIN(t1, t2), MIN(t3, t4));
1020
180
          tmp->max = MAX(MAX(t1, t2), MAX(t3, t4));
1021
180
        }
1022
810
        return 1;
1023
810
      }
1024
890
      break;
1025
2.68k
    case ZEND_BW_OR:
1026
2.68k
      if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) {
1027
1.97k
        if (OP1_RANGE_UNDERFLOW() ||
1028
556
          OP2_RANGE_UNDERFLOW() ||
1029
300
          OP1_RANGE_OVERFLOW() ||
1030
1.68k
          OP2_RANGE_OVERFLOW()) {
1031
1.68k
          tmp->min = ZEND_LONG_MIN;
1032
1.68k
          tmp->max = ZEND_LONG_MAX;
1033
1.68k
        } else {
1034
296
          op1_min = OP1_MIN_RANGE();
1035
296
          op2_min = OP2_MIN_RANGE();
1036
296
          op1_max = OP1_MAX_RANGE();
1037
296
          op2_max = OP2_MAX_RANGE();
1038
296
          zend_ssa_range_or(op1_min, op1_max, op2_min, op2_max, tmp);
1039
296
        }
1040
1.97k
        return 1;
1041
1.97k
      }
1042
708
      break;
1043
21.4k
    case ZEND_BW_AND:
1044
21.4k
      if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) {
1045
18.2k
        if (OP1_RANGE_UNDERFLOW() ||
1046
7.36k
          OP2_RANGE_UNDERFLOW() ||
1047
2.55k
          OP1_RANGE_OVERFLOW() ||
1048
15.6k
          OP2_RANGE_OVERFLOW()) {
1049
15.6k
          tmp->min = ZEND_LONG_MIN;
1050
15.6k
          tmp->max = ZEND_LONG_MAX;
1051
15.6k
        } else {
1052
2.54k
          op1_min = OP1_MIN_RANGE();
1053
2.54k
          op2_min = OP2_MIN_RANGE();
1054
2.54k
          op1_max = OP1_MAX_RANGE();
1055
2.54k
          op2_max = OP2_MAX_RANGE();
1056
2.54k
          zend_ssa_range_and(op1_min, op1_max, op2_min, op2_max, tmp);
1057
2.54k
        }
1058
18.2k
        return 1;
1059
18.2k
      }
1060
3.27k
      break;
1061
3.65k
    case ZEND_BW_XOR:
1062
      // TODO
1063
3.65k
      break;
1064
0
    default: ZEND_UNREACHABLE();
1065
121k
  }
1066
38.8k
  return 0;
1067
121k
}
1068
1069
static bool zend_inference_calc_range(const zend_op_array *op_array, const zend_ssa *ssa, int var, int widening, bool narrowing, zend_ssa_range *tmp)
1070
2.15M
{
1071
2.15M
  uint32_t line;
1072
2.15M
  const zend_op *opline;
1073
2.15M
  const zend_ssa_op *ssa_op;
1074
1075
2.15M
  if (ssa->vars[var].definition_phi) {
1076
438k
    const zend_ssa_phi *p = ssa->vars[var].definition_phi;
1077
1078
438k
    tmp->underflow = 0;
1079
438k
    tmp->min = ZEND_LONG_MAX;
1080
438k
    tmp->max = ZEND_LONG_MIN;
1081
438k
    tmp->overflow = 0;
1082
438k
    if (p->pi >= 0 && p->has_range_constraint) {
1083
53.1k
      const zend_ssa_range_constraint *constraint = &p->constraint.range;
1084
53.1k
      if (constraint->negative) {
1085
5.43k
        int src1 = p->sources[0];
1086
1087
5.43k
        if (ssa->var_info[src1].has_range) {
1088
4.93k
          *tmp = ssa->var_info[src1].range;
1089
4.93k
          if (constraint->range.min == constraint->range.max
1090
4.93k
           && !constraint->range.underflow
1091
4.93k
           && !constraint->range.overflow
1092
4.93k
           && p->constraint.range.min_ssa_var < 0
1093
712
           && p->constraint.range.max_ssa_var < 0
1094
712
           && ssa->vars[src1].definition >= 0) {
1095
            /* Check for constrained induction variable */
1096
143
            line = ssa->vars[src1].definition;
1097
143
            opline = op_array->opcodes + line;
1098
143
            switch (opline->opcode) {
1099
0
              case ZEND_PRE_DEC:
1100
54
              case ZEND_POST_DEC:
1101
54
                if (!tmp->underflow) {
1102
48
                  const zend_ssa_phi *p = ssa->vars[ssa->ops[line].op1_use].definition_phi;
1103
1104
48
                  if (p && p->pi < 0
1105
48
                   && ssa->cfg.blocks[p->block].predecessors_count == 2
1106
48
                   && p->sources[1] == var
1107
48
                   && ssa->var_info[p->sources[0]].has_range
1108
48
                   && ssa->var_info[p->sources[0]].range.min > constraint->range.max) {
1109
48
                    tmp->min = constraint->range.max + 1;
1110
48
                  }
1111
48
                }
1112
54
                break;
1113
0
              case ZEND_PRE_INC:
1114
6
              case ZEND_POST_INC:
1115
6
                if (!tmp->overflow) {
1116
0
                  const zend_ssa_phi *p = ssa->vars[ssa->ops[line].op1_use].definition_phi;
1117
1118
0
                  if (p && p->pi < 0
1119
0
                   && ssa->cfg.blocks[p->block].predecessors_count == 2
1120
0
                   && p->sources[1] == var
1121
0
                   && ssa->var_info[p->sources[0]].has_range
1122
0
                   && ssa->var_info[p->sources[0]].range.max < constraint->range.min) {
1123
0
                    tmp->max = constraint->range.min - 1;
1124
0
                  }
1125
0
                }
1126
6
                break;
1127
143
            }
1128
143
          }
1129
4.93k
        } else if (narrowing) {
1130
454
          tmp->underflow = 1;
1131
454
          tmp->min = ZEND_LONG_MIN;
1132
454
          tmp->max = ZEND_LONG_MAX;
1133
454
          tmp->overflow = 1;
1134
454
        }
1135
1136
#ifdef NEG_RANGE
1137
        if (constraint->min_ssa_var < 0 &&
1138
            constraint->max_ssa_var < 0 &&
1139
            ssa->var_info[p->ssa_var].has_range) {
1140
          LOG_NEG_RANGE("%s() #%d [%ld..%ld] -> [%ld..%ld]?\n",
1141
            ZSTR_VAL(op_array->function_name),
1142
            p->ssa_var,
1143
            ssa->var_info[p->ssa_var].range.min,
1144
            ssa->var_info[p->ssa_var].range.max,
1145
            tmp->min,
1146
            tmp->max);
1147
          if (constraint->negative == NEG_USE_LT &&
1148
              tmp->max >= constraint->range.min) {
1149
            tmp->overflow = 0;
1150
            tmp->max = constraint->range.min - 1;
1151
            LOG_NEG_RANGE("  => [%ld..%ld]\n", tmp->min, tmp->max);
1152
          } else if (constraint->negative == NEG_USE_GT &&
1153
                     tmp->min <= constraint->range.max) {
1154
            tmp->underflow = 0;
1155
            tmp->min = constraint->range.max + 1;
1156
            LOG_NEG_RANGE("  => [%ld..%ld]\n", tmp->min, tmp->max);
1157
          }
1158
        }
1159
#endif
1160
47.7k
      } else if (ssa->var_info[p->sources[0]].has_range) {
1161
        /* intersection */
1162
47.3k
        *tmp = ssa->var_info[p->sources[0]].range;
1163
47.3k
        if (constraint->min_ssa_var < 0) {
1164
38.2k
          tmp->underflow = constraint->range.underflow && tmp->underflow;
1165
38.2k
          tmp->min = MAX(constraint->range.min, tmp->min);
1166
38.2k
#ifdef SYM_RANGE
1167
38.2k
        } else if (narrowing && ssa->var_info[constraint->min_ssa_var].has_range) {
1168
2.67k
          tmp->underflow = ssa->var_info[constraint->min_ssa_var].range.underflow && tmp->underflow;
1169
2.67k
          if (!add_will_overflow(ssa->var_info[constraint->min_ssa_var].range.min, constraint->range.min)) {
1170
2.65k
            tmp->min = MAX(ssa->var_info[constraint->min_ssa_var].range.min + constraint->range.min, tmp->min);
1171
2.65k
          }
1172
2.67k
#endif
1173
2.67k
        }
1174
47.3k
        if (constraint->max_ssa_var < 0) {
1175
35.5k
          tmp->max = MIN(constraint->range.max, tmp->max);
1176
35.5k
          tmp->overflow = constraint->range.overflow && tmp->overflow;
1177
35.5k
#ifdef SYM_RANGE
1178
35.5k
        } else if (narrowing && ssa->var_info[constraint->max_ssa_var].has_range) {
1179
2.81k
          if (!add_will_overflow(ssa->var_info[constraint->max_ssa_var].range.max, constraint->range.max)) {
1180
2.79k
            tmp->max = MIN(ssa->var_info[constraint->max_ssa_var].range.max + constraint->range.max, tmp->max);
1181
2.79k
          }
1182
2.81k
          tmp->overflow = ssa->var_info[constraint->max_ssa_var].range.overflow && tmp->overflow;
1183
2.81k
#endif
1184
2.81k
        }
1185
47.3k
      } else if (narrowing) {
1186
369
        if (constraint->min_ssa_var < 0) {
1187
365
          tmp->underflow = constraint->range.underflow;
1188
365
          tmp->min = constraint->range.min;
1189
365
#ifdef SYM_RANGE
1190
365
        } else if (narrowing && ssa->var_info[constraint->min_ssa_var].has_range) {
1191
0
          if (add_will_overflow(ssa->var_info[constraint->min_ssa_var].range.min, constraint->range.min)) {
1192
0
            tmp->underflow = 1;
1193
0
            tmp->min = ZEND_LONG_MIN;
1194
0
          } else {
1195
0
            tmp->underflow = ssa->var_info[constraint->min_ssa_var].range.underflow;
1196
0
            tmp->min = ssa->var_info[constraint->min_ssa_var].range.min + constraint->range.min;
1197
0
          }
1198
0
#endif
1199
4
        } else {
1200
4
          tmp->underflow = 1;
1201
4
          tmp->min = ZEND_LONG_MIN;
1202
4
        }
1203
369
        if (constraint->max_ssa_var < 0) {
1204
365
          tmp->max = constraint->range.max;
1205
365
          tmp->overflow = constraint->range.overflow;
1206
365
#ifdef SYM_RANGE
1207
365
        } else if (narrowing && ssa->var_info[constraint->max_ssa_var].has_range) {
1208
0
          if (add_will_overflow(ssa->var_info[constraint->max_ssa_var].range.max, constraint->range.max)) {
1209
0
            tmp->overflow = 1;
1210
0
            tmp->max = ZEND_LONG_MAX;
1211
0
          } else {
1212
0
            tmp->max = ssa->var_info[constraint->max_ssa_var].range.max + constraint->range.max;
1213
0
            tmp->overflow = ssa->var_info[constraint->max_ssa_var].range.overflow;
1214
0
          }
1215
0
#endif
1216
4
        } else {
1217
4
          tmp->max = ZEND_LONG_MAX;
1218
4
          tmp->overflow = 1;
1219
4
        }
1220
369
      }
1221
384k
    } else {
1222
1.16M
      for (uint32_t i = 0; i < ssa->cfg.blocks[p->block].predecessors_count; i++) {
1223
777k
        ZEND_ASSERT(p->sources[i] >= 0);
1224
777k
        if (ssa->var_info[p->sources[i]].has_range) {
1225
          /* union */
1226
661k
          tmp->underflow |= ssa->var_info[p->sources[i]].range.underflow;
1227
661k
          tmp->min = MIN(tmp->min, ssa->var_info[p->sources[i]].range.min);
1228
661k
          tmp->max = MAX(tmp->max, ssa->var_info[p->sources[i]].range.max);
1229
661k
          tmp->overflow |= ssa->var_info[p->sources[i]].range.overflow;
1230
661k
        } else if (narrowing) {
1231
33.6k
          tmp->underflow = 1;
1232
33.6k
          tmp->min = ZEND_LONG_MIN;
1233
33.6k
          tmp->max = ZEND_LONG_MAX;
1234
33.6k
          tmp->overflow = 1;
1235
33.6k
        }
1236
777k
      }
1237
384k
    }
1238
438k
    return (tmp->min <= tmp->max);
1239
1.71M
  } else if (ssa->vars[var].definition < 0) {
1240
17.6k
    return 0;
1241
17.6k
  }
1242
1.69M
  line = ssa->vars[var].definition;
1243
1.69M
  opline = op_array->opcodes + line;
1244
1.69M
  ssa_op = &ssa->ops[line];
1245
1246
1.69M
  return zend_inference_propagate_range(op_array, ssa, opline, ssa_op, var, tmp);
1247
2.15M
}
1248
1249
ZEND_API bool zend_inference_propagate_range(const zend_op_array *op_array, const zend_ssa *ssa, const zend_op *opline, const zend_ssa_op* ssa_op, int var, zend_ssa_range *tmp)
1250
1.69M
{
1251
1.69M
  tmp->underflow = 0;
1252
1.69M
  tmp->overflow = 0;
1253
1.69M
  switch (opline->opcode) {
1254
32.4k
    case ZEND_ADD:
1255
50.8k
    case ZEND_SUB:
1256
62.1k
    case ZEND_MUL:
1257
68.4k
    case ZEND_DIV:
1258
72.4k
    case ZEND_MOD:
1259
75.0k
    case ZEND_SL:
1260
76.7k
    case ZEND_SR:
1261
78.5k
    case ZEND_BW_OR:
1262
82.4k
    case ZEND_BW_AND:
1263
86.0k
    case ZEND_BW_XOR:
1264
86.0k
      if (ssa_op->result_def == var) {
1265
86.0k
        return zend_inference_calc_binary_op_range(
1266
86.0k
          op_array, ssa, opline, ssa_op, opline->opcode, tmp);
1267
86.0k
      }
1268
0
      break;
1269
1270
22.3k
    case ZEND_BW_NOT:
1271
22.3k
      if (ssa_op->result_def == var) {
1272
22.3k
        if (OP1_HAS_RANGE()) {
1273
21.5k
          if (OP1_RANGE_UNDERFLOW() ||
1274
20.0k
              OP1_RANGE_OVERFLOW()) {
1275
1.46k
            tmp->min = ZEND_LONG_MIN;
1276
1.46k
            tmp->max = ZEND_LONG_MAX;
1277
20.0k
          } else {
1278
20.0k
            zend_long op1_min = OP1_MIN_RANGE();
1279
20.0k
            zend_long op1_max = OP1_MAX_RANGE();
1280
20.0k
            tmp->min = ~op1_max;
1281
20.0k
            tmp->max = ~op1_min;
1282
20.0k
          }
1283
21.5k
          return 1;
1284
21.5k
        }
1285
22.3k
      }
1286
763
      break;
1287
3.38k
    case ZEND_CAST:
1288
3.38k
      if (ssa_op->op1_def == var) {
1289
0
        if (ssa_op->op1_def >= 0) {
1290
0
          if (OP1_HAS_RANGE()) {
1291
0
            tmp->underflow = OP1_RANGE_UNDERFLOW();
1292
0
            tmp->min = OP1_MIN_RANGE();
1293
0
            tmp->max = OP1_MAX_RANGE();
1294
0
            tmp->overflow  = OP1_RANGE_OVERFLOW();
1295
0
            return 1;
1296
0
          }
1297
0
        }
1298
3.38k
      } else if (ssa_op->result_def == var) {
1299
3.38k
        if (opline->extended_value == IS_LONG) {
1300
1.26k
          if (OP1_HAS_RANGE()) {
1301
1.08k
            tmp->min = OP1_MIN_RANGE();
1302
1.08k
            tmp->max = OP1_MAX_RANGE();
1303
1.08k
            return 1;
1304
1.08k
          } else {
1305
183
            tmp->min = ZEND_LONG_MIN;
1306
183
            tmp->max = ZEND_LONG_MAX;
1307
183
            return 1;
1308
183
          }
1309
1.26k
        }
1310
3.38k
      }
1311
2.11k
      break;
1312
15.2k
    case ZEND_QM_ASSIGN:
1313
18.0k
    case ZEND_JMP_SET:
1314
22.4k
    case ZEND_COALESCE:
1315
24.7k
    case ZEND_COPY_TMP:
1316
24.7k
      if (ssa_op->op1_def == var) {
1317
0
        if (ssa_op->op1_def >= 0) {
1318
0
          if (OP1_HAS_RANGE()) {
1319
0
            tmp->underflow = OP1_RANGE_UNDERFLOW();
1320
0
            tmp->min = OP1_MIN_RANGE();
1321
0
            tmp->max = OP1_MAX_RANGE();
1322
0
            tmp->overflow  = OP1_RANGE_OVERFLOW();
1323
0
            return 1;
1324
0
          }
1325
0
        }
1326
0
      }
1327
24.7k
      if (ssa_op->result_def == var) {
1328
24.7k
        if (OP1_HAS_RANGE()) {
1329
17.7k
          tmp->min = OP1_MIN_RANGE();
1330
17.7k
          tmp->max = OP1_MAX_RANGE();
1331
17.7k
          tmp->underflow = OP1_RANGE_UNDERFLOW();
1332
17.7k
          tmp->overflow  = OP1_RANGE_OVERFLOW();
1333
17.7k
          return 1;
1334
17.7k
        }
1335
24.7k
      }
1336
7.04k
      break;
1337
7.04k
    case ZEND_SEND_VAR:
1338
0
      if (ssa_op->op1_def == var) {
1339
0
        if (ssa_op->op1_def >= 0) {
1340
0
          if (OP1_HAS_RANGE()) {
1341
0
            tmp->underflow = OP1_RANGE_UNDERFLOW();
1342
0
            tmp->min = OP1_MIN_RANGE();
1343
0
            tmp->max = OP1_MAX_RANGE();
1344
0
            tmp->overflow  = OP1_RANGE_OVERFLOW();
1345
0
            return 1;
1346
0
          }
1347
0
        }
1348
0
      }
1349
0
      break;
1350
31.7k
    case ZEND_PRE_INC:
1351
31.7k
      if (ssa_op->op1_def == var || ssa_op->result_def == var) {
1352
31.7k
        if (OP1_HAS_RANGE()) {
1353
31.2k
          tmp->min = OP1_MIN_RANGE();
1354
31.2k
          tmp->max = OP1_MAX_RANGE();
1355
31.2k
          tmp->underflow = OP1_RANGE_UNDERFLOW();
1356
31.2k
          tmp->overflow = OP1_RANGE_OVERFLOW();
1357
31.2k
          if (tmp->max < ZEND_LONG_MAX) {
1358
26.5k
            tmp->max++;
1359
26.5k
          } else {
1360
4.76k
            tmp->overflow = 1;
1361
4.76k
          }
1362
31.2k
          if (tmp->min < ZEND_LONG_MAX && !tmp->underflow) {
1363
25.2k
            tmp->min++;
1364
25.2k
          }
1365
31.2k
          return 1;
1366
31.2k
        }
1367
31.7k
      }
1368
489
      break;
1369
5.19k
    case ZEND_PRE_DEC:
1370
5.19k
      if (ssa_op->op1_def == var || ssa_op->result_def == var) {
1371
5.19k
        if (OP1_HAS_RANGE()) {
1372
4.71k
          tmp->min = OP1_MIN_RANGE();
1373
4.71k
          tmp->max = OP1_MAX_RANGE();
1374
4.71k
          tmp->underflow = OP1_RANGE_UNDERFLOW();
1375
4.71k
          tmp->overflow = OP1_RANGE_OVERFLOW();
1376
4.71k
          if (tmp->min > ZEND_LONG_MIN) {
1377
908
            tmp->min--;
1378
3.81k
          } else {
1379
3.81k
            tmp->underflow = 1;
1380
3.81k
          }
1381
4.71k
          if (tmp->max > ZEND_LONG_MIN && !tmp->overflow) {
1382
2.22k
            tmp->max--;
1383
2.22k
          }
1384
4.71k
          return 1;
1385
4.71k
        }
1386
5.19k
      }
1387
472
      break;
1388
8.12k
    case ZEND_POST_INC:
1389
8.12k
      if (ssa_op->op1_def == var || ssa_op->result_def == var) {
1390
8.12k
        if (OP1_HAS_RANGE()) {
1391
7.83k
          tmp->min = OP1_MIN_RANGE();
1392
7.83k
          tmp->max = OP1_MAX_RANGE();
1393
7.83k
          tmp->underflow = OP1_RANGE_UNDERFLOW();
1394
7.83k
          tmp->overflow = OP1_RANGE_OVERFLOW();
1395
7.83k
          if (ssa_op->result_def == var) {
1396
1.30k
            return 1;
1397
1.30k
          }
1398
6.53k
          if (tmp->max < ZEND_LONG_MAX) {
1399
4.64k
            tmp->max++;
1400
4.64k
          } else {
1401
1.89k
            tmp->overflow = 1;
1402
1.89k
          }
1403
6.53k
          if (tmp->min < ZEND_LONG_MAX && !tmp->underflow) {
1404
5.52k
            tmp->min++;
1405
5.52k
          }
1406
6.53k
          return 1;
1407
7.83k
        }
1408
8.12k
      }
1409
287
      break;
1410
8.19k
    case ZEND_POST_DEC:
1411
8.19k
      if (ssa_op->op1_def == var || ssa_op->result_def == var) {
1412
8.19k
        if (OP1_HAS_RANGE()) {
1413
6.92k
          tmp->min = OP1_MIN_RANGE();
1414
6.92k
          tmp->max = OP1_MAX_RANGE();
1415
6.92k
          tmp->underflow = OP1_RANGE_UNDERFLOW();
1416
6.92k
          tmp->overflow = OP1_RANGE_OVERFLOW();
1417
6.92k
          if (ssa_op->result_def == var) {
1418
3.10k
            return 1;
1419
3.10k
          }
1420
3.81k
          if (tmp->min > ZEND_LONG_MIN) {
1421
320
            tmp->min--;
1422
3.49k
          } else {
1423
3.49k
            tmp->underflow = 1;
1424
3.49k
          }
1425
3.81k
          if (tmp->max > ZEND_LONG_MIN && !tmp->overflow) {
1426
914
            tmp->max--;
1427
914
          }
1428
3.81k
          return 1;
1429
6.92k
        }
1430
8.19k
      }
1431
1.27k
      break;
1432
3.08k
    case ZEND_UNSET_DIM:
1433
3.14k
    case ZEND_UNSET_OBJ:
1434
3.14k
      if (ssa_op->op1_def == var) {
1435
        /* If op1 is scalar, UNSET_DIM and UNSET_OBJ have no effect, so we can keep
1436
         * the previous ranges. */
1437
3.14k
        if (OP1_HAS_RANGE()) {
1438
2.66k
          tmp->min = OP1_MIN_RANGE();
1439
2.66k
          tmp->max = OP1_MAX_RANGE();
1440
2.66k
          tmp->underflow = OP1_RANGE_UNDERFLOW();
1441
2.66k
          tmp->overflow  = OP1_RANGE_OVERFLOW();
1442
2.66k
          return 1;
1443
2.66k
        }
1444
3.14k
      }
1445
483
      break;
1446
86.2k
    case ZEND_ASSIGN:
1447
86.2k
      if (ssa_op->op1_def == var || ssa_op->op2_def == var || ssa_op->result_def == var) {
1448
86.2k
        if (OP2_HAS_RANGE()) {
1449
74.2k
          tmp->min = OP2_MIN_RANGE();
1450
74.2k
          tmp->max = OP2_MAX_RANGE();
1451
74.2k
          tmp->underflow = OP2_RANGE_UNDERFLOW();
1452
74.2k
          tmp->overflow  = OP2_RANGE_OVERFLOW();
1453
74.2k
          return 1;
1454
74.2k
        }
1455
86.2k
      }
1456
11.9k
      break;
1457
78.1k
    case ZEND_ASSIGN_DIM:
1458
84.8k
    case ZEND_ASSIGN_OBJ:
1459
85.4k
    case ZEND_ASSIGN_STATIC_PROP:
1460
92.6k
    case ZEND_ASSIGN_DIM_OP:
1461
93.5k
    case ZEND_ASSIGN_OBJ_OP:
1462
93.5k
    case ZEND_ASSIGN_STATIC_PROP_OP:
1463
93.5k
      if ((ssa_op+1)->op1_def == var) {
1464
0
        opline++;
1465
0
        ssa_op++;
1466
0
        if (OP1_HAS_RANGE()) {
1467
0
          tmp->min = OP1_MIN_RANGE();
1468
0
          tmp->max = OP1_MAX_RANGE();
1469
0
          tmp->underflow = OP1_RANGE_UNDERFLOW();
1470
0
          tmp->overflow  = OP1_RANGE_OVERFLOW();
1471
0
        }
1472
0
        return 1;
1473
0
      }
1474
93.5k
      break;
1475
93.5k
    case ZEND_ASSIGN_OP:
1476
45.0k
      if (opline->extended_value != ZEND_CONCAT
1477
35.5k
       && opline->extended_value != ZEND_POW) {
1478
35.5k
        if (ssa_op->op1_def == var || ssa_op->result_def == var) {
1479
35.5k
          return zend_inference_calc_binary_op_range(
1480
35.5k
            op_array, ssa, opline, ssa_op,
1481
35.5k
            opline->extended_value, tmp);
1482
35.5k
        }
1483
35.5k
      }
1484
9.49k
      break;
1485
9.49k
    case ZEND_OP_DATA:
1486
8
      if (ssa_op->op1_def == var) {
1487
8
        if ((opline-1)->opcode == ZEND_ASSIGN_DIM ||
1488
8
            (opline-1)->opcode == ZEND_ASSIGN_OBJ ||
1489
8
            (opline-1)->opcode == ZEND_ASSIGN_STATIC_PROP ||
1490
8
            (opline-1)->opcode == ZEND_ASSIGN_DIM_OP ||
1491
8
            (opline-1)->opcode == ZEND_ASSIGN_OBJ_OP ||
1492
8
            (opline-1)->opcode == ZEND_ASSIGN_STATIC_PROP_OP) {
1493
0
          if (OP1_HAS_RANGE()) {
1494
0
            tmp->min = OP1_MIN_RANGE();
1495
0
            tmp->max = OP1_MAX_RANGE();
1496
0
            tmp->underflow = OP1_RANGE_UNDERFLOW();
1497
0
            tmp->overflow  = OP1_RANGE_OVERFLOW();
1498
0
            return 1;
1499
0
          }
1500
0
        }
1501
8
        break;
1502
8
      }
1503
0
      break;
1504
17.1k
    case ZEND_RECV:
1505
19.0k
    case ZEND_RECV_INIT:
1506
19.0k
      if (ssa_op->result_def == var) {
1507
19.0k
        if (op_array->arg_info &&
1508
19.0k
            opline->op1.num <= op_array->num_args) {
1509
19.0k
          zend_type type = op_array->arg_info[opline->op1.num-1].type;
1510
19.0k
          uint32_t mask = ZEND_TYPE_PURE_MASK_WITHOUT_NULL(type);
1511
19.0k
          if (mask == MAY_BE_LONG) {
1512
1.79k
            tmp->underflow = 0;
1513
1.79k
            tmp->min = ZEND_LONG_MIN;
1514
1.79k
            tmp->max = ZEND_LONG_MAX;
1515
1.79k
            tmp->overflow = 0;
1516
1.79k
            return 1;
1517
1.79k
          }
1518
19.0k
        }
1519
19.0k
      }
1520
17.2k
      break;
1521
17.2k
    case ZEND_STRLEN:
1522
2.05k
      if (ssa_op->result_def == var) {
1523
#if SIZEOF_ZEND_LONG == 4
1524
        /* The length of a string is a non-negative integer. However, on 32-bit
1525
         * platforms overflows into negative lengths may occur, so it's better
1526
         * to not assume any particular range. */
1527
        tmp->min = ZEND_LONG_MIN;
1528
#else
1529
2.05k
        tmp->min = 0;
1530
2.05k
#endif
1531
2.05k
        tmp->max = ZEND_LONG_MAX;
1532
2.05k
        return 1;
1533
2.05k
      }
1534
0
      break;
1535
186
    case ZEND_FUNC_NUM_ARGS:
1536
186
      tmp->min = 0;
1537
186
      tmp->max = ZEND_LONG_MAX;
1538
186
      return 1;
1539
1.39k
    case ZEND_COUNT:
1540
      /* count() on Countable objects may return negative numbers */
1541
1.39k
      tmp->min = ZEND_LONG_MIN;
1542
1.39k
      tmp->max = ZEND_LONG_MAX;
1543
1.39k
      return 1;
1544
47.4k
    case ZEND_DO_FCALL:
1545
47.4k
    case ZEND_DO_ICALL:
1546
52.2k
    case ZEND_DO_UCALL:
1547
52.2k
    case ZEND_DO_FCALL_BY_NAME:
1548
52.2k
      if (ssa_op->result_def == var) {
1549
52.2k
        const zend_func_info *func_info = ZEND_FUNC_INFO(op_array);
1550
52.2k
        const zend_call_info *call_info;
1551
52.2k
        if (!func_info || !func_info->call_map) {
1552
6.81k
          break;
1553
6.81k
        }
1554
1555
45.4k
        call_info = func_info->call_map[opline - op_array->opcodes];
1556
45.4k
        if (!call_info || call_info->is_prototype) {
1557
14.4k
          break;
1558
14.4k
        }
1559
30.9k
        if (call_info->callee_func->type == ZEND_USER_FUNCTION) {
1560
9.86k
          func_info = ZEND_FUNC_INFO(&call_info->callee_func->op_array);
1561
9.86k
          if (func_info && func_info->return_info.has_range) {
1562
428
            *tmp = func_info->return_info.range;
1563
428
            return 1;
1564
428
          }
1565
9.86k
        }
1566
//TODO: we can't use type inference for internal functions at this point ???
1567
#if 0
1568
          uint32_t type;
1569
1570
          type = zend_get_func_info(call_info, ssa);
1571
          if (!(type & (MAY_BE_ANY - (MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG)))) {
1572
            tmp->underflow = 0;
1573
            tmp->min = 0;
1574
            tmp->max = 0;
1575
            tmp->overflow = 0;
1576
            if (type & MAY_BE_LONG) {
1577
              tmp->min = ZEND_LONG_MIN;
1578
              tmp->max = ZEND_LONG_MAX;
1579
            } else if (type & MAY_BE_TRUE) {
1580
              if (!(type & (MAY_BE_NULL|MAY_BE_FALSE))) {
1581
                tmp->min = 1;
1582
              }
1583
              tmp->max = 1;
1584
            }
1585
            return 1;
1586
          }
1587
#endif
1588
30.9k
      }
1589
30.5k
      break;
1590
    // FIXME: support for more opcodes
1591
1.20M
    default:
1592
1.20M
      break;
1593
1.69M
  }
1594
1.40M
  return 0;
1595
1.69M
}
1596
1597
static void zend_inference_init_range(const zend_op_array *op_array, const zend_ssa *ssa, int var, bool underflow, zend_long min, zend_long max, bool overflow)
1598
1.08M
{
1599
1.08M
  if (underflow) {
1600
1.03M
    min = ZEND_LONG_MIN;
1601
1.03M
  }
1602
1.08M
  if (overflow) {
1603
1.03M
    max = ZEND_LONG_MAX;
1604
1.03M
  }
1605
1.08M
  ssa->var_info[var].has_range = 1;
1606
1.08M
  ssa->var_info[var].range.underflow = underflow;
1607
1.08M
  ssa->var_info[var].range.min = min;
1608
1.08M
  ssa->var_info[var].range.max = max;
1609
1.08M
  ssa->var_info[var].range.overflow = overflow;
1610
1.08M
  LOG_SSA_RANGE("  change range (init      SCC %2d) %2d [%s%ld..%ld%s]\n", ssa->vars[var].scc, var, (underflow?"-- ":""), min, max, (overflow?" ++":""));
1611
1.08M
}
1612
1613
static bool zend_inference_widening_meet(zend_ssa_var_info *var_info, zend_ssa_range *r)
1614
64.1k
{
1615
64.1k
  if (!var_info->has_range) {
1616
104
    var_info->has_range = 1;
1617
64.0k
  } else {
1618
64.0k
    if (r->underflow ||
1619
19.6k
        var_info->range.underflow ||
1620
45.9k
        r->min < var_info->range.min) {
1621
45.9k
      r->underflow = 1;
1622
45.9k
      r->min = ZEND_LONG_MIN;
1623
45.9k
    } else {
1624
18.1k
      r->min = var_info->range.min;
1625
18.1k
    }
1626
64.0k
    if (r->overflow ||
1627
18.6k
        var_info->range.overflow ||
1628
49.0k
        r->max > var_info->range.max) {
1629
49.0k
      r->overflow = 1;
1630
49.0k
      r->max = ZEND_LONG_MAX;
1631
49.0k
    } else {
1632
15.0k
      r->max = var_info->range.max;
1633
15.0k
    }
1634
64.0k
    if (var_info->range.min == r->min &&
1635
62.1k
        var_info->range.max == r->max &&
1636
57.1k
        var_info->range.underflow == r->underflow &&
1637
57.1k
        var_info->range.overflow == r->overflow) {
1638
57.1k
      return 0;
1639
57.1k
    }
1640
64.0k
  }
1641
7.02k
  var_info->range = *r;
1642
7.02k
  return 1;
1643
64.1k
}
1644
1645
static bool zend_ssa_range_widening(const zend_op_array *op_array, const zend_ssa *ssa, int var, int scc)
1646
181k
{
1647
181k
  zend_ssa_range tmp;
1648
1649
181k
  if (zend_inference_calc_range(op_array, ssa, var, 1, 0, &tmp)) {
1650
64.1k
    if (zend_inference_widening_meet(&ssa->var_info[var], &tmp)) {
1651
7.02k
      LOG_SSA_RANGE("  change range (widening  SCC %2d) %2d [%s%ld..%ld%s]\n", scc, var, (tmp.underflow?"-- ":""), tmp.min, tmp.max, (tmp.overflow?" ++":""));
1652
7.02k
      return 1;
1653
7.02k
    }
1654
64.1k
  }
1655
174k
  return 0;
1656
181k
}
1657
1658
static bool zend_inference_narrowing_meet(zend_ssa_var_info *var_info, zend_ssa_range *r)
1659
455k
{
1660
455k
  if (!var_info->has_range) {
1661
94.4k
    var_info->has_range = 1;
1662
361k
  } else {
1663
361k
    if (!r->underflow &&
1664
155k
        !var_info->range.underflow &&
1665
153k
        var_info->range.min < r->min) {
1666
245
      r->min = var_info->range.min;
1667
245
    }
1668
361k
    if (!r->overflow &&
1669
153k
        !var_info->range.overflow &&
1670
149k
        var_info->range.max > r->max) {
1671
149
      r->max = var_info->range.max;
1672
149
    }
1673
361k
    if (r->underflow) {
1674
205k
      r->min = ZEND_LONG_MIN;
1675
205k
    }
1676
361k
    if (r->overflow) {
1677
207k
      r->max = ZEND_LONG_MAX;
1678
207k
    }
1679
361k
    if (var_info->range.min == r->min &&
1680
345k
        var_info->range.max == r->max &&
1681
275k
        var_info->range.underflow == r->underflow &&
1682
273k
        var_info->range.overflow == r->overflow) {
1683
273k
      return 0;
1684
273k
    }
1685
361k
  }
1686
182k
  var_info->range = *r;
1687
182k
  return 1;
1688
455k
}
1689
1690
static bool zend_ssa_range_narrowing(const zend_op_array *op_array, const zend_ssa *ssa, int var, int scc)
1691
191k
{
1692
191k
  zend_ssa_range tmp;
1693
1694
191k
  if (zend_inference_calc_range(op_array, ssa, var, 0, 1, &tmp)) {
1695
126k
    if (zend_inference_narrowing_meet(&ssa->var_info[var], &tmp)) {
1696
57.2k
      LOG_SSA_RANGE("  change range (narrowing SCC %2d) %2d [%s%ld..%ld%s]\n", scc, var, (tmp.underflow?"-- ":""), tmp.min, tmp.max, (tmp.overflow?" ++":""));
1697
57.2k
      return 1;
1698
57.2k
    }
1699
126k
  }
1700
134k
  return 0;
1701
191k
}
1702
1703
#ifdef NEG_RANGE
1704
# define CHECK_INNER_CYCLE(var2) \
1705
  do { \
1706
    if (ssa->vars[var2].scc == ssa->vars[var].scc && \
1707
        !ssa->vars[var2].scc_entry && \
1708
        !zend_bitset_in(visited, var2) && \
1709
      zend_check_inner_cycles(op_array, ssa, worklist, visited, var2)) { \
1710
      return 1; \
1711
    } \
1712
  } while (0)
1713
1714
static bool zend_check_inner_cycles(const zend_op_array *op_array, zend_ssa *ssa, zend_bitset worklist, zend_bitset visited, int var)
1715
{
1716
  if (zend_bitset_in(worklist, var)) {
1717
    return 1;
1718
  }
1719
  zend_bitset_incl(worklist, var);
1720
  FOR_EACH_VAR_USAGE(var, CHECK_INNER_CYCLE);
1721
  zend_bitset_incl(visited, var);
1722
  return 0;
1723
}
1724
#endif
1725
1726
static void zend_infer_ranges_warmup(const zend_op_array *op_array, zend_ssa *ssa, const int *scc_var, const int *next_scc_var, int scc)
1727
23.6k
{
1728
23.6k
  int worklist_len = zend_bitset_len(ssa->vars_count);
1729
23.6k
  int j, n;
1730
23.6k
  zend_ssa_range tmp;
1731
23.6k
  ALLOCA_FLAG(use_heap)
1732
23.6k
  zend_bitset worklist = do_alloca(sizeof(zend_ulong) * worklist_len * 2, use_heap);
1733
23.6k
  zend_bitset visited = worklist + worklist_len;
1734
#ifdef NEG_RANGE
1735
  bool has_inner_cycles = false;
1736
1737
  memset(worklist, 0, sizeof(zend_ulong) * worklist_len);
1738
  memset(visited, 0, sizeof(zend_ulong) * worklist_len);
1739
  j = scc_var[scc];
1740
  while (j >= 0) {
1741
    if (!zend_bitset_in(visited, j) &&
1742
        zend_check_inner_cycles(op_array, ssa, worklist, visited, j)) {
1743
      has_inner_cycles = true;
1744
      break;
1745
    }
1746
    j = next_scc_var[j];
1747
  }
1748
#endif
1749
1750
23.6k
  memset(worklist, 0, sizeof(zend_ulong) * worklist_len);
1751
1752
401k
  for (n = 0; n < RANGE_WARMUP_PASSES; n++) {
1753
378k
    j= scc_var[scc];
1754
3.12M
    while (j >= 0) {
1755
2.74M
      if (ssa->vars[j].scc_entry
1756
1.02M
       && !(ssa->var_info[j].type & MAY_BE_REF)) {
1757
667k
        zend_bitset_incl(worklist, j);
1758
667k
      }
1759
2.74M
      j = next_scc_var[j];
1760
2.74M
    }
1761
1762
378k
    memset(visited, 0, sizeof(zend_ulong) * worklist_len);
1763
1764
11.5M
    WHILE_WORKLIST(worklist, worklist_len, j) {
1765
11.5M
      if (zend_inference_calc_range(op_array, ssa, j, 0, 0, &tmp)) {
1766
#ifdef NEG_RANGE
1767
        if (!has_inner_cycles &&
1768
            ssa->var_info[j].has_range &&
1769
            ssa->vars[j].definition_phi &&
1770
            ssa->vars[j].definition_phi->pi >= 0 &&
1771
          ssa->vars[j].definition_phi->has_range_constraint &&
1772
            ssa->vars[j].definition_phi->constraint.range.negative &&
1773
            ssa->vars[j].definition_phi->constraint.range.min_ssa_var < 0 &&
1774
            ssa->vars[j].definition_phi->constraint.range.max_ssa_var < 0) {
1775
          zend_ssa_range_constraint *constraint =
1776
            &ssa->vars[j].definition_phi->constraint.range;
1777
          if (tmp.min == ssa->var_info[j].range.min &&
1778
              tmp.max == ssa->var_info[j].range.max) {
1779
            if (constraint->negative == NEG_INIT) {
1780
              LOG_NEG_RANGE("#%d INVARIANT\n", j);
1781
              constraint->negative = NEG_INVARIANT;
1782
            }
1783
          } else if (tmp.min == ssa->var_info[j].range.min &&
1784
                     tmp.max == ssa->var_info[j].range.max + 1 &&
1785
                     tmp.max < constraint->range.min) {
1786
            if (constraint->negative == NEG_INIT ||
1787
                constraint->negative == NEG_INVARIANT) {
1788
              LOG_NEG_RANGE("#%d LT\n", j);
1789
              constraint->negative = NEG_USE_LT;
1790
//???NEG
1791
            } else if (constraint->negative == NEG_USE_GT) {
1792
              LOG_NEG_RANGE("#%d UNKNOWN\n", j);
1793
              constraint->negative = NEG_UNKNOWN;
1794
            }
1795
          } else if (tmp.max == ssa->var_info[j].range.max &&
1796
                       tmp.min == ssa->var_info[j].range.min - 1 &&
1797
                     tmp.min > constraint->range.max) {
1798
            if (constraint->negative == NEG_INIT ||
1799
                constraint->negative == NEG_INVARIANT) {
1800
              LOG_NEG_RANGE("#%d GT\n", j);
1801
              constraint->negative = NEG_USE_GT;
1802
//???NEG
1803
            } else if (constraint->negative == NEG_USE_LT) {
1804
              LOG_NEG_RANGE("#%d UNKNOWN\n", j);
1805
              constraint->negative = NEG_UNKNOWN;
1806
            }
1807
          } else {
1808
            LOG_NEG_RANGE("#%d UNKNOWN\n", j);
1809
            constraint->negative = NEG_UNKNOWN;
1810
          }
1811
        }
1812
#endif
1813
328k
        if (zend_inference_narrowing_meet(&ssa->var_info[j], &tmp)) {
1814
125k
          LOG_SSA_RANGE("  change range (warmup %2d SCC %2d) %2d [%s%ld..%ld%s]\n", n, scc, j, (tmp.underflow?"-- ":""), tmp.min, tmp.max, (tmp.overflow?" ++":""));
1815
125k
          zend_bitset_incl(visited, j);
1816
217k
          FOR_EACH_VAR_USAGE(j, ADD_SCC_VAR_1);
1817
125k
        }
1818
328k
      }
1819
11.5M
    } WHILE_WORKLIST_END();
1820
378k
  }
1821
23.6k
  free_alloca(worklist, use_heap);
1822
23.6k
}
1823
1824
static void zend_infer_ranges(const zend_op_array *op_array, zend_ssa *ssa) /* {{{ */
1825
89.1k
{
1826
89.1k
  int worklist_len = zend_bitset_len(ssa->vars_count);
1827
89.1k
  zend_bitset worklist;
1828
89.1k
  int *next_scc_var;
1829
89.1k
  int *scc_var;
1830
89.1k
  zend_ssa_phi *p;
1831
89.1k
  zend_ssa_range tmp;
1832
89.1k
  int scc, j;
1833
89.1k
  ALLOCA_FLAG(use_heap);
1834
1835
89.1k
  worklist = do_alloca(
1836
89.1k
    ZEND_MM_ALIGNED_SIZE(sizeof(zend_ulong) * worklist_len) +
1837
89.1k
    ZEND_MM_ALIGNED_SIZE(sizeof(int) * ssa->vars_count) +
1838
89.1k
    sizeof(int) * ssa->sccs, use_heap);
1839
89.1k
  next_scc_var = (int*)((char*)worklist + ZEND_MM_ALIGNED_SIZE(sizeof(zend_ulong) * worklist_len));
1840
89.1k
  scc_var = (int*)((char*)next_scc_var + ZEND_MM_ALIGNED_SIZE(sizeof(int) * ssa->vars_count));
1841
1842
89.1k
  LOG_SSA_RANGE("Range Inference\n");
1843
1844
  /* Create linked lists of SSA variables for each SCC */
1845
89.1k
  memset(scc_var, -1, sizeof(int) * ssa->sccs);
1846
1.57M
  for (j = 0; j < ssa->vars_count; j++) {
1847
1.48M
    if (ssa->vars[j].scc >= 0) {
1848
1.37M
      next_scc_var[j] = scc_var[ssa->vars[j].scc];
1849
1.37M
      scc_var[ssa->vars[j].scc] = j;
1850
1.37M
    }
1851
1.48M
  }
1852
1853
1.31M
  for (scc = 0; scc < ssa->sccs; scc++) {
1854
1.23M
    j = scc_var[scc];
1855
1.23M
    if (next_scc_var[j] < 0) {
1856
      /* SCC with a single element */
1857
1.20M
      if (ssa->var_info[j].type & MAY_BE_REF) {
1858
        /* pass */
1859
1.01M
      } else if (zend_inference_calc_range(op_array, ssa, j, 0, 1, &tmp)) {
1860
173k
        zend_inference_init_range(op_array, ssa, j, tmp.underflow, tmp.min, tmp.max, tmp.overflow);
1861
842k
      } else {
1862
842k
        zend_inference_init_range(op_array, ssa, j, true, ZEND_LONG_MIN, ZEND_LONG_MAX, true);
1863
842k
      }
1864
1.20M
    } else {
1865
      /* Find SCC entry points */
1866
23.6k
      memset(worklist, 0, sizeof(zend_ulong) * worklist_len);
1867
171k
      do {
1868
171k
        if (ssa->vars[j].scc_entry
1869
63.8k
         && !(ssa->var_info[j].type & MAY_BE_REF)) {
1870
41.6k
          zend_bitset_incl(worklist, j);
1871
41.6k
        }
1872
171k
        j = next_scc_var[j];
1873
171k
      } while (j >= 0);
1874
1875
23.6k
#if RANGE_WARMUP_PASSES > 0
1876
23.6k
      zend_infer_ranges_warmup(op_array, ssa, scc_var, next_scc_var, scc);
1877
23.6k
      j = scc_var[scc];
1878
171k
      do {
1879
171k
        if (!(ssa->var_info[j].type & MAY_BE_REF)) {
1880
111k
          zend_bitset_incl(worklist, j);
1881
111k
        }
1882
171k
        j = next_scc_var[j];
1883
171k
      } while (j >= 0);
1884
23.6k
#endif
1885
1886
      /* widening */
1887
886k
      WHILE_WORKLIST(worklist, worklist_len, j) {
1888
886k
        if (zend_ssa_range_widening(op_array, ssa, j, scc)) {
1889
11.5k
          FOR_EACH_VAR_USAGE(j, ADD_SCC_VAR);
1890
6.15k
        }
1891
886k
      } WHILE_WORKLIST_END();
1892
1893
      /* initialize missing ranges */
1894
195k
      for (j = scc_var[scc]; j >= 0; j = next_scc_var[j]) {
1895
171k
        if (!ssa->var_info[j].has_range
1896
128k
         && !(ssa->var_info[j].type & MAY_BE_REF)) {
1897
68.5k
          zend_inference_init_range(op_array, ssa, j, true, ZEND_LONG_MIN, ZEND_LONG_MAX,
1898
68.5k
                  true);
1899
84.2k
          FOR_EACH_VAR_USAGE(j, ADD_SCC_VAR);
1900
68.5k
        }
1901
171k
      }
1902
1903
      /* widening (second round) */
1904
453k
      WHILE_WORKLIST(worklist, worklist_len, j) {
1905
453k
        if (zend_ssa_range_widening(op_array, ssa, j, scc)) {
1906
1.73k
          FOR_EACH_VAR_USAGE(j, ADD_SCC_VAR);
1907
864
        }
1908
453k
      } WHILE_WORKLIST_END();
1909
1910
      /* Add all SCC entry variables into worklist for narrowing */
1911
195k
      for (j = scc_var[scc]; j >= 0; j = next_scc_var[j]) {
1912
171k
        if (ssa->vars[j].definition_phi
1913
68.6k
         && ssa->vars[j].definition_phi->pi < 0
1914
46.4k
         && !(ssa->var_info[j].type & MAY_BE_REF)) {
1915
          /* narrowing Phi functions first */
1916
17.4k
          zend_ssa_range_narrowing(op_array, ssa, j, scc);
1917
17.4k
        }
1918
171k
        zend_bitset_incl(worklist, j);
1919
171k
      }
1920
1921
      /* narrowing */
1922
1.37M
      WHILE_WORKLIST(worklist, worklist_len, j) {
1923
1.37M
        if (zend_ssa_range_narrowing(op_array, ssa, j, scc)) {
1924
126k
          FOR_EACH_VAR_USAGE(j, ADD_SCC_VAR);
1925
57.2k
#ifdef SYM_RANGE
1926
          /* Process symbolic control-flow constraints */
1927
57.2k
          p = ssa->vars[j].sym_use_chain;
1928
58.4k
          while (p) {
1929
1.22k
            ADD_SCC_VAR(p->ssa_var);
1930
1.22k
            p = p->sym_use_chain;
1931
1.22k
          }
1932
57.2k
#endif
1933
57.2k
        }
1934
1.37M
      } WHILE_WORKLIST_END();
1935
23.6k
    }
1936
1.23M
  }
1937
1938
89.1k
  free_alloca(worklist, use_heap);
1939
89.1k
}
1940
/* }}} */
1941
1942
0
static uint32_t get_ssa_alias_types(zend_ssa_alias_kind alias) {
1943
0
  if (alias == HTTP_RESPONSE_HEADER_ALIAS) {
1944
0
    return MAY_BE_ARRAY | MAY_BE_ARRAY_KEY_LONG | MAY_BE_ARRAY_OF_STRING | MAY_BE_RC1 | MAY_BE_RCN;
1945
0
  } else {
1946
0
    return MAY_BE_UNDEF | MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_REF | MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
1947
0
  }
1948
0
}
1949
1950
#define UPDATE_SSA_TYPE(_type, _var)                  \
1951
1.47M
  do {                               \
1952
1.47M
    uint32_t __type = (_type) & ~MAY_BE_GUARD;           \
1953
1.47M
    int __var = (_var);                       \
1954
1.47M
    if (__type & MAY_BE_REF) {                   \
1955
228k
      __type |= MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF; \
1956
228k
    }                                \
1957
1.47M
    if (__var >= 0) {                       \
1958
1.47M
      zend_ssa_var *__ssa_var = &ssa_vars[__var];         \
1959
1.47M
      if (__ssa_var->var < op_array->num_args) {         \
1960
43.6k
        if (__type & MAY_BE_RC1) {                              \
1961
38.0k
          /* TODO: may be captured by exception backtreace */ \
1962
38.0k
          __type |= MAY_BE_RCN;                               \
1963
38.0k
        }                                                       \
1964
43.6k
      }                                                           \
1965
1.47M
      if (__ssa_var->var < op_array->last_var) {         \
1966
423k
        if (__type & (MAY_BE_REF|MAY_BE_RCN)) {         \
1967
292k
          __type |= MAY_BE_RC1 | MAY_BE_RCN;         \
1968
292k
        }                            \
1969
423k
        if ((__type & MAY_BE_RC1) && (__type & MAY_BE_STRING)) {\
1970
271k
          /* TODO: support for array keys and ($str . "")*/   \
1971
271k
          __type |= MAY_BE_RCN;                               \
1972
271k
        }                                                       \
1973
423k
        if ((__type & MAY_BE_RC1) && (__type & MAY_BE_OBJECT)) {\
1974
279k
          /* TODO: object may be captured by magic handlers */\
1975
279k
          __type |= MAY_BE_RCN;                               \
1976
279k
        }                                                       \
1977
423k
        if (__ssa_var->alias) {                 \
1978
0
          __type |= get_ssa_alias_types(__ssa_var->alias);  \
1979
0
        }                            \
1980
423k
      }                              \
1981
1.47M
      if (ssa_var_info[__var].type != __type) {           \
1982
1.21M
        ZEND_ASSERT(ssa_opcodes != NULL ||           \
1983
1.21M
          __ssa_var->var >= op_array->last_var ||       \
1984
1.21M
          (ssa_var_info[__var].type & MAY_BE_REF)       \
1985
1.21M
            == (__type & MAY_BE_REF));            \
1986
1.21M
        if (ssa_var_info[__var].type & ~__type) {       \
1987
0
          emit_type_narrowing_warning(op_array, ssa, __var);  \
1988
0
          return FAILURE;                   \
1989
0
        }                            \
1990
1.21M
        ssa_var_info[__var].type = __type;            \
1991
1.21M
        if (update_worklist) {                   \
1992
1.21M
          add_usages(op_array, ssa, worklist, __var);     \
1993
1.21M
        }                            \
1994
1.21M
      }                              \
1995
1.47M
      /*zend_bitset_excl(worklist, var);*/            \
1996
1.47M
    }                                \
1997
1.47M
  } while (0)
1998
1999
#define UPDATE_SSA_OBJ_TYPE(_ce, _is_instanceof, var)           \
2000
511k
  do {                                                                \
2001
511k
    if (var >= 0) {                         \
2002
511k
      zend_class_entry *__ce = (_ce);               \
2003
511k
      bool __is_instanceof = (_is_instanceof);          \
2004
511k
      if (__ce && (__ce->ce_flags & ZEND_ACC_FINAL)) {     \
2005
13.5k
        __is_instanceof = false;                \
2006
13.5k
      }                              \
2007
511k
      if (ssa_var_info[var].ce != __ce ||             \
2008
511k
          ssa_var_info[var].is_instanceof != __is_instanceof) { \
2009
44.9k
        ssa_var_info[var].ce = __ce;              \
2010
44.9k
        ssa_var_info[var].is_instanceof = __is_instanceof;    \
2011
44.9k
        if (update_worklist) {                   \
2012
44.9k
          add_usages(op_array, ssa, worklist, var);     \
2013
44.9k
        }                            \
2014
44.9k
      }                              \
2015
511k
      /*zend_bitset_excl(worklist, var);*/            \
2016
511k
    }                               \
2017
511k
  } while (0)
2018
2019
215k
#define COPY_SSA_OBJ_TYPE(from_var, to_var) do { \
2020
215k
  if ((from_var) >= 0 && (ssa_var_info[(from_var)].type & MAY_BE_OBJECT) \
2021
215k
      && ssa_var_info[(from_var)].ce && !(ssa_var_info[(to_var)].type & MAY_BE_REF)) { \
2022
6.81k
    UPDATE_SSA_OBJ_TYPE(ssa_var_info[(from_var)].ce, \
2023
6.81k
      ssa_var_info[(from_var)].is_instanceof, (to_var)); \
2024
208k
  } else { \
2025
208k
    UPDATE_SSA_OBJ_TYPE(NULL, 0, (to_var)); \
2026
208k
  } \
2027
215k
} while (0)
2028
2029
static void add_usages(const zend_op_array *op_array, const zend_ssa *ssa, zend_bitset worklist, int var)
2030
1.25M
{
2031
1.25M
  if (ssa->vars[var].phi_use_chain) {
2032
209k
    const zend_ssa_phi *p = ssa->vars[var].phi_use_chain;
2033
254k
    do {
2034
254k
      zend_bitset_incl(worklist, p->ssa_var);
2035
254k
      p = zend_ssa_next_use_phi(ssa, var, p);
2036
254k
    } while (p);
2037
209k
  }
2038
1.25M
  if (ssa->vars[var].use_chain >= 0) {
2039
1.09M
    int use = ssa->vars[var].use_chain;
2040
1.09M
    const zend_ssa_op *op;
2041
2042
1.23M
    do {
2043
1.23M
      op = ssa->ops + use;
2044
1.23M
      if (op->result_def >= 0) {
2045
814k
        zend_bitset_incl(worklist, op->result_def);
2046
814k
      }
2047
1.23M
      if (op->op1_def >= 0) {
2048
153k
        zend_bitset_incl(worklist, op->op1_def);
2049
153k
      }
2050
1.23M
      if (op->op2_def >= 0) {
2051
12.4k
        zend_bitset_incl(worklist, op->op2_def);
2052
12.4k
      }
2053
1.23M
      if (op_array->opcodes[use].opcode == ZEND_OP_DATA) {
2054
18.4k
        op--;
2055
18.4k
        if (op->result_def >= 0) {
2056
4.83k
          zend_bitset_incl(worklist, op->result_def);
2057
4.83k
        }
2058
18.4k
        if (op->op1_def >= 0) {
2059
10.5k
          zend_bitset_incl(worklist, op->op1_def);
2060
10.5k
        }
2061
18.4k
        if (op->op2_def >= 0) {
2062
0
          zend_bitset_incl(worklist, op->op2_def);
2063
0
        }
2064
1.21M
      } else if (use + 1 < op_array->last
2065
1.19M
       && op_array->opcodes[use + 1].opcode == ZEND_OP_DATA) {
2066
19.6k
        op++;
2067
19.6k
        if (op->result_def >= 0) {
2068
0
          zend_bitset_incl(worklist, op->result_def);
2069
0
        }
2070
19.6k
        if (op->op1_def >= 0) {
2071
162
          zend_bitset_incl(worklist, op->op1_def);
2072
162
        }
2073
19.6k
        if (op->op2_def >= 0) {
2074
0
          zend_bitset_incl(worklist, op->op2_def);
2075
0
        }
2076
19.6k
      }
2077
1.23M
      use = zend_ssa_next_use(ssa->ops, var, use);
2078
1.23M
    } while (use >= 0);
2079
1.09M
  }
2080
1.25M
}
2081
2082
static void emit_type_narrowing_warning(const zend_op_array *op_array, const zend_ssa *ssa, int var)
2083
0
{
2084
0
  int def_op_num = ssa->vars[var].definition;
2085
0
  const zend_op *def_opline = def_op_num >= 0 ? &op_array->opcodes[def_op_num] : NULL;
2086
0
  const char *def_op_name = def_opline ? zend_get_opcode_name(def_opline->opcode) : "PHI";
2087
0
  uint32_t lineno = def_opline ? def_opline->lineno : 0;
2088
0
  zend_error_at(
2089
0
    E_WARNING, op_array->filename, lineno,
2090
0
    "Narrowing occurred during type inference of %s. Please file a bug report on https://github.com/php/php-src/issues", def_op_name);
2091
0
#if ZEND_DEBUG
2092
0
  ZEND_ASSERT(0 && "Narrowing during type inference");
2093
0
#endif
2094
0
}
2095
2096
ZEND_API uint32_t ZEND_FASTCALL zend_array_type_info(const zval *zv)
2097
21.8k
{
2098
21.8k
  HashTable *ht = Z_ARRVAL_P(zv);
2099
21.8k
  uint32_t tmp = MAY_BE_ARRAY;
2100
21.8k
  zend_string *str;
2101
21.8k
  zval *val;
2102
2103
21.8k
  if (Z_REFCOUNTED_P(zv)) {
2104
14.3k
    tmp |= MAY_BE_RC1 | MAY_BE_RCN;
2105
14.3k
  } else {
2106
7.50k
    tmp |= MAY_BE_RCN;
2107
7.50k
  }
2108
2109
21.8k
  if (zend_hash_num_elements(ht) == 0) {
2110
7.54k
    tmp |=  MAY_BE_ARRAY_EMPTY;
2111
14.3k
  } else if (HT_IS_PACKED(ht)) {
2112
10.7k
    tmp |= MAY_BE_ARRAY_PACKED;
2113
150k
    ZEND_HASH_PACKED_FOREACH_VAL(ht, val) {
2114
150k
      tmp |= 1 << (Z_TYPE_P(val) + MAY_BE_ARRAY_SHIFT);
2115
150k
    } ZEND_HASH_FOREACH_END();
2116
10.7k
  } else {
2117
23.7k
    ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(ht, str, val) {
2118
23.7k
      if (str) {
2119
5.87k
        tmp |= MAY_BE_ARRAY_STRING_HASH;
2120
5.87k
      } else {
2121
2.38k
        tmp |= MAY_BE_ARRAY_NUMERIC_HASH;
2122
2.38k
      }
2123
23.7k
      tmp |= 1 << (Z_TYPE_P(val) + MAY_BE_ARRAY_SHIFT);
2124
23.7k
    } ZEND_HASH_FOREACH_END();
2125
3.61k
  }
2126
21.8k
  return tmp;
2127
21.8k
}
2128
2129
2130
ZEND_API uint32_t zend_array_element_type(uint32_t t1, uint8_t op_type, bool write, bool insert)
2131
32.6k
{
2132
32.6k
  uint32_t tmp = 0;
2133
2134
32.6k
  if (t1 & MAY_BE_OBJECT) {
2135
24.0k
      if (!write) {
2136
      /* can't be REF  because of ZVAL_COPY_DEREF() usage */
2137
12.0k
      tmp |= MAY_BE_ANY | MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
2138
12.0k
    } else {
2139
12.0k
      tmp |= MAY_BE_ANY | MAY_BE_REF | MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
2140
12.0k
      }
2141
24.0k
    if (write) {
2142
12.0k
      tmp |= MAY_BE_INDIRECT;
2143
12.0k
    }
2144
24.0k
  }
2145
32.6k
  if (t1 & MAY_BE_ARRAY) {
2146
29.2k
    if (insert) {
2147
1.68k
      tmp |= MAY_BE_NULL;
2148
27.5k
    } else {
2149
27.5k
      tmp |= MAY_BE_NULL | ((t1 & MAY_BE_ARRAY_OF_ANY) >> MAY_BE_ARRAY_SHIFT);
2150
27.5k
      if (tmp & MAY_BE_ARRAY) {
2151
25.7k
        tmp |= MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
2152
25.7k
      }
2153
27.5k
      if (tmp & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)) {
2154
26.3k
        if (!write) {
2155
          /* can't be REF  because of ZVAL_COPY_DEREF() usage */
2156
14.1k
          tmp |= MAY_BE_RCN;
2157
14.1k
          if ((op_type & (IS_VAR|IS_TMP_VAR)) && (t1 & MAY_BE_RC1)) {
2158
3.92k
            tmp |= MAY_BE_RC1;
2159
3.92k
          }
2160
14.1k
        } else if (t1 & MAY_BE_ARRAY_OF_REF) {
2161
10.9k
          tmp |= MAY_BE_REF | MAY_BE_RC1 | MAY_BE_RCN;
2162
10.9k
        } else {
2163
1.31k
          tmp |= MAY_BE_RC1 | MAY_BE_RCN;
2164
1.31k
        }
2165
26.3k
      }
2166
27.5k
    }
2167
29.2k
    if (write) {
2168
14.3k
      tmp |= MAY_BE_INDIRECT;
2169
14.3k
    }
2170
29.2k
  }
2171
32.6k
  if (t1 & MAY_BE_STRING) {
2172
22.5k
    tmp |= MAY_BE_STRING | MAY_BE_RC1;
2173
22.5k
    if (write) {
2174
11.9k
      tmp |= MAY_BE_NULL;
2175
11.9k
    }
2176
22.5k
  }
2177
32.6k
  if (t1 & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE)) {
2178
27.8k
    tmp |= MAY_BE_NULL;
2179
27.8k
    if (write) {
2180
14.1k
      tmp |= MAY_BE_INDIRECT;
2181
14.1k
    }
2182
27.8k
  }
2183
32.6k
  if (t1 & (MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE|MAY_BE_RESOURCE)) {
2184
24.3k
    if (!write) {
2185
12.1k
      tmp |= MAY_BE_NULL;
2186
12.1k
    }
2187
24.3k
  }
2188
32.6k
  return tmp;
2189
32.6k
}
2190
2191
static uint32_t assign_dim_array_result_type(
2192
44.8k
    uint32_t arr_type, uint32_t dim_type, uint32_t value_type, uint8_t dim_op_type) {
2193
44.8k
  uint32_t tmp = 0;
2194
  /* Only add key type if we have a value type. We want to maintain the invariant that a
2195
   * key type exists iff a value type exists even in dead code that may use empty types. */
2196
44.8k
  if (value_type & (MAY_BE_ANY|MAY_BE_UNDEF)) {
2197
44.8k
    if (value_type & MAY_BE_UNDEF) {
2198
1.23k
      value_type |= MAY_BE_NULL;
2199
1.23k
    }
2200
44.8k
    if (dim_op_type == IS_UNUSED) {
2201
27.6k
      if (arr_type & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE)) {
2202
1.93k
        tmp |= MAY_BE_ARRAY_PACKED;
2203
1.93k
      }
2204
27.6k
      tmp |= MAY_BE_HASH_ONLY(arr_type) ? MAY_BE_ARRAY_NUMERIC_HASH : MAY_BE_ARRAY_KEY_LONG;
2205
27.6k
    } else {
2206
17.2k
      if (dim_type & (MAY_BE_LONG|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_RESOURCE|MAY_BE_DOUBLE)) {
2207
7.26k
        if (arr_type & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE)) {
2208
5.74k
          tmp |= MAY_BE_ARRAY_PACKED;
2209
5.74k
        }
2210
7.26k
        tmp |= MAY_BE_HASH_ONLY(arr_type) ? MAY_BE_ARRAY_NUMERIC_HASH : MAY_BE_ARRAY_KEY_LONG;
2211
7.26k
      }
2212
17.2k
      if (dim_type & MAY_BE_STRING) {
2213
7.64k
        tmp |= MAY_BE_ARRAY_KEY_STRING;
2214
7.64k
        if (dim_op_type != IS_CONST) {
2215
          // FIXME: numeric string
2216
4.22k
          if (arr_type & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE)) {
2217
3.56k
            tmp |= MAY_BE_ARRAY_PACKED;
2218
3.56k
          }
2219
4.22k
          tmp |= MAY_BE_HASH_ONLY(arr_type) ? MAY_BE_ARRAY_NUMERIC_HASH : MAY_BE_ARRAY_KEY_LONG;
2220
4.22k
        }
2221
7.64k
      }
2222
17.2k
      if (dim_type & (MAY_BE_UNDEF|MAY_BE_NULL)) {
2223
6.74k
        tmp |= MAY_BE_ARRAY_KEY_STRING;
2224
6.74k
      }
2225
17.2k
    }
2226
44.8k
  }
2227
  /* Only add value type if we have a key type. It might be that the key type is illegal
2228
   * for arrays. */
2229
44.8k
  if (tmp & MAY_BE_ARRAY_KEY_ANY) {
2230
44.8k
    tmp |= (value_type & MAY_BE_ANY) << MAY_BE_ARRAY_SHIFT;
2231
44.8k
  }
2232
44.8k
  tmp &= ~MAY_BE_ARRAY_EMPTY;
2233
44.8k
  return tmp;
2234
44.8k
}
2235
2236
static uint32_t assign_dim_result_type(
2237
17.7k
    uint32_t arr_type, uint32_t dim_type, uint32_t value_type, uint8_t dim_op_type) {
2238
17.7k
  uint32_t tmp = arr_type & ~(MAY_BE_RC1|MAY_BE_RCN);
2239
2240
17.7k
  if (arr_type & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE)) {
2241
11.7k
    tmp &= ~(MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE);
2242
11.7k
    tmp |= MAY_BE_ARRAY|MAY_BE_RC1;
2243
11.7k
  }
2244
17.7k
  if (tmp & (MAY_BE_ARRAY|MAY_BE_STRING)) {
2245
17.4k
    tmp |= MAY_BE_RC1;
2246
17.4k
  }
2247
17.7k
  if (tmp & (MAY_BE_OBJECT|MAY_BE_RESOURCE)) {
2248
9.12k
    tmp |= MAY_BE_RC1 | MAY_BE_RCN;
2249
9.12k
  }
2250
17.7k
  if (tmp & MAY_BE_ARRAY) {
2251
17.3k
    tmp |= assign_dim_array_result_type(arr_type, dim_type, value_type, dim_op_type);
2252
17.3k
  }
2253
17.7k
  return tmp;
2254
17.7k
}
2255
2256
/* For binary ops that have compound assignment operators */
2257
static uint32_t binary_op_result_type(
2258
    const zend_ssa *ssa, uint8_t opcode, uint32_t t1, uint32_t t2, int result_var,
2259
82.7k
    zend_long optimization_level) {
2260
82.7k
  uint32_t tmp = 0;
2261
82.7k
  uint32_t t1_type = (t1 & MAY_BE_ANY) | (t1 & MAY_BE_UNDEF ? MAY_BE_NULL : 0);
2262
82.7k
  uint32_t t2_type = (t2 & MAY_BE_ANY) | (t2 & MAY_BE_UNDEF ? MAY_BE_NULL : 0);
2263
2264
82.7k
  if (!(ZEND_OPTIMIZER_IGNORE_OVERLOADING & optimization_level)) {
2265
    /* Handle potentially overloaded operators.
2266
     * This could be made more precise by checking the class type, if known. */
2267
82.7k
    if ((t1_type & MAY_BE_OBJECT) || (t2_type & MAY_BE_OBJECT)) {
2268
      /* This is somewhat GMP specific. */
2269
33.7k
      tmp |= MAY_BE_OBJECT | MAY_BE_FALSE | MAY_BE_RC1;
2270
33.7k
    }
2271
82.7k
  }
2272
2273
82.7k
  switch (opcode) {
2274
16.8k
    case ZEND_ADD:
2275
16.8k
      if (t1_type == MAY_BE_LONG && t2_type == MAY_BE_LONG) {
2276
805
        if (result_var < 0 ||
2277
793
          !ssa->var_info[result_var].has_range ||
2278
791
            ssa->var_info[result_var].range.underflow ||
2279
546
            ssa->var_info[result_var].range.overflow) {
2280
          /* may overflow */
2281
440
          tmp |= MAY_BE_LONG | MAY_BE_DOUBLE;
2282
440
        } else {
2283
365
          tmp |= MAY_BE_LONG;
2284
365
        }
2285
16.0k
      } else if (t1_type == MAY_BE_DOUBLE || t2_type == MAY_BE_DOUBLE) {
2286
646
        tmp |= MAY_BE_DOUBLE;
2287
15.4k
      } else if (t1_type == MAY_BE_ARRAY && t2_type == MAY_BE_ARRAY) {
2288
64
        tmp |= MAY_BE_ARRAY | MAY_BE_RC1;
2289
64
        tmp |= t1 & (MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF);
2290
64
        tmp |= t2 & (MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF);
2291
15.3k
      } else {
2292
15.3k
        tmp |= MAY_BE_LONG | MAY_BE_DOUBLE;
2293
15.3k
        if ((t1_type & MAY_BE_ARRAY) && (t2_type & MAY_BE_ARRAY)) {
2294
2.09k
          tmp |= MAY_BE_ARRAY | MAY_BE_RC1;
2295
2.09k
          tmp |= t1 & (MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF);
2296
2.09k
          tmp |= t2 & (MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF);
2297
2.09k
        }
2298
15.3k
      }
2299
16.8k
      break;
2300
10.5k
    case ZEND_SUB:
2301
21.7k
    case ZEND_MUL:
2302
21.7k
      if (t1_type == MAY_BE_LONG && t2_type == MAY_BE_LONG) {
2303
2.26k
        if (result_var < 0 ||
2304
2.26k
          !ssa->var_info[result_var].has_range ||
2305
2.24k
            ssa->var_info[result_var].range.underflow ||
2306
1.53k
            ssa->var_info[result_var].range.overflow) {
2307
          /* may overflow */
2308
1.53k
          tmp |= MAY_BE_LONG | MAY_BE_DOUBLE;
2309
1.53k
        } else {
2310
723
          tmp |= MAY_BE_LONG;
2311
723
        }
2312
19.5k
      } else if (t1_type == MAY_BE_DOUBLE || t2_type == MAY_BE_DOUBLE) {
2313
439
        tmp |= MAY_BE_DOUBLE;
2314
19.0k
      } else {
2315
19.0k
        tmp |= MAY_BE_LONG | MAY_BE_DOUBLE;
2316
19.0k
      }
2317
21.7k
      break;
2318
5.58k
    case ZEND_DIV:
2319
6.14k
    case ZEND_POW:
2320
6.14k
      if (t1_type == MAY_BE_DOUBLE || t2_type == MAY_BE_DOUBLE) {
2321
52
        tmp |= MAY_BE_DOUBLE;
2322
6.09k
      } else {
2323
6.09k
        tmp |= MAY_BE_LONG | MAY_BE_DOUBLE;
2324
6.09k
      }
2325
      /* Division by zero results in Inf/-Inf/Nan (double), so it doesn't need any special
2326
       * handling */
2327
6.14k
      break;
2328
3.99k
    case ZEND_MOD:
2329
3.99k
      tmp |= MAY_BE_LONG;
2330
      /* Division by zero results in an exception, so it doesn't need any special handling */
2331
3.99k
      break;
2332
1.91k
    case ZEND_BW_OR:
2333
9.69k
    case ZEND_BW_AND:
2334
13.3k
    case ZEND_BW_XOR:
2335
13.3k
      if ((t1_type & MAY_BE_STRING) && (t2_type & MAY_BE_STRING)) {
2336
1.58k
        tmp |= MAY_BE_STRING | MAY_BE_RC1 | MAY_BE_RCN;
2337
1.58k
      }
2338
13.3k
      if ((t1_type & ~MAY_BE_STRING) || (t2_type & ~MAY_BE_STRING)) {
2339
12.9k
        tmp |= MAY_BE_LONG;
2340
12.9k
      }
2341
13.3k
      break;
2342
2.61k
    case ZEND_SL:
2343
4.60k
    case ZEND_SR:
2344
4.60k
      tmp |= MAY_BE_LONG;
2345
4.60k
      break;
2346
15.9k
    case ZEND_CONCAT:
2347
15.9k
    case ZEND_FAST_CONCAT:
2348
      /* TODO: +MAY_BE_OBJECT ??? */
2349
15.9k
      tmp = MAY_BE_STRING | MAY_BE_RC1 | MAY_BE_RCN;
2350
15.9k
      break;
2351
0
    default: ZEND_UNREACHABLE();
2352
82.7k
  }
2353
82.7k
  return tmp;
2354
82.7k
}
2355
2356
43.2k
static uint32_t zend_convert_type_declaration_mask(uint32_t type_mask) {
2357
43.2k
  uint32_t result_mask = type_mask & MAY_BE_ANY;
2358
43.2k
  if (type_mask & MAY_BE_VOID) {
2359
2.83k
    result_mask |= MAY_BE_NULL;
2360
2.83k
  }
2361
43.2k
  if (type_mask & MAY_BE_CALLABLE) {
2362
248
    result_mask |= MAY_BE_STRING|MAY_BE_OBJECT|MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF;
2363
248
  }
2364
43.2k
  if (type_mask & MAY_BE_STATIC) {
2365
214
    result_mask |= MAY_BE_OBJECT;
2366
214
  }
2367
43.2k
  if (type_mask & MAY_BE_ARRAY) {
2368
9.81k
    result_mask |= MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF;
2369
9.81k
  }
2370
43.2k
  return result_mask;
2371
43.2k
}
2372
2373
static uint32_t zend_convert_type(const zend_script *script, zend_type type, zend_class_entry **pce)
2374
72.4k
{
2375
72.4k
  if (pce) {
2376
72.3k
    *pce = NULL;
2377
72.3k
  }
2378
2379
72.4k
  if (!ZEND_TYPE_IS_SET(type)) {
2380
29.1k
    return MAY_BE_ANY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF|MAY_BE_RC1|MAY_BE_RCN;
2381
29.1k
  }
2382
2383
43.2k
  uint32_t tmp = zend_convert_type_declaration_mask(ZEND_TYPE_PURE_MASK(type));
2384
43.2k
  if (ZEND_TYPE_IS_COMPLEX(type)) {
2385
6.22k
    tmp |= MAY_BE_OBJECT;
2386
6.22k
    if (pce) {
2387
      /* As we only have space to store one CE,
2388
       * we use a plain object type for class unions. */
2389
6.22k
      if (ZEND_TYPE_HAS_NAME(type)) {
2390
5.22k
        zend_string *lcname = zend_string_tolower(ZEND_TYPE_NAME(type));
2391
        // TODO: Pass through op_array.
2392
5.22k
        *pce = zend_optimizer_get_class_entry(script, NULL, lcname);
2393
5.22k
        zend_string_release_ex(lcname, 0);
2394
5.22k
      }
2395
6.22k
    }
2396
6.22k
  }
2397
43.2k
  if (tmp & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)) {
2398
28.7k
    tmp |= MAY_BE_RC1 | MAY_BE_RCN;
2399
28.7k
  }
2400
43.2k
  return tmp;
2401
72.4k
}
2402
2403
ZEND_API uint32_t zend_fetch_arg_info_type(const zend_script *script, const zend_arg_info *arg_info, zend_class_entry **pce)
2404
64.9k
{
2405
64.9k
  return zend_convert_type(script, arg_info->type, pce);
2406
64.9k
}
2407
2408
9.24k
static const zend_property_info *lookup_prop_info(const zend_class_entry *ce, zend_string *name, zend_class_entry *scope) {
2409
9.24k
  const zend_property_info *prop_info;
2410
2411
  /* If the class is linked, reuse the precise runtime logic. */
2412
9.24k
  if ((ce->ce_flags & ZEND_ACC_LINKED)
2413
8.19k
   && (!scope || (scope->ce_flags & ZEND_ACC_LINKED))) {
2414
8.15k
    const zend_class_entry *prev_scope = EG(fake_scope);
2415
8.15k
    EG(fake_scope) = scope;
2416
8.15k
    prop_info = zend_get_property_info(ce, name, 1);
2417
8.15k
    EG(fake_scope) = prev_scope;
2418
8.15k
    if (prop_info && prop_info != ZEND_WRONG_PROPERTY_INFO) {
2419
6.61k
      return prop_info;
2420
6.61k
    }
2421
1.54k
    return NULL;
2422
8.15k
  }
2423
2424
  /* Otherwise, handle only some safe cases */
2425
1.09k
  prop_info = zend_hash_find_ptr(&ce->properties_info, name);
2426
1.09k
  if (prop_info &&
2427
837
    ((prop_info->ce == scope) ||
2428
38
     (!scope && (prop_info->flags & ZEND_ACC_PUBLIC)))
2429
1.09k
  ) {
2430
799
    return prop_info;
2431
799
  }
2432
292
  return NULL;
2433
1.09k
}
2434
2435
static const zend_property_info *zend_fetch_prop_info(const zend_op_array *op_array, const zend_ssa *ssa, const zend_op *opline, const zend_ssa_op *ssa_op)
2436
71.4k
{
2437
71.4k
  const zend_property_info *prop_info = NULL;
2438
71.4k
  if (opline->op2_type == IS_CONST) {
2439
69.2k
    const zend_class_entry *ce = NULL;
2440
2441
69.2k
    if (opline->op1_type == IS_UNUSED && !(op_array->fn_flags & ZEND_ACC_TRAIT_CLONE)) {
2442
5.82k
      ce = op_array->scope;
2443
63.4k
    } else if (ssa_op->op1_use >= 0) {
2444
63.4k
      ce = ssa->var_info[ssa_op->op1_use].ce;
2445
63.4k
    }
2446
69.2k
    if (ce) {
2447
6.67k
      prop_info = lookup_prop_info(ce,
2448
6.67k
        Z_STR_P(CRT_CONSTANT(opline->op2)),
2449
6.67k
        op_array->scope);
2450
6.67k
      if (prop_info && (prop_info->flags & ZEND_ACC_STATIC)) {
2451
26
        prop_info = NULL;
2452
26
      }
2453
6.67k
    }
2454
69.2k
  }
2455
71.4k
  return prop_info;
2456
71.4k
}
2457
2458
static const zend_property_info *zend_fetch_static_prop_info(const zend_script *script, const zend_op_array *op_array, const zend_ssa *ssa, const zend_op *opline)
2459
3.27k
{
2460
3.27k
  const zend_property_info *prop_info = NULL;
2461
3.27k
  if (opline->op1_type == IS_CONST) {
2462
2.99k
    const zend_class_entry *ce = NULL;
2463
2.99k
    if (opline->op2_type == IS_UNUSED) {
2464
1.07k
      uint32_t fetch_type = opline->op2.num & ZEND_FETCH_CLASS_MASK;
2465
1.07k
      switch (fetch_type) {
2466
946
        case ZEND_FETCH_CLASS_SELF:
2467
1.04k
        case ZEND_FETCH_CLASS_STATIC:
2468
          /* We enforce that static property types cannot change during inheritance, so
2469
           * handling static the same way as self here is legal. */
2470
1.04k
          ce = op_array->scope;
2471
1.04k
          break;
2472
26
        case ZEND_FETCH_CLASS_PARENT:
2473
26
          if (op_array->scope && (op_array->scope->ce_flags & ZEND_ACC_LINKED)) {
2474
20
            ce = op_array->scope->parent;
2475
20
          }
2476
26
          break;
2477
1.07k
      }
2478
1.92k
    } else if (opline->op2_type == IS_CONST) {
2479
1.77k
      const zval *zv = CRT_CONSTANT(opline->op2);
2480
1.77k
      ce = zend_optimizer_get_class_entry(script, op_array, Z_STR_P(zv + 1));
2481
1.77k
    }
2482
2483
2.99k
    if (ce) {
2484
2.56k
      const zval *zv = CRT_CONSTANT(opline->op1);
2485
2.56k
      prop_info = lookup_prop_info(ce, Z_STR_P(zv), op_array->scope);
2486
2.56k
      if (prop_info && !(prop_info->flags & ZEND_ACC_STATIC)) {
2487
64
        prop_info = NULL;
2488
64
      }
2489
2.56k
    }
2490
2.99k
  }
2491
3.27k
  return prop_info;
2492
3.27k
}
2493
2494
static uint32_t zend_fetch_prop_type(const zend_script *script, const zend_property_info *prop_info, zend_class_entry **pce)
2495
74.7k
{
2496
74.7k
  if (!prop_info) {
2497
67.4k
    if (pce) {
2498
66.6k
      *pce = NULL;
2499
66.6k
    }
2500
67.4k
    return MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF | MAY_BE_RC1 | MAY_BE_RCN;
2501
67.4k
  }
2502
2503
7.35k
  return zend_convert_type(script, prop_info->type, pce);
2504
74.7k
}
2505
2506
static bool result_may_be_separated(const zend_ssa *ssa, const zend_ssa_op *ssa_op)
2507
6.16k
{
2508
6.16k
  int tmp_var = ssa_op->result_def;
2509
2510
6.16k
  if (ssa->vars[tmp_var].use_chain >= 0
2511
6.16k
   && !ssa->vars[tmp_var].phi_use_chain) {
2512
6.16k
    const zend_ssa_op *use_op = &ssa->ops[ssa->vars[tmp_var].use_chain];
2513
2514
    /* TODO: analyze instructions between ssa_op and use_op */
2515
6.16k
    if (use_op == ssa_op + 1) {
2516
5.70k
      if ((use_op->op1_use == tmp_var && use_op->op1_use_chain < 0)
2517
5.68k
       || (use_op->op2_use == tmp_var && use_op->op2_use_chain < 0)) {
2518
5.68k
        return 0;
2519
5.68k
      }
2520
5.70k
    }
2521
6.16k
  }
2522
482
  return 1;
2523
6.16k
}
2524
2525
static zend_always_inline zend_result _zend_update_type_info(
2526
      const zend_op_array *op_array,
2527
      zend_ssa            *ssa,
2528
      const zend_script   *script,
2529
      zend_bitset          worklist,
2530
      const zend_op       *opline,
2531
      zend_ssa_op         *ssa_op,
2532
      const zend_op      **ssa_opcodes,
2533
      zend_long            optimization_level,
2534
      bool            update_worklist)
2535
1.16M
{
2536
1.16M
  uint32_t t1, t2;
2537
1.16M
  uint32_t tmp, orig;
2538
1.16M
  zend_ssa_var *ssa_vars = ssa->vars;
2539
1.16M
  zend_ssa_var_info *ssa_var_info = ssa->var_info;
2540
1.16M
  zend_class_entry *ce;
2541
1.16M
  int j;
2542
2543
1.16M
  if (opline->opcode == ZEND_OP_DATA) {
2544
392
    opline--;
2545
392
    ssa_op--;
2546
392
  }
2547
2548
1.16M
  t1 = OP1_INFO();
2549
1.16M
  t2 = OP2_INFO();
2550
2551
  /* If one of the operands cannot have any type, this means the operand derives from
2552
   * unreachable code. Propagate the empty result early, so that that the following
2553
   * code may assume that operands have at least one type. */
2554
1.16M
  if (!(t1 & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_CLASS))
2555
1.16M
   || !(t2 & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_CLASS))
2556
1.16M
   || (ssa_op->result_use >= 0 && !(RES_USE_INFO() & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_CLASS)))
2557
1.16M
   || ((opline->opcode == ZEND_ASSIGN_DIM_OP
2558
1.15M
     || opline->opcode == ZEND_ASSIGN_OBJ_OP
2559
1.15M
     || opline->opcode == ZEND_ASSIGN_STATIC_PROP_OP
2560
1.15M
     || opline->opcode == ZEND_ASSIGN_DIM
2561
1.14M
     || opline->opcode == ZEND_ASSIGN_OBJ)
2562
27.4k
      && !(OP1_DATA_INFO() & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_CLASS)) /*&& 0*/)) {
2563
3.80k
    tmp = 0;
2564
3.80k
    if (ssa_op->result_def >= 0 && !(ssa_var_info[ssa_op->result_def].type & MAY_BE_REF)) {
2565
2.95k
      UPDATE_SSA_TYPE(tmp, ssa_op->result_def);
2566
2.95k
    }
2567
3.80k
    if (ssa_op->op1_def >= 0 && !(ssa_var_info[ssa_op->op1_def].type & MAY_BE_REF)) {
2568
1.33k
      UPDATE_SSA_TYPE(tmp, ssa_op->op1_def);
2569
1.33k
    }
2570
3.80k
    if (ssa_op->op2_def >= 0 && !(ssa_var_info[ssa_op->op2_def].type & MAY_BE_REF)) {
2571
4
      UPDATE_SSA_TYPE(tmp, ssa_op->op2_def);
2572
4
    }
2573
3.80k
    if (opline->opcode == ZEND_ASSIGN_DIM_OP
2574
3.80k
     || opline->opcode == ZEND_ASSIGN_OBJ_OP
2575
3.79k
     || opline->opcode == ZEND_ASSIGN_STATIC_PROP_OP
2576
3.79k
     || opline->opcode == ZEND_ASSIGN_DIM
2577
3.38k
     || opline->opcode == ZEND_ASSIGN_OBJ) {
2578
663
      if ((ssa_op+1)->op1_def >= 0 && !(ssa_var_info[(ssa_op+1)->op1_def].type & MAY_BE_REF)) {
2579
0
        UPDATE_SSA_TYPE(tmp, (ssa_op+1)->op1_def);
2580
0
      }
2581
663
    }
2582
3.80k
    return SUCCESS;
2583
3.80k
  }
2584
2585
1.16M
  switch (opline->opcode) {
2586
12.8k
    case ZEND_ADD:
2587
22.5k
    case ZEND_SUB:
2588
30.8k
    case ZEND_MUL:
2589
36.1k
    case ZEND_DIV:
2590
36.6k
    case ZEND_POW:
2591
40.4k
    case ZEND_MOD:
2592
42.1k
    case ZEND_BW_OR:
2593
45.7k
    case ZEND_BW_AND:
2594
49.3k
    case ZEND_BW_XOR:
2595
51.9k
    case ZEND_SL:
2596
53.2k
    case ZEND_SR:
2597
65.0k
    case ZEND_CONCAT:
2598
65.0k
      tmp = binary_op_result_type(ssa, opline->opcode, t1, t2, ssa_op->result_def, optimization_level);
2599
65.0k
      UPDATE_SSA_TYPE(tmp, ssa_op->result_def);
2600
65.0k
      break;
2601
65.0k
    case ZEND_BW_NOT:
2602
20.8k
      tmp = 0;
2603
20.8k
      if (t1 & MAY_BE_STRING) {
2604
18.8k
        tmp |= MAY_BE_STRING | MAY_BE_RC1 | MAY_BE_RCN;
2605
18.8k
      }
2606
20.8k
      if (t1 & (MAY_BE_ANY-MAY_BE_STRING)) {
2607
20.4k
        tmp |= MAY_BE_LONG;
2608
20.4k
      }
2609
20.8k
      if (!(ZEND_OPTIMIZER_IGNORE_OVERLOADING & optimization_level)) {
2610
20.8k
        if (t1 & MAY_BE_OBJECT) {
2611
          /* Potentially overloaded operator. */
2612
17.8k
          tmp |= MAY_BE_OBJECT | MAY_BE_RC1;
2613
17.8k
        }
2614
20.8k
      }
2615
20.8k
      UPDATE_SSA_TYPE(tmp, ssa_op->result_def);
2616
20.8k
      break;
2617
74.0k
    case ZEND_BEGIN_SILENCE:
2618
74.0k
      UPDATE_SSA_TYPE(MAY_BE_LONG, ssa_op->result_def);
2619
74.0k
      break;
2620
74.0k
    case ZEND_BOOL_NOT:
2621
4.77k
    case ZEND_BOOL_XOR:
2622
7.47k
    case ZEND_IS_IDENTICAL:
2623
8.80k
    case ZEND_IS_NOT_IDENTICAL:
2624
13.6k
    case ZEND_IS_EQUAL:
2625
19.2k
    case ZEND_IS_NOT_EQUAL:
2626
32.9k
    case ZEND_IS_SMALLER:
2627
37.7k
    case ZEND_IS_SMALLER_OR_EQUAL:
2628
38.1k
    case ZEND_INSTANCEOF:
2629
39.2k
    case ZEND_JMPZ_EX:
2630
40.5k
    case ZEND_JMPNZ_EX:
2631
40.6k
    case ZEND_CASE:
2632
40.9k
    case ZEND_CASE_STRICT:
2633
42.3k
    case ZEND_BOOL:
2634
42.4k
    case ZEND_ISSET_ISEMPTY_CV:
2635
42.5k
    case ZEND_ISSET_ISEMPTY_VAR:
2636
44.6k
    case ZEND_ISSET_ISEMPTY_DIM_OBJ:
2637
45.7k
    case ZEND_ISSET_ISEMPTY_PROP_OBJ:
2638
45.9k
    case ZEND_ISSET_ISEMPTY_STATIC_PROP:
2639
46.1k
    case ZEND_ASSERT_CHECK:
2640
46.1k
    case ZEND_IN_ARRAY:
2641
46.2k
    case ZEND_ARRAY_KEY_EXISTS:
2642
46.2k
      UPDATE_SSA_TYPE(MAY_BE_FALSE|MAY_BE_TRUE, ssa_op->result_def);
2643
46.2k
      break;
2644
46.2k
    case ZEND_CAST:
2645
2.99k
      if (ssa_op->op1_def >= 0) {
2646
0
        tmp = t1;
2647
0
        if ((t1 & (MAY_BE_ARRAY|MAY_BE_OBJECT)) &&
2648
0
            (opline->extended_value == IS_ARRAY ||
2649
0
             opline->extended_value == IS_OBJECT)) {
2650
0
          tmp |= MAY_BE_RCN;
2651
0
        } else if ((t1 & MAY_BE_STRING) &&
2652
0
            opline->extended_value == IS_STRING) {
2653
0
          tmp |= MAY_BE_RCN;
2654
0
        }
2655
0
        UPDATE_SSA_TYPE(tmp, ssa_op->op1_def);
2656
0
        COPY_SSA_OBJ_TYPE(ssa_op->op1_use, ssa_op->op1_def);
2657
0
      }
2658
2.99k
      tmp = 1 << opline->extended_value;
2659
2.99k
      if (tmp & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)) {
2660
2.05k
        if ((tmp & MAY_BE_ANY) == (t1 & MAY_BE_ANY)) {
2661
75
          tmp |= (t1 & MAY_BE_RC1) | MAY_BE_RCN;
2662
1.98k
        } else if ((opline->extended_value == IS_ARRAY ||
2663
1.69k
              opline->extended_value == IS_OBJECT) &&
2664
798
               (t1 & (MAY_BE_ARRAY|MAY_BE_OBJECT))) {
2665
699
            tmp |= MAY_BE_RC1 | MAY_BE_RCN;
2666
1.28k
        } else if (opline->extended_value == IS_STRING &&
2667
1.18k
               (t1 & (MAY_BE_STRING|MAY_BE_OBJECT))) {
2668
896
          tmp |= MAY_BE_RC1 | MAY_BE_RCN;
2669
896
        } else {
2670
386
          tmp |= MAY_BE_RC1;
2671
386
          if (opline->extended_value == IS_ARRAY
2672
27
           && (t1 & (MAY_BE_UNDEF|MAY_BE_NULL))) {
2673
11
            tmp |= MAY_BE_RCN;
2674
11
          }
2675
386
        }
2676
2.05k
      }
2677
2.99k
      if (opline->extended_value == IS_ARRAY) {
2678
286
        if (t1 & (MAY_BE_UNDEF|MAY_BE_NULL)) {
2679
176
          tmp |= MAY_BE_ARRAY_EMPTY;
2680
176
        }
2681
286
        if (t1 & MAY_BE_ARRAY) {
2682
167
          tmp |= t1 & (MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF);
2683
167
        }
2684
286
        if (t1 & MAY_BE_OBJECT) {
2685
257
          tmp |= MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
2686
257
        } else if (t1 & (MAY_BE_ANY - MAY_BE_NULL)) {
2687
24
          tmp |= ((t1 & (MAY_BE_ANY - MAY_BE_NULL)) << MAY_BE_ARRAY_SHIFT) | ((t1 & MAY_BE_NULL) ? MAY_BE_ARRAY_KEY_LONG : MAY_BE_ARRAY_PACKED);
2688
24
        }
2689
286
      }
2690
2.99k
      UPDATE_SSA_TYPE(tmp, ssa_op->result_def);
2691
2.99k
      break;
2692
14.6k
    case ZEND_QM_ASSIGN:
2693
16.9k
    case ZEND_JMP_SET:
2694
21.4k
    case ZEND_COALESCE:
2695
23.7k
    case ZEND_COPY_TMP:
2696
23.7k
      if (ssa_op->op1_def >= 0) {
2697
0
        tmp = t1;
2698
0
        if (t1 & (MAY_BE_RC1|MAY_BE_REF)) {
2699
0
          tmp |= MAY_BE_RCN;
2700
0
        }
2701
0
        UPDATE_SSA_TYPE(tmp, ssa_op->op1_def);
2702
0
        COPY_SSA_OBJ_TYPE(ssa_op->op1_use, ssa_op->op1_def);
2703
0
      }
2704
23.7k
      tmp = t1 & ~MAY_BE_UNDEF;
2705
23.7k
      if (opline->opcode != ZEND_COPY_TMP || opline->op1_type != IS_VAR) {
2706
23.7k
        tmp &= ~MAY_BE_REF;
2707
23.7k
      }
2708
23.7k
      if (t1 & MAY_BE_UNDEF) {
2709
4.18k
        tmp |= MAY_BE_NULL;
2710
4.18k
      }
2711
23.7k
      if (t1 & (MAY_BE_RC1|MAY_BE_RCN)) {
2712
11.6k
        tmp |= (t1 & (MAY_BE_RC1|MAY_BE_RCN));
2713
11.6k
        if (opline->opcode == ZEND_COPY_TMP || opline->op1_type == IS_CV) {
2714
3.42k
          tmp |= MAY_BE_RCN;
2715
3.42k
        }
2716
11.6k
      }
2717
23.7k
      if (opline->opcode == ZEND_COALESCE || opline->opcode == ZEND_JMP_SET) {
2718
        /* COALESCE and JMP_SET result can't be null */
2719
6.81k
        tmp &= ~MAY_BE_NULL;
2720
6.81k
        if (opline->opcode == ZEND_JMP_SET) {
2721
          /* JMP_SET result can't be false either */
2722
2.30k
          tmp &= ~MAY_BE_FALSE;
2723
2.30k
        }
2724
6.81k
      }
2725
23.7k
      UPDATE_SSA_TYPE(tmp, ssa_op->result_def);
2726
23.7k
      COPY_SSA_OBJ_TYPE(ssa_op->op1_use, ssa_op->result_def);
2727
23.7k
      break;
2728
38.6k
    case ZEND_JMP_NULL:
2729
38.6k
    {
2730
38.6k
      uint32_t short_circuiting_type = opline->extended_value & ZEND_SHORT_CIRCUITING_CHAIN_MASK;
2731
38.6k
      if (short_circuiting_type == ZEND_SHORT_CIRCUITING_CHAIN_EXPR) {
2732
38.4k
        tmp = MAY_BE_NULL;
2733
38.4k
      } else if (short_circuiting_type == ZEND_SHORT_CIRCUITING_CHAIN_ISSET) {
2734
80
        tmp = MAY_BE_FALSE;
2735
80
      } else {
2736
80
        ZEND_ASSERT(short_circuiting_type == ZEND_SHORT_CIRCUITING_CHAIN_EMPTY);
2737
80
        tmp = MAY_BE_TRUE;
2738
80
      }
2739
38.6k
      UPDATE_SSA_TYPE(tmp, ssa_op->result_def);
2740
38.6k
      break;
2741
38.6k
    }
2742
38.6k
    case ZEND_ASSIGN_OP:
2743
16.8k
    case ZEND_ASSIGN_DIM_OP:
2744
17.6k
    case ZEND_ASSIGN_OBJ_OP:
2745
17.6k
    case ZEND_ASSIGN_STATIC_PROP_OP:
2746
17.6k
    {
2747
17.6k
      const zend_property_info *prop_info = NULL;
2748
17.6k
      orig = 0;
2749
17.6k
      tmp = 0;
2750
17.6k
      if (opline->opcode == ZEND_ASSIGN_OBJ_OP) {
2751
817
        prop_info = zend_fetch_prop_info(op_array, ssa, opline, ssa_op);
2752
817
        orig = t1;
2753
817
        t1 = zend_fetch_prop_type(script, prop_info, NULL);
2754
817
        t2 = OP1_DATA_INFO();
2755
16.8k
      } else if (opline->opcode == ZEND_ASSIGN_DIM_OP) {
2756
3.45k
        if (t1 & MAY_BE_ARRAY_OF_REF) {
2757
2.68k
              tmp |= MAY_BE_REF;
2758
2.68k
        }
2759
3.45k
        orig = t1;
2760
3.45k
        t1 = zend_array_element_type(t1, opline->op1_type, 1, 0);
2761
3.45k
        t2 = OP1_DATA_INFO();
2762
13.4k
      } else if (opline->opcode == ZEND_ASSIGN_STATIC_PROP_OP) {
2763
14
        prop_info = zend_fetch_static_prop_info(script, op_array, ssa, opline);
2764
14
        t1 = zend_fetch_prop_type(script, prop_info, NULL);
2765
14
        t2 = OP1_DATA_INFO();
2766
13.4k
      } else {
2767
13.4k
        if (t1 & MAY_BE_REF) {
2768
3.06k
              tmp |= MAY_BE_REF;
2769
3.06k
        }
2770
13.4k
      }
2771
2772
17.6k
      tmp |= binary_op_result_type(
2773
17.6k
        ssa, opline->extended_value, t1, t2,
2774
17.6k
        opline->opcode == ZEND_ASSIGN_OP ? ssa_op->op1_def : -1, optimization_level);
2775
17.6k
      if (tmp & (MAY_BE_STRING|MAY_BE_ARRAY)) {
2776
5.64k
        tmp |= MAY_BE_RC1 | MAY_BE_RCN;
2777
5.64k
      }
2778
17.6k
      if (tmp & (MAY_BE_OBJECT|MAY_BE_RESOURCE)) {
2779
6.20k
        tmp |= MAY_BE_RC1 | MAY_BE_RCN;
2780
6.20k
      }
2781
2782
17.6k
      if (opline->opcode == ZEND_ASSIGN_DIM_OP) {
2783
3.45k
        if (opline->op1_type == IS_CV) {
2784
3.20k
          orig = assign_dim_result_type(orig, OP2_INFO(), tmp, opline->op2_type);
2785
3.20k
          UPDATE_SSA_TYPE(orig, ssa_op->op1_def);
2786
3.20k
          COPY_SSA_OBJ_TYPE(ssa_op->op1_use, ssa_op->op1_def);
2787
3.20k
        }
2788
14.2k
      } else if (opline->opcode == ZEND_ASSIGN_OBJ_OP) {
2789
817
        if (opline->op1_type == IS_CV) {
2790
781
          orig = (orig & (MAY_BE_REF|MAY_BE_OBJECT))|MAY_BE_RC1|MAY_BE_RCN;
2791
781
          UPDATE_SSA_TYPE(orig, ssa_op->op1_def);
2792
781
          COPY_SSA_OBJ_TYPE(ssa_op->op1_use, ssa_op->op1_def);
2793
781
        }
2794
13.4k
      } else if (opline->opcode == ZEND_ASSIGN_STATIC_PROP_OP) {
2795
        /* Nothing to do */
2796
13.4k
      } else {
2797
13.4k
        if (opline->opcode == ZEND_ASSIGN_OP && ssa_op->result_def >= 0 && (tmp & MAY_BE_RC1)) {
2798
4.11k
          tmp |= MAY_BE_RCN;
2799
4.11k
        }
2800
13.4k
        UPDATE_SSA_TYPE(tmp, ssa_op->op1_def);
2801
13.4k
      }
2802
17.6k
      if (ssa_op->result_def >= 0) {
2803
10.1k
        ce = NULL;
2804
10.1k
        if (opline->opcode == ZEND_ASSIGN_DIM_OP) {
2805
1.83k
          if (opline->op2_type == IS_UNUSED) {
2806
            /* When appending to an array and the LONG_MAX key is already used
2807
             * null will be returned. */
2808
76
            tmp |= MAY_BE_NULL;
2809
76
          }
2810
1.83k
          if (t2 & (MAY_BE_ARRAY | MAY_BE_OBJECT)) {
2811
            /* Arrays and objects cannot be used as keys. */
2812
534
            tmp |= MAY_BE_NULL;
2813
534
          }
2814
1.83k
          if (t1 & (MAY_BE_ANY - (MAY_BE_NULL | MAY_BE_FALSE | MAY_BE_STRING | MAY_BE_ARRAY))) {
2815
            /* null and false are implicitly converted to array, anything else
2816
             * results in a null return value. */
2817
1.67k
            tmp |= MAY_BE_NULL;
2818
1.67k
          }
2819
1.83k
          if (tmp & MAY_BE_REF) {
2820
            /* Typed reference may cause auto conversion */
2821
1.65k
            tmp |= MAY_BE_ANY;
2822
1.65k
          }
2823
8.30k
        } else if (opline->opcode == ZEND_ASSIGN_OBJ_OP) {
2824
          /* The return value must also satisfy the property type */
2825
318
          if (prop_info) {
2826
20
            t1 = zend_fetch_prop_type(script, prop_info, &ce);
2827
20
            if ((t1 & (MAY_BE_LONG|MAY_BE_DOUBLE)) == MAY_BE_LONG
2828
14
             && (tmp & (MAY_BE_LONG|MAY_BE_DOUBLE)) == MAY_BE_DOUBLE) {
2829
              /* DOUBLE may be auto-converted to LONG */
2830
0
              tmp |= MAY_BE_LONG;
2831
0
              tmp &= ~MAY_BE_DOUBLE;
2832
20
            } else if ((t1 & (MAY_BE_LONG|MAY_BE_DOUBLE|MAY_BE_STRING)) == MAY_BE_STRING
2833
0
             && (tmp & (MAY_BE_LONG|MAY_BE_DOUBLE))) {
2834
              /* LONG/DOUBLE may be auto-converted to STRING */
2835
0
              tmp |= MAY_BE_STRING;
2836
0
              tmp &= ~(MAY_BE_LONG|MAY_BE_DOUBLE);
2837
0
            }
2838
20
            tmp &= t1;
2839
298
          } else {
2840
298
            tmp |= MAY_BE_LONG | MAY_BE_STRING;
2841
298
          }
2842
7.98k
        } else if (opline->opcode == ZEND_ASSIGN_STATIC_PROP_OP) {
2843
          /* The return value must also satisfy the property type */
2844
14
          if (prop_info) {
2845
12
            t1 = zend_fetch_prop_type(script, prop_info, &ce);
2846
12
            if ((t1 & (MAY_BE_LONG|MAY_BE_DOUBLE)) == MAY_BE_LONG
2847
0
             && (tmp & (MAY_BE_LONG|MAY_BE_DOUBLE)) == MAY_BE_DOUBLE) {
2848
              /* DOUBLE may be auto-converted to LONG */
2849
0
              tmp |= MAY_BE_LONG;
2850
0
              tmp &= ~MAY_BE_DOUBLE;
2851
12
            } else if ((t1 & (MAY_BE_LONG|MAY_BE_DOUBLE|MAY_BE_STRING)) == MAY_BE_STRING
2852
10
             && (tmp & (MAY_BE_LONG|MAY_BE_DOUBLE))) {
2853
              /* LONG/DOUBLE may be auto-converted to STRING */
2854
10
              tmp |= MAY_BE_STRING;
2855
10
              tmp &= ~(MAY_BE_LONG|MAY_BE_DOUBLE);
2856
10
            }
2857
12
            tmp &= t1;
2858
12
          } else {
2859
2
            tmp |= MAY_BE_LONG | MAY_BE_STRING;
2860
2
          }
2861
7.97k
        } else {
2862
7.97k
          if (tmp & MAY_BE_REF) {
2863
            /* Typed reference may cause auto conversion */
2864
1.80k
            tmp |= MAY_BE_ANY;
2865
1.80k
          }
2866
7.97k
        }
2867
10.1k
        tmp &= ~MAY_BE_REF;
2868
10.1k
        UPDATE_SSA_TYPE(tmp, ssa_op->result_def);
2869
10.1k
        if (ce) {
2870
0
          UPDATE_SSA_OBJ_TYPE(ce, 1, ssa_op->result_def);
2871
0
        }
2872
10.1k
      }
2873
17.6k
      break;
2874
17.6k
    }
2875
17.6k
    case ZEND_PRE_INC:
2876
12.3k
    case ZEND_PRE_DEC:
2877
12.3k
      tmp = 0;
2878
12.3k
      if (t1 & (MAY_BE_RC1|MAY_BE_RCN)) {
2879
3.65k
        tmp |= MAY_BE_RC1;
2880
3.65k
        if (ssa_op->result_def >= 0) {
2881
908
          tmp |= MAY_BE_RCN;
2882
908
        }
2883
3.65k
      }
2884
12.3k
      if ((t1 & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_LONG) {
2885
2.66k
        if (!ssa_var_info[ssa_op->op1_use].has_range ||
2886
2.66k
            (opline->opcode == ZEND_PRE_DEC &&
2887
458
             (ssa_var_info[ssa_op->op1_use].range.underflow ||
2888
409
              ssa_var_info[ssa_op->op1_use].range.min == ZEND_LONG_MIN)) ||
2889
2.27k
             (opline->opcode == ZEND_PRE_INC &&
2890
2.20k
              (ssa_var_info[ssa_op->op1_use].range.overflow ||
2891
1.56k
               ssa_var_info[ssa_op->op1_use].range.max == ZEND_LONG_MAX))) {
2892
          /* may overflow */
2893
1.02k
          tmp |= MAY_BE_LONG | MAY_BE_DOUBLE;
2894
1.63k
        } else {
2895
1.63k
          tmp |= MAY_BE_LONG;
2896
1.63k
        }
2897
9.66k
      } else {
2898
9.66k
        if (t1 & (MAY_BE_UNDEF | MAY_BE_NULL)) {
2899
7.87k
          if (opline->opcode == ZEND_PRE_INC) {
2900
6.51k
            tmp |= MAY_BE_LONG;
2901
6.51k
          } else {
2902
1.36k
            tmp |= MAY_BE_NULL;
2903
1.36k
          }
2904
7.87k
        }
2905
9.66k
        if (t1 & MAY_BE_LONG) {
2906
7.37k
          tmp |= MAY_BE_LONG | MAY_BE_DOUBLE;
2907
7.37k
        }
2908
9.66k
        if (t1 & MAY_BE_DOUBLE) {
2909
6.17k
          tmp |= MAY_BE_DOUBLE;
2910
6.17k
        }
2911
9.66k
        if (t1 & MAY_BE_STRING) {
2912
3.47k
          tmp |= MAY_BE_STRING | MAY_BE_LONG | MAY_BE_DOUBLE;
2913
3.47k
        }
2914
9.66k
        tmp |= t1 & (MAY_BE_FALSE | MAY_BE_TRUE | MAY_BE_OBJECT);
2915
9.66k
      }
2916
12.3k
      if (ssa_op->result_def >= 0) {
2917
3.72k
        UPDATE_SSA_TYPE(tmp, ssa_op->result_def);
2918
3.72k
      }
2919
12.3k
      if (ssa_op->op1_def >= 0) {
2920
12.2k
        if (t1 & MAY_BE_REF) {
2921
3.16k
          tmp |= MAY_BE_REF;
2922
3.16k
        }
2923
12.2k
        UPDATE_SSA_TYPE(tmp, ssa_op->op1_def);
2924
12.2k
      }
2925
12.3k
      break;
2926
12.3k
    case ZEND_POST_INC:
2927
8.35k
    case ZEND_POST_DEC:
2928
8.35k
      if (ssa_op->result_def >= 0) {
2929
8.35k
        tmp = 0;
2930
8.35k
        if (t1 & (MAY_BE_RC1|MAY_BE_RCN)) {
2931
2.30k
          tmp |= MAY_BE_RC1|MAY_BE_RCN;
2932
2.30k
        }
2933
8.35k
        tmp |= t1 & ~(MAY_BE_UNDEF|MAY_BE_REF|MAY_BE_RCN);
2934
8.35k
        if (t1 & MAY_BE_UNDEF) {
2935
2.54k
          tmp |= MAY_BE_NULL;
2936
2.54k
        }
2937
8.35k
        UPDATE_SSA_TYPE(tmp, ssa_op->result_def);
2938
8.35k
      }
2939
8.35k
      tmp = 0;
2940
8.35k
      if (t1 & MAY_BE_REF) {
2941
1.60k
        tmp |= MAY_BE_REF;
2942
1.60k
      }
2943
8.35k
      if (t1 & (MAY_BE_RC1|MAY_BE_RCN)) {
2944
2.30k
        tmp |= MAY_BE_RC1;
2945
2.30k
      }
2946
8.35k
      if ((t1 & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_LONG) {
2947
1.20k
        if (!ssa_var_info[ssa_op->op1_use].has_range ||
2948
1.20k
             (opline->opcode == ZEND_POST_DEC &&
2949
450
              (ssa_var_info[ssa_op->op1_use].range.underflow ||
2950
428
               ssa_var_info[ssa_op->op1_use].range.min == ZEND_LONG_MIN)) ||
2951
817
              (opline->opcode == ZEND_POST_INC &&
2952
755
               (ssa_var_info[ssa_op->op1_use].range.overflow ||
2953
759
                ssa_var_info[ssa_op->op1_use].range.max == ZEND_LONG_MAX))) {
2954
          /* may overflow */
2955
759
          tmp |= MAY_BE_LONG | MAY_BE_DOUBLE;
2956
759
        } else {
2957
446
          tmp |= MAY_BE_LONG;
2958
446
        }
2959
7.14k
      } else {
2960
7.14k
        if (t1 & (MAY_BE_UNDEF | MAY_BE_NULL)) {
2961
4.39k
          if (opline->opcode == ZEND_POST_INC) {
2962
1.93k
            tmp |= MAY_BE_LONG;
2963
2.45k
          } else {
2964
2.45k
            tmp |= MAY_BE_NULL;
2965
2.45k
          }
2966
4.39k
        }
2967
7.14k
        if (t1 & MAY_BE_LONG) {
2968
5.45k
          tmp |= MAY_BE_LONG | MAY_BE_DOUBLE;
2969
5.45k
        }
2970
7.14k
        if (t1 & MAY_BE_DOUBLE) {
2971
4.99k
          tmp |= MAY_BE_DOUBLE;
2972
4.99k
        }
2973
7.14k
        if (t1 & MAY_BE_STRING) {
2974
1.94k
          tmp |= MAY_BE_STRING | MAY_BE_LONG | MAY_BE_DOUBLE;
2975
1.94k
        }
2976
7.14k
        tmp |= t1 & (MAY_BE_FALSE | MAY_BE_TRUE | MAY_BE_RESOURCE | MAY_BE_ARRAY | MAY_BE_OBJECT | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF | MAY_BE_ARRAY_KEY_ANY);
2977
7.14k
      }
2978
8.35k
      if (ssa_op->op1_def >= 0) {
2979
8.27k
        UPDATE_SSA_TYPE(tmp, ssa_op->op1_def);
2980
8.27k
      }
2981
8.35k
      break;
2982
15.5k
    case ZEND_ASSIGN_DIM:
2983
15.5k
      if (opline->op1_type == IS_CV) {
2984
14.5k
        tmp = assign_dim_result_type(t1, t2, OP1_DATA_INFO(), opline->op2_type);
2985
14.5k
        tmp |= ssa->var_info[ssa_op->op1_def].type & (MAY_BE_ARRAY_PACKED|MAY_BE_ARRAY_NUMERIC_HASH|MAY_BE_ARRAY_STRING_HASH);
2986
14.5k
        UPDATE_SSA_TYPE(tmp, ssa_op->op1_def);
2987
14.5k
        COPY_SSA_OBJ_TYPE(ssa_op->op1_use, ssa_op->op1_def);
2988
14.5k
      }
2989
15.5k
      if (ssa_op->result_def >= 0) {
2990
8.72k
        tmp = 0;
2991
8.72k
        if (t1 & MAY_BE_STRING) {
2992
2.75k
          tmp |= MAY_BE_STRING | MAY_BE_NULL;
2993
2.75k
        }
2994
8.72k
        if (t1 & MAY_BE_OBJECT) {
2995
2.72k
          tmp |= (MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF);
2996
2.72k
        }
2997
8.72k
        if (t1 & (MAY_BE_ARRAY|MAY_BE_FALSE|MAY_BE_NULL|MAY_BE_UNDEF)) {
2998
8.64k
          tmp |= (OP1_DATA_INFO() & (MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF));
2999
3000
8.64k
          if (OP1_DATA_INFO() & MAY_BE_UNDEF) {
3001
569
            tmp |= MAY_BE_NULL;
3002
569
          }
3003
8.64k
          if (t1 & MAY_BE_ARRAY_OF_REF) {
3004
            /* A scalar type conversion may occur when assigning to a typed reference. */
3005
2.89k
            tmp |= MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE|MAY_BE_STRING;
3006
2.89k
          }
3007
8.64k
        }
3008
8.72k
        if (t1 & (MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE|MAY_BE_RESOURCE)) {
3009
2.82k
          tmp |= MAY_BE_NULL;
3010
2.82k
        }
3011
8.72k
        tmp |= MAY_BE_RC1 | MAY_BE_RCN;
3012
8.72k
        UPDATE_SSA_TYPE(tmp, ssa_op->result_def);
3013
8.72k
      }
3014
15.5k
      if ((ssa_op+1)->op1_def >= 0) {
3015
0
        opline++;
3016
0
        ssa_op++;
3017
0
        tmp = OP1_INFO();
3018
0
        if (tmp & (MAY_BE_ANY | MAY_BE_REF)) {
3019
0
          if (tmp & MAY_BE_RC1) {
3020
0
            tmp |= MAY_BE_RCN;
3021
0
          }
3022
0
        }
3023
0
        UPDATE_SSA_TYPE(tmp, ssa_op->op1_def);
3024
0
      }
3025
15.5k
      break;
3026
15.5k
    case ZEND_ASSIGN_OBJ:
3027
7.25k
      if (opline->op1_type == IS_CV) {
3028
6.91k
        const zend_class_entry *ce = ssa_var_info[ssa_op->op1_use].ce;
3029
6.91k
        bool add_rc = (t1 & (MAY_BE_OBJECT|MAY_BE_REF)) && (!ce
3030
1.06k
          || ce->__set
3031
          /* Non-default write_property may be set within create_object. */
3032
1.06k
          || ce->create_object
3033
1.06k
          || ce->default_object_handlers->write_property != zend_std_write_property
3034
1.06k
          || ssa_var_info[ssa_op->op1_use].is_instanceof);
3035
6.91k
        tmp = (t1 & (MAY_BE_REF|MAY_BE_OBJECT|MAY_BE_RC1|MAY_BE_RCN))|(add_rc ? (MAY_BE_RC1|MAY_BE_RCN) : 0);
3036
6.91k
        UPDATE_SSA_TYPE(tmp, ssa_op->op1_def);
3037
6.91k
        COPY_SSA_OBJ_TYPE(ssa_op->op1_use, ssa_op->op1_def);
3038
6.91k
      }
3039
7.25k
      if (ssa_op->result_def >= 0) {
3040
        // TODO: If there is no __set we might do better
3041
1.98k
        tmp = zend_fetch_prop_type(script,
3042
1.98k
          zend_fetch_prop_info(op_array, ssa, opline, ssa_op), &ce);
3043
1.98k
        UPDATE_SSA_TYPE(tmp, ssa_op->result_def);
3044
1.98k
        if (ce) {
3045
4
          UPDATE_SSA_OBJ_TYPE(ce, 1, ssa_op->result_def);
3046
4
        }
3047
1.98k
      }
3048
7.25k
      if ((ssa_op+1)->op1_def >= 0) {
3049
0
        opline++;
3050
0
        ssa_op++;
3051
0
        tmp = OP1_INFO();
3052
0
        if (tmp & MAY_BE_RC1) {
3053
0
          tmp |= MAY_BE_RCN;
3054
0
        }
3055
0
        UPDATE_SSA_TYPE(tmp, ssa_op->op1_def);
3056
0
      }
3057
7.25k
      break;
3058
7.25k
    case ZEND_ASSIGN_STATIC_PROP:
3059
530
      if (ssa_op->result_def >= 0) {
3060
530
        tmp = MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF | MAY_BE_RC1 | MAY_BE_RCN;
3061
530
        UPDATE_SSA_TYPE(tmp, ssa_op->result_def);
3062
530
      }
3063
530
      if ((ssa_op+1)->op1_def >= 0) {
3064
0
        opline++;
3065
0
        ssa_op++;
3066
0
        tmp = OP1_INFO();
3067
0
        if (tmp & MAY_BE_RC1) {
3068
0
          tmp |= MAY_BE_RCN;
3069
0
        }
3070
0
        UPDATE_SSA_TYPE(tmp, ssa_op->op1_def);
3071
0
      }
3072
530
      break;
3073
530
    case ZEND_PRE_INC_OBJ:
3074
767
    case ZEND_PRE_DEC_OBJ:
3075
1.02k
    case ZEND_POST_INC_OBJ:
3076
1.12k
    case ZEND_POST_DEC_OBJ:
3077
1.12k
      if (opline->op1_type == IS_CV) {
3078
1.01k
        tmp = (t1 & (MAY_BE_REF|MAY_BE_OBJECT))|MAY_BE_RC1|MAY_BE_RCN;
3079
1.01k
        UPDATE_SSA_TYPE(tmp, ssa_op->op1_def);
3080
1.01k
        COPY_SSA_OBJ_TYPE(ssa_op->op1_use, ssa_op->op1_def);
3081
1.01k
      }
3082
1.12k
      if (ssa_op->result_def >= 0) {
3083
        // TODO: ???
3084
733
        tmp = MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
3085
733
        UPDATE_SSA_TYPE(tmp, ssa_op->result_def);
3086
733
      }
3087
1.12k
      break;
3088
106k
    case ZEND_ASSIGN:
3089
106k
      if (ssa_op->op2_def >= 0) {
3090
0
        tmp = t2;
3091
0
        if (tmp & MAY_BE_RC1) {
3092
0
          tmp |= MAY_BE_RCN;
3093
0
        }
3094
0
        UPDATE_SSA_TYPE(tmp, ssa_op->op2_def);
3095
0
      }
3096
106k
      tmp = t2 & ~(MAY_BE_UNDEF|MAY_BE_REF|MAY_BE_RC1|MAY_BE_RCN);
3097
106k
      if (t2 & MAY_BE_UNDEF) {
3098
3.80k
        tmp |= MAY_BE_NULL;
3099
3.80k
      }
3100
106k
      if (t1 & MAY_BE_REF) {
3101
55.2k
        tmp |= MAY_BE_REF;
3102
55.2k
      }
3103
106k
      if (t2 & MAY_BE_REF) {
3104
2.69k
        tmp |= MAY_BE_RC1 | MAY_BE_RCN;
3105
104k
      } else if (opline->op2_type & (IS_TMP_VAR|IS_VAR)) {
3106
68.0k
        tmp |= t2 & (MAY_BE_RC1|MAY_BE_RCN);
3107
68.0k
      } else if (t2 & (MAY_BE_RC1|MAY_BE_RCN)) {
3108
11.6k
        tmp |= MAY_BE_RCN;
3109
11.6k
      }
3110
106k
      if (RETURN_VALUE_USED(opline) && (tmp & MAY_BE_RC1)) {
3111
16.6k
        tmp |= MAY_BE_RCN;
3112
16.6k
      }
3113
106k
      if (ssa_op->op1_def >= 0) {
3114
106k
        if (ssa_var_info[ssa_op->op1_def].use_as_double) {
3115
20
          tmp &= ~MAY_BE_LONG;
3116
20
          tmp |= MAY_BE_DOUBLE;
3117
20
        }
3118
106k
        UPDATE_SSA_TYPE(tmp, ssa_op->op1_def);
3119
106k
        COPY_SSA_OBJ_TYPE(ssa_op->op2_use, ssa_op->op1_def);
3120
106k
      }
3121
106k
      if (ssa_op->result_def >= 0) {
3122
37.8k
        if (tmp & MAY_BE_REF) {
3123
          /* A scalar type conversion may occur when assigning to a typed reference. */
3124
12.9k
          tmp &= ~MAY_BE_REF;
3125
12.9k
          tmp |= MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE|MAY_BE_STRING|MAY_BE_RC1|MAY_BE_RCN;
3126
12.9k
        }
3127
37.8k
        if ((tmp & (MAY_BE_RC1|MAY_BE_RCN)) == MAY_BE_RCN) {
3128
          /* refcount may be indirectly decremented. Make an exception if the result is used in the next instruction */
3129
1.33k
          if (!ssa_opcodes) {
3130
1.33k
            if (ssa->vars[ssa_op->result_def].use_chain < 0
3131
1.28k
             || opline + 1 != op_array->opcodes + ssa->vars[ssa_op->result_def].use_chain) {
3132
164
              tmp |= MAY_BE_RC1;
3133
164
              }
3134
1.33k
          } else {
3135
0
            if (ssa->vars[ssa_op->result_def].use_chain < 0
3136
0
             || opline + 1 != ssa_opcodes[ssa->vars[ssa_op->result_def].use_chain]) {
3137
0
              tmp |= MAY_BE_RC1;
3138
0
              }
3139
0
          }
3140
1.33k
        }
3141
37.8k
        UPDATE_SSA_TYPE(tmp, ssa_op->result_def);
3142
37.8k
        COPY_SSA_OBJ_TYPE(ssa_op->op2_use, ssa_op->result_def);
3143
37.8k
      }
3144
106k
      break;
3145
106k
    case ZEND_ASSIGN_REF:
3146
// TODO: ???
3147
5.88k
      if (opline->op2_type == IS_CV) {
3148
4.23k
        tmp = (MAY_BE_REF | t2) & ~(MAY_BE_UNDEF|MAY_BE_RC1|MAY_BE_RCN);
3149
4.23k
        if (t2 & MAY_BE_UNDEF) {
3150
822
          tmp |= MAY_BE_NULL;
3151
822
        }
3152
4.23k
        UPDATE_SSA_TYPE(tmp, ssa_op->op2_def);
3153
4.23k
      }
3154
5.88k
      if (opline->op2_type == IS_VAR && opline->extended_value == ZEND_RETURNS_FUNCTION) {
3155
209
        tmp = (MAY_BE_REF | MAY_BE_RCN | MAY_BE_RC1 | t2) & ~MAY_BE_UNDEF;
3156
5.67k
      } else {
3157
5.67k
        tmp = (MAY_BE_REF | t2) & ~(MAY_BE_UNDEF|MAY_BE_RC1|MAY_BE_RCN);
3158
5.67k
      }
3159
5.88k
      if (t2 & MAY_BE_UNDEF) {
3160
822
        tmp |= MAY_BE_NULL;
3161
822
      }
3162
5.88k
      UPDATE_SSA_TYPE(tmp, ssa_op->op1_def);
3163
5.88k
      if (ssa_op->result_def >= 0) {
3164
2.91k
        UPDATE_SSA_TYPE(tmp, ssa_op->result_def);
3165
2.91k
      }
3166
5.88k
      break;
3167
5.88k
    case ZEND_ASSIGN_OBJ_REF:
3168
418
      if (opline->op1_type == IS_CV && ssa_op->op1_def >= 0) {
3169
0
        tmp = t1;
3170
0
        if (tmp & MAY_BE_OBJECT) {
3171
0
          tmp |= MAY_BE_RC1 | MAY_BE_RCN;
3172
0
        }
3173
0
        UPDATE_SSA_TYPE(tmp, ssa_op->op1_def);
3174
0
        COPY_SSA_OBJ_TYPE(ssa_op->op1_use, ssa_op->op1_def);
3175
0
      }
3176
3177
418
      t2 = OP1_DATA_INFO();
3178
418
      if ((opline+1)->op1_type == IS_VAR && (opline->extended_value & ZEND_RETURNS_FUNCTION)) {
3179
2
        tmp = (MAY_BE_REF | MAY_BE_RCN | MAY_BE_RC1 | t2) & ~MAY_BE_UNDEF;
3180
416
      } else {
3181
416
        tmp = (MAY_BE_REF | t2) & ~(MAY_BE_UNDEF|MAY_BE_RC1|MAY_BE_RCN);
3182
416
      }
3183
418
      if (t2 & MAY_BE_UNDEF) {
3184
108
        tmp |= MAY_BE_NULL;
3185
108
      }
3186
418
      if (ssa_op->result_def >= 0) {
3187
150
        UPDATE_SSA_TYPE(tmp, ssa_op->result_def);
3188
150
      }
3189
418
      if ((opline+1)->op1_type == IS_CV) {
3190
404
        opline++;
3191
404
        ssa_op++;
3192
404
        tmp = (MAY_BE_REF | t2) & ~(MAY_BE_UNDEF|MAY_BE_RC1|MAY_BE_RCN);
3193
404
        if (t2 & MAY_BE_UNDEF) {
3194
108
          tmp |= MAY_BE_NULL;
3195
108
        }
3196
404
        UPDATE_SSA_TYPE(tmp, ssa_op->op1_def);
3197
404
      }
3198
418
      break;
3199
418
    case ZEND_ASSIGN_STATIC_PROP_REF:
3200
100
      if (ssa_op->result_def >= 0) {
3201
80
        UPDATE_SSA_TYPE(MAY_BE_REF, ssa_op->result_def);
3202
80
      }
3203
100
      if ((opline+1)->op1_type == IS_CV) {
3204
92
        opline++;
3205
92
        ssa_op++;
3206
92
        UPDATE_SSA_TYPE(MAY_BE_REF, ssa_op->op1_def);
3207
92
      }
3208
100
      break;
3209
1.06k
    case ZEND_BIND_GLOBAL:
3210
1.06k
      tmp = MAY_BE_REF | MAY_BE_ANY
3211
1.06k
        | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
3212
1.06k
      UPDATE_SSA_TYPE(tmp, ssa_op->op1_def);
3213
1.06k
      break;
3214
9.49k
    case ZEND_BIND_STATIC:
3215
9.49k
      tmp = MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF
3216
9.49k
        | ((opline->extended_value & ZEND_BIND_REF) ? MAY_BE_REF : (MAY_BE_RC1 | MAY_BE_RCN));
3217
9.49k
      if (opline->extended_value & ZEND_BIND_IMPLICIT) {
3218
6.97k
        tmp |= MAY_BE_UNDEF;
3219
6.97k
      }
3220
9.49k
      UPDATE_SSA_TYPE(tmp, ssa_op->op1_def);
3221
9.49k
      break;
3222
9.49k
    case ZEND_BIND_INIT_STATIC_OR_JMP:
3223
201
      tmp = MAY_BE_UNDEF | MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF | MAY_BE_REF;
3224
201
      UPDATE_SSA_TYPE(tmp, ssa_op->op1_def);
3225
201
      break;
3226
201
    case ZEND_SEND_VAR:
3227
0
      if (ssa_op->op1_def >= 0) {
3228
0
        tmp = t1;
3229
0
        if (t1 & (MAY_BE_RC1|MAY_BE_REF)) {
3230
0
          tmp |= MAY_BE_RCN;
3231
0
        }
3232
0
        UPDATE_SSA_TYPE(tmp, ssa_op->op1_def);
3233
0
        COPY_SSA_OBJ_TYPE(ssa_op->op1_use, ssa_op->op1_def);
3234
0
      }
3235
0
      break;
3236
614
    case ZEND_BIND_LEXICAL:
3237
614
      if (ssa_op->op2_def >= 0) {
3238
614
        if (opline->extended_value & ZEND_BIND_REF) {
3239
614
          tmp = t2 | MAY_BE_REF;
3240
614
        } else {
3241
0
          tmp = t2 & ~(MAY_BE_RC1|MAY_BE_RCN);
3242
0
          if (t2 & (MAY_BE_RC1|MAY_BE_RCN)) {
3243
0
            tmp |= MAY_BE_RCN;
3244
0
          }
3245
0
        }
3246
614
        UPDATE_SSA_TYPE(tmp, ssa_op->op2_def);
3247
614
        COPY_SSA_OBJ_TYPE(ssa_op->op2_use, ssa_op->op2_def);
3248
614
      }
3249
614
      break;
3250
614
    case ZEND_YIELD:
3251
564
      if (ssa_op->op1_def >= 0) {
3252
72
        if (op_array->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
3253
72
          tmp = t1 | MAY_BE_REF;
3254
72
        } else {
3255
0
          tmp = t1 & ~(MAY_BE_RC1|MAY_BE_RCN);
3256
0
          if (t1 & (MAY_BE_RC1|MAY_BE_RCN)) {
3257
0
            tmp |= MAY_BE_RCN;
3258
0
          }
3259
0
        }
3260
72
        UPDATE_SSA_TYPE(tmp, ssa_op->op1_def);
3261
72
        COPY_SSA_OBJ_TYPE(ssa_op->op1_use, ssa_op->op1_def);
3262
72
      }
3263
564
      if (ssa_op->result_def >= 0) {
3264
504
        tmp = MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF
3265
504
          | MAY_BE_RC1 | MAY_BE_RCN;
3266
504
        UPDATE_SSA_TYPE(tmp, ssa_op->result_def);
3267
504
      }
3268
564
      break;
3269
7.26k
    case ZEND_SEND_VAR_EX:
3270
7.26k
    case ZEND_SEND_FUNC_ARG:
3271
7.26k
      if (ssa_op->op1_def >= 0) {
3272
7.26k
        tmp = (t1 & MAY_BE_UNDEF)|MAY_BE_REF|MAY_BE_RC1|MAY_BE_RCN|MAY_BE_ANY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF;
3273
7.26k
        UPDATE_SSA_TYPE(tmp, ssa_op->op1_def);
3274
7.26k
      }
3275
7.26k
      break;
3276
7.26k
    case ZEND_SEND_REF:
3277
2.61k
      if (ssa_op->op1_def >= 0) {
3278
2.61k
        tmp = MAY_BE_REF|MAY_BE_RC1|MAY_BE_RCN|MAY_BE_ANY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF;
3279
2.61k
        UPDATE_SSA_TYPE(tmp, ssa_op->op1_def);
3280
2.61k
      }
3281
2.61k
      break;
3282
2.61k
    case ZEND_SEND_UNPACK:
3283
550
      if (ssa_op->op1_def >= 0) {
3284
550
        tmp = t1;
3285
550
        if (t1 & MAY_BE_ARRAY) {
3286
546
          tmp |= MAY_BE_RC1 | MAY_BE_RCN;
3287
546
          if (t1 & MAY_BE_ARRAY_OF_ANY) {
3288
            /* SEND_UNPACK may acquire references into the array */
3289
546
            tmp |= MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
3290
546
          }
3291
546
        }
3292
550
        if (t1 & MAY_BE_OBJECT) {
3293
326
          tmp |= MAY_BE_RC1 | MAY_BE_RCN;
3294
326
        }
3295
550
        UPDATE_SSA_TYPE(tmp, ssa_op->op1_def);
3296
550
      }
3297
550
      break;
3298
4.85k
    case ZEND_FAST_CONCAT:
3299
24.1k
    case ZEND_ROPE_INIT:
3300
360k
    case ZEND_ROPE_ADD:
3301
380k
    case ZEND_ROPE_END:
3302
380k
      UPDATE_SSA_TYPE(MAY_BE_STRING|MAY_BE_RC1|MAY_BE_RCN, ssa_op->result_def);
3303
380k
      break;
3304
380k
    case ZEND_RECV:
3305
32.0k
    case ZEND_RECV_INIT:
3306
32.6k
    case ZEND_RECV_VARIADIC:
3307
32.6k
    {
3308
      /* Typehinting */
3309
32.6k
      zend_arg_info *arg_info = &op_array->arg_info[opline->op1.num-1];
3310
3311
32.6k
      ce = NULL;
3312
32.6k
      tmp = zend_fetch_arg_info_type(script, arg_info, &ce);
3313
32.6k
      if (ZEND_ARG_SEND_MODE(arg_info)) {
3314
2.41k
        tmp |= MAY_BE_REF;
3315
2.41k
        ce = NULL;
3316
2.41k
      }
3317
3318
32.6k
      if (opline->opcode == ZEND_RECV_VARIADIC) {
3319
626
        uint32_t elem_type = tmp & MAY_BE_REF
3320
626
          ? MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF
3321
626
          : (tmp & MAY_BE_ANY) << MAY_BE_ARRAY_SHIFT;
3322
626
        tmp = MAY_BE_RC1|MAY_BE_RCN|MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_ANY|elem_type;
3323
626
        ce = NULL;
3324
626
      }
3325
3326
32.6k
      UPDATE_SSA_TYPE(tmp, ssa_op->result_def);
3327
32.6k
      if (ce) {
3328
1.03k
        UPDATE_SSA_OBJ_TYPE(ce, 1, ssa_op->result_def);
3329
31.6k
      } else {
3330
31.6k
        UPDATE_SSA_OBJ_TYPE(NULL, 0, ssa_op->result_def);
3331
31.6k
      }
3332
32.6k
      break;
3333
32.6k
    }
3334
622
    case ZEND_DECLARE_ANON_CLASS:
3335
622
      UPDATE_SSA_TYPE(MAY_BE_CLASS, ssa_op->result_def);
3336
622
      if (script && (ce = zend_hash_find_ptr(&script->class_table, Z_STR_P(CRT_CONSTANT(opline->op1)))) != NULL) {
3337
622
        UPDATE_SSA_OBJ_TYPE(ce, 0, ssa_op->result_def);
3338
622
      }
3339
622
      break;
3340
1.12k
    case ZEND_FETCH_CLASS:
3341
1.12k
      UPDATE_SSA_TYPE(MAY_BE_CLASS, ssa_op->result_def);
3342
1.12k
      if (opline->op2_type == IS_UNUSED) {
3343
0
        switch (opline->op1.num & ZEND_FETCH_CLASS_MASK) {
3344
0
          case ZEND_FETCH_CLASS_SELF:
3345
0
            if (op_array->scope) {
3346
0
              UPDATE_SSA_OBJ_TYPE(op_array->scope, 0, ssa_op->result_def);
3347
0
            } else {
3348
0
              UPDATE_SSA_OBJ_TYPE(NULL, 0, ssa_op->result_def);
3349
0
            }
3350
0
            break;
3351
0
          case ZEND_FETCH_CLASS_PARENT:
3352
0
            if (op_array->scope && op_array->scope->parent && (op_array->scope->ce_flags & ZEND_ACC_LINKED)) {
3353
0
              UPDATE_SSA_OBJ_TYPE(op_array->scope->parent, 0, ssa_op->result_def);
3354
0
            } else {
3355
0
              UPDATE_SSA_OBJ_TYPE(NULL, 0, ssa_op->result_def);
3356
0
            }
3357
0
            break;
3358
0
          case ZEND_FETCH_CLASS_STATIC:
3359
0
            if (op_array->scope && (op_array->scope->ce_flags & ZEND_ACC_FINAL)) {
3360
0
              UPDATE_SSA_OBJ_TYPE(op_array->scope, 0, ssa_op->result_def);
3361
0
            } else {
3362
0
              UPDATE_SSA_OBJ_TYPE(NULL, 0, ssa_op->result_def);
3363
0
            }
3364
0
            break;
3365
0
          default:
3366
0
            UPDATE_SSA_OBJ_TYPE(NULL, 0, ssa_op->result_def);
3367
0
            break;
3368
0
        }
3369
1.12k
      } else if (opline->op2_type == IS_CONST) {
3370
38
        zval *zv = CRT_CONSTANT(opline->op2);
3371
38
        if (Z_TYPE_P(zv) == IS_STRING) {
3372
38
          ce = zend_optimizer_get_class_entry(script, op_array, Z_STR_P(zv+1));
3373
38
          UPDATE_SSA_OBJ_TYPE(ce, 0, ssa_op->result_def);
3374
38
        } else {
3375
0
          UPDATE_SSA_OBJ_TYPE(NULL, 0, ssa_op->result_def);
3376
0
        }
3377
1.08k
      } else {
3378
1.08k
        COPY_SSA_OBJ_TYPE(ssa_op->op2_use, ssa_op->result_def);
3379
1.08k
      }
3380
1.12k
      break;
3381
26.6k
    case ZEND_NEW:
3382
26.6k
      tmp = MAY_BE_RC1|MAY_BE_RCN|MAY_BE_OBJECT;
3383
26.6k
      ce = zend_optimizer_get_class_entry_from_op1(script, op_array, opline);
3384
26.6k
      if (ce) {
3385
22.4k
        UPDATE_SSA_OBJ_TYPE(ce, 0, ssa_op->result_def);
3386
22.4k
      } else if ((t1 & MAY_BE_CLASS) && ssa_op->op1_use >= 0 && ssa_var_info[ssa_op->op1_use].ce) {
3387
628
        UPDATE_SSA_OBJ_TYPE(ssa_var_info[ssa_op->op1_use].ce, ssa_var_info[ssa_op->op1_use].is_instanceof, ssa_op->result_def);
3388
628
        if (!ssa_var_info[ssa_op->result_def].is_instanceof) {
3389
626
          ce = ssa_var_info[ssa_op->op1_use].ce;
3390
626
        }
3391
3.51k
      } else {
3392
3.51k
        UPDATE_SSA_OBJ_TYPE(NULL, 0, ssa_op->result_def);
3393
3.51k
      }
3394
      /* New objects without constructors cannot escape. */
3395
26.6k
      if (ce
3396
23.0k
       && !ce->constructor
3397
13.0k
       && !ce->create_object
3398
12.4k
       && ce->default_object_handlers->get_constructor == zend_std_get_constructor) {
3399
12.4k
        tmp &= ~MAY_BE_RCN;
3400
12.4k
      }
3401
26.6k
      UPDATE_SSA_TYPE(tmp, ssa_op->result_def);
3402
26.6k
      break;
3403
26.6k
    case ZEND_CLONE:
3404
539
      UPDATE_SSA_TYPE(MAY_BE_RC1|MAY_BE_RCN|MAY_BE_OBJECT, ssa_op->result_def);
3405
539
      COPY_SSA_OBJ_TYPE(ssa_op->op1_use, ssa_op->result_def);
3406
539
      break;
3407
5.21k
    case ZEND_INIT_ARRAY:
3408
27.6k
    case ZEND_ADD_ARRAY_ELEMENT:
3409
27.6k
      if (ssa_op->op1_def >= 0) {
3410
660
        if (opline->extended_value & ZEND_ARRAY_ELEMENT_REF) {
3411
660
          tmp = (MAY_BE_REF | t1) & ~(MAY_BE_UNDEF|MAY_BE_RC1|MAY_BE_RCN);
3412
660
          if (t1 & MAY_BE_UNDEF) {
3413
236
            tmp |= MAY_BE_NULL;
3414
236
          }
3415
660
        } else if ((t1 & (MAY_BE_REF|MAY_BE_RC1|MAY_BE_RCN)) == MAY_BE_REF) {
3416
0
          tmp = (MAY_BE_REF | t1) & ~(MAY_BE_UNDEF|MAY_BE_RC1|MAY_BE_RCN);
3417
0
          if (t1 & MAY_BE_UNDEF) {
3418
0
            tmp |= MAY_BE_NULL;
3419
0
          }
3420
0
        } else if (t1 & MAY_BE_REF) {
3421
0
          tmp = (MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_REF | t1);
3422
0
        } else {
3423
0
          tmp = t1;
3424
0
          if (t1 & MAY_BE_RC1) {
3425
0
            tmp |= MAY_BE_RCN;
3426
0
          }
3427
0
        }
3428
660
        UPDATE_SSA_TYPE(tmp, ssa_op->op1_def);
3429
660
      }
3430
27.6k
      if (ssa_op->result_def >= 0) {
3431
27.6k
        uint32_t arr_type;
3432
27.6k
        if (opline->opcode == ZEND_INIT_ARRAY) {
3433
5.21k
          arr_type = 0;
3434
22.4k
        } else {
3435
22.4k
          arr_type = RES_USE_INFO();
3436
22.4k
        }
3437
27.6k
        tmp = MAY_BE_RC1|MAY_BE_ARRAY|arr_type;
3438
27.6k
        if (opline->opcode == ZEND_INIT_ARRAY && opline->op1_type == IS_UNUSED) {
3439
161
          tmp |= MAY_BE_ARRAY_EMPTY;
3440
161
        }
3441
27.6k
        if (opline->op1_type != IS_UNUSED
3442
27.5k
         && (opline->op2_type == IS_UNUSED
3443
27.4k
          || (t2 & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE|MAY_BE_RESOURCE|MAY_BE_STRING)))) {
3444
27.4k
          tmp |= assign_dim_array_result_type(arr_type, t2, t1, opline->op2_type);
3445
27.4k
          if (opline->extended_value & ZEND_ARRAY_ELEMENT_REF) {
3446
677
            tmp |= MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF;
3447
677
          }
3448
27.4k
        }
3449
27.6k
        UPDATE_SSA_TYPE(tmp, ssa_op->result_def);
3450
27.6k
      }
3451
27.6k
      break;
3452
27.6k
    case ZEND_ADD_ARRAY_UNPACK:
3453
249
      tmp = ssa_var_info[ssa_op->result_use].type;
3454
249
      ZEND_ASSERT(tmp & MAY_BE_ARRAY);
3455
249
      tmp |= t1 & (MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF);
3456
249
      if (t1 & MAY_BE_OBJECT) {
3457
194
        tmp |= MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY;
3458
194
      }
3459
249
      UPDATE_SSA_TYPE(tmp, ssa_op->result_def);
3460
249
      break;
3461
2.39k
    case ZEND_UNSET_CV:
3462
2.39k
      tmp = MAY_BE_UNDEF;
3463
2.39k
      if (!op_array->function_name) {
3464
        /* In global scope, we know nothing */
3465
1.70k
        tmp |= MAY_BE_REF;
3466
1.70k
      }
3467
2.39k
      UPDATE_SSA_TYPE(tmp, ssa_op->op1_def);
3468
2.39k
      break;
3469
2.39k
    case ZEND_UNSET_DIM:
3470
1.63k
    case ZEND_UNSET_OBJ:
3471
1.63k
      if (ssa_op->op1_def >= 0) {
3472
1.63k
        UPDATE_SSA_TYPE(t1, ssa_op->op1_def);
3473
1.63k
        COPY_SSA_OBJ_TYPE(ssa_op->op1_use, ssa_op->op1_def);
3474
1.63k
      }
3475
1.63k
      break;
3476
3.96k
    case ZEND_FE_RESET_R:
3477
5.73k
    case ZEND_FE_RESET_RW:
3478
5.73k
      if (ssa_op->op1_def >= 0) {
3479
1.65k
        tmp = t1;
3480
1.65k
        if (opline->opcode == ZEND_FE_RESET_RW) {
3481
1.65k
          tmp |= MAY_BE_REF;
3482
1.65k
        } else if (t1 & MAY_BE_RC1) {
3483
0
          tmp |= MAY_BE_RCN;
3484
0
        }
3485
1.65k
        UPDATE_SSA_TYPE(tmp, ssa_op->op1_def);
3486
1.65k
        COPY_SSA_OBJ_TYPE(ssa_op->op1_use, ssa_op->op1_def);
3487
1.65k
      }
3488
5.73k
      if (opline->opcode == ZEND_FE_RESET_RW) {
3489
//???
3490
1.76k
        tmp = MAY_BE_REF | (t1 & (MAY_BE_ARRAY | MAY_BE_OBJECT));
3491
3.96k
      } else {
3492
3.96k
        tmp = MAY_BE_RC1 | MAY_BE_RCN | (t1 & (MAY_BE_ARRAY | MAY_BE_OBJECT | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF));
3493
3.96k
      }
3494
      /* The result is set to UNDEF for invalid foreach inputs. */
3495
5.73k
      if ((t1 & (MAY_BE_ANY | MAY_BE_UNDEF)) & ~(MAY_BE_ARRAY | MAY_BE_OBJECT)) {
3496
4.41k
        tmp |= MAY_BE_UNDEF;
3497
4.41k
      }
3498
5.73k
      UPDATE_SSA_TYPE(tmp, ssa_op->result_def);
3499
5.73k
      COPY_SSA_OBJ_TYPE(ssa_op->op1_use, ssa_op->result_def);
3500
5.73k
      break;
3501
5.76k
    case ZEND_FE_FETCH_R:
3502
7.01k
    case ZEND_FE_FETCH_RW:
3503
7.01k
      tmp = 0;
3504
7.01k
      if (opline->op2_type == IS_CV) {
3505
6.51k
        tmp = t2 & MAY_BE_REF;
3506
6.51k
      }
3507
7.01k
      if (t1 & MAY_BE_OBJECT) {
3508
4.98k
        if (opline->opcode == ZEND_FE_FETCH_RW) {
3509
1.25k
          tmp |= MAY_BE_REF | MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
3510
3.73k
        } else {
3511
3.73k
          tmp |= MAY_BE_RCN | MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
3512
3.73k
          if (opline->op2_type != IS_CV) {
3513
289
            tmp |= MAY_BE_REF;
3514
289
          }
3515
3.73k
        }
3516
4.98k
      }
3517
7.01k
      if (t1 & MAY_BE_ARRAY) {
3518
6.33k
        if (opline->opcode == ZEND_FE_FETCH_RW) {
3519
1.25k
          tmp |= MAY_BE_REF | MAY_BE_RCN | MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
3520
5.08k
        } else {
3521
5.08k
          tmp |= ((t1 & MAY_BE_ARRAY_OF_ANY) >> MAY_BE_ARRAY_SHIFT);
3522
5.08k
          if (tmp & MAY_BE_ARRAY) {
3523
4.14k
            tmp |= MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
3524
4.14k
          }
3525
5.08k
          if (t1 & MAY_BE_ARRAY_OF_REF) {
3526
3.76k
            tmp |= MAY_BE_RC1 | MAY_BE_RCN;
3527
3.76k
            if (opline->op2_type != IS_CV) {
3528
303
              tmp |= MAY_BE_REF;
3529
303
            }
3530
3.76k
          } else if (tmp & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)) {
3531
631
            tmp |= MAY_BE_RC1 | MAY_BE_RCN;
3532
631
          }
3533
5.08k
        }
3534
6.33k
      }
3535
7.01k
      UPDATE_SSA_TYPE(tmp, ssa_op->op2_def);
3536
7.01k
      if (ssa_op->result_def >= 0) {
3537
3.11k
        tmp = (ssa_op->result_use >= 0) ? RES_USE_INFO() : 0;
3538
3.11k
        if (t1 & MAY_BE_OBJECT) {
3539
2.46k
          tmp |= MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
3540
2.46k
        }
3541
3.11k
        if (t1 & MAY_BE_ARRAY) {
3542
2.86k
          if (t1 & MAY_BE_ARRAY_KEY_LONG) {
3543
2.73k
            tmp |= MAY_BE_LONG;
3544
2.73k
          }
3545
2.86k
          if (t1 & MAY_BE_ARRAY_KEY_STRING) {
3546
2.65k
            tmp |= MAY_BE_STRING | MAY_BE_RCN;
3547
2.65k
          }
3548
2.86k
        }
3549
3.11k
        UPDATE_SSA_TYPE(tmp, ssa_op->result_def);
3550
3.11k
      }
3551
7.01k
      break;
3552
12.7k
    case ZEND_FETCH_DIM_R:
3553
14.4k
    case ZEND_FETCH_DIM_IS:
3554
15.7k
    case ZEND_FETCH_DIM_RW:
3555
25.2k
    case ZEND_FETCH_DIM_W:
3556
25.5k
    case ZEND_FETCH_DIM_UNSET:
3557
26.8k
    case ZEND_FETCH_DIM_FUNC_ARG:
3558
28.8k
    case ZEND_FETCH_LIST_R:
3559
29.2k
    case ZEND_FETCH_LIST_W:
3560
29.2k
      if (ssa_op->op1_def >= 0) {
3561
9.20k
        uint32_t key_type = 0;
3562
9.20k
        tmp = t1 & ~(MAY_BE_RC1|MAY_BE_RCN);
3563
9.20k
        if (opline->opcode == ZEND_FETCH_DIM_W ||
3564
2.30k
            opline->opcode == ZEND_FETCH_DIM_RW ||
3565
1.37k
            opline->opcode == ZEND_FETCH_DIM_FUNC_ARG ||
3566
8.95k
            opline->opcode == ZEND_FETCH_LIST_W) {
3567
8.95k
          if (t1 & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE)) {
3568
7.82k
            if (opline->opcode != ZEND_FETCH_DIM_FUNC_ARG) {
3569
6.79k
              tmp &= ~(MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE);
3570
6.79k
            }
3571
7.82k
            tmp |= MAY_BE_ARRAY | MAY_BE_RC1;
3572
7.82k
          }
3573
8.95k
          if (t1 & (MAY_BE_STRING|MAY_BE_ARRAY)) {
3574
7.56k
            tmp |= MAY_BE_RC1;
3575
7.56k
            if (opline->opcode == ZEND_FETCH_DIM_FUNC_ARG) {
3576
1.03k
              tmp |= t1 & MAY_BE_RCN;
3577
1.03k
            }
3578
7.56k
          }
3579
8.95k
          if (t1 & (MAY_BE_OBJECT|MAY_BE_RESOURCE)) {
3580
5.75k
            tmp |= t1 & (MAY_BE_RC1|MAY_BE_RCN);
3581
5.75k
          }
3582
8.95k
          if (opline->op2_type == IS_UNUSED) {
3583
694
            if (t1 & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE)) {
3584
592
              key_type |= MAY_BE_ARRAY_PACKED;
3585
592
            }
3586
694
            if (t1 & MAY_BE_ARRAY) {
3587
553
              key_type |= MAY_BE_HASH_ONLY(t1) ?
3588
545
                MAY_BE_ARRAY_NUMERIC_HASH : MAY_BE_ARRAY_KEY_LONG;
3589
553
            }
3590
8.25k
          } else {
3591
8.25k
            if (t2 & (MAY_BE_LONG|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_RESOURCE|MAY_BE_DOUBLE)) {
3592
5.21k
              if (t1 & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE)) {
3593
4.53k
                key_type |= MAY_BE_ARRAY_PACKED;
3594
4.53k
              }
3595
5.21k
              if (t1 & MAY_BE_ARRAY) {
3596
4.29k
                key_type |= MAY_BE_HASH_ONLY(t1) ?
3597
4.24k
                  MAY_BE_ARRAY_NUMERIC_HASH : MAY_BE_ARRAY_KEY_LONG;
3598
4.29k
                }
3599
5.21k
            }
3600
8.25k
            if (t2 & MAY_BE_STRING) {
3601
3.36k
              key_type |= MAY_BE_ARRAY_KEY_STRING;
3602
3.36k
              if (opline->op2_type != IS_CONST) {
3603
                // FIXME: numeric string
3604
1.36k
                if (t1 & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE)) {
3605
1.34k
                  key_type |= MAY_BE_ARRAY_PACKED;
3606
1.34k
                }
3607
1.36k
                if (t1 & MAY_BE_ARRAY) {
3608
1.31k
                  key_type |= MAY_BE_HASH_ONLY(t1) ?
3609
1.27k
                    MAY_BE_ARRAY_NUMERIC_HASH : MAY_BE_ARRAY_KEY_LONG;
3610
1.31k
                  }
3611
1.36k
              }
3612
3.36k
            }
3613
8.25k
            if (t2 & (MAY_BE_UNDEF | MAY_BE_NULL)) {
3614
1.39k
              key_type |= MAY_BE_ARRAY_KEY_STRING;
3615
1.39k
            }
3616
8.25k
          }
3617
8.95k
        } else if (opline->opcode == ZEND_FETCH_DIM_UNSET) {
3618
248
          if (t1 & MAY_BE_ARRAY) {
3619
216
            tmp |= MAY_BE_RC1;
3620
216
          }
3621
248
          if (t1 & (MAY_BE_OBJECT|MAY_BE_RESOURCE)) {
3622
184
            tmp |= t1 & (MAY_BE_RC1|MAY_BE_RCN);
3623
184
          }
3624
248
        }
3625
9.20k
        if ((key_type & (MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_KEY_STRING))
3626
8.74k
            && (opline->opcode == ZEND_FETCH_DIM_RW
3627
7.82k
            || opline->opcode == ZEND_FETCH_DIM_W
3628
1.10k
            || opline->opcode == ZEND_FETCH_DIM_FUNC_ARG
3629
8.74k
            || opline->opcode == ZEND_FETCH_LIST_W)) {
3630
8.74k
          j = ssa_vars[ssa_op->result_def].use_chain;
3631
8.74k
          if (j < 0) {
3632
            /* no uses */
3633
0
            tmp |= key_type | MAY_BE_ARRAY | MAY_BE_ARRAY_OF_NULL;
3634
0
          }
3635
17.4k
          while (j >= 0) {
3636
8.74k
            uint8_t opcode;
3637
3638
8.74k
            if (!ssa_opcodes) {
3639
8.74k
              if (j != (opline - op_array->opcodes) + 1) {
3640
                /* Use must be in next opline */
3641
0
                tmp |= key_type | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
3642
0
                break;
3643
0
              }
3644
8.74k
              opcode = op_array->opcodes[j].opcode;
3645
8.74k
            } else {
3646
0
              if (ssa_opcodes[j] != opline + 1) {
3647
                /* Use must be in next opline */
3648
0
                tmp |= key_type | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
3649
0
                break;
3650
0
              }
3651
0
              opcode = ssa_opcodes[j]->opcode;
3652
0
            }
3653
8.74k
            switch (opcode) {
3654
384
              case ZEND_FETCH_DIM_W:
3655
614
              case ZEND_FETCH_DIM_RW:
3656
678
              case ZEND_FETCH_DIM_FUNC_ARG:
3657
678
              case ZEND_FETCH_LIST_W:
3658
4.03k
              case ZEND_ASSIGN_DIM:
3659
4.57k
              case ZEND_ASSIGN_DIM_OP:
3660
4.57k
                tmp |= key_type | MAY_BE_ARRAY | MAY_BE_ARRAY_OF_ARRAY;
3661
4.57k
                break;
3662
0
              case ZEND_SEND_VAR_EX:
3663
998
              case ZEND_SEND_FUNC_ARG:
3664
998
              case ZEND_SEND_VAR_NO_REF:
3665
998
              case ZEND_SEND_VAR_NO_REF_EX:
3666
1.38k
              case ZEND_SEND_REF:
3667
3.38k
              case ZEND_ASSIGN_REF:
3668
3.39k
              case ZEND_YIELD:
3669
3.40k
              case ZEND_INIT_ARRAY:
3670
3.40k
              case ZEND_ADD_ARRAY_ELEMENT:
3671
3.41k
              case ZEND_RETURN_BY_REF:
3672
3.44k
              case ZEND_VERIFY_RETURN_TYPE:
3673
3.67k
              case ZEND_MAKE_REF:
3674
3.67k
              case ZEND_FE_RESET_RW:
3675
3.67k
                tmp |= key_type | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
3676
3.67k
                break;
3677
88
              case ZEND_PRE_INC:
3678
96
              case ZEND_PRE_DEC:
3679
116
              case ZEND_POST_INC:
3680
132
              case ZEND_POST_DEC:
3681
132
                if (tmp & MAY_BE_ARRAY_OF_LONG) {
3682
                  /* may overflow */
3683
96
                  tmp |= key_type | MAY_BE_ARRAY_OF_DOUBLE;
3684
96
                } else if (!(tmp & (MAY_BE_ARRAY_OF_LONG|MAY_BE_ARRAY_OF_DOUBLE))) {
3685
36
                  tmp |= key_type | MAY_BE_ARRAY_OF_LONG | MAY_BE_ARRAY_OF_DOUBLE;
3686
36
                }
3687
132
                break;
3688
28
              case ZEND_FETCH_OBJ_W:
3689
28
              case ZEND_FETCH_OBJ_RW:
3690
55
              case ZEND_FETCH_OBJ_FUNC_ARG:
3691
303
              case ZEND_ASSIGN_OBJ:
3692
303
              case ZEND_ASSIGN_OBJ_OP:
3693
331
              case ZEND_ASSIGN_OBJ_REF:
3694
335
              case ZEND_PRE_INC_OBJ:
3695
335
              case ZEND_PRE_DEC_OBJ:
3696
335
              case ZEND_POST_INC_OBJ:
3697
343
              case ZEND_POST_DEC_OBJ:
3698
                /* These will result in an error exception, unless the element
3699
                 * is already an object. */
3700
343
                break;
3701
16
              case ZEND_SEND_VAR:
3702
20
              case ZEND_FETCH_DIM_R:
3703
                /* This can occur if a DIM_FETCH_FUNC_ARG with UNUSED op2 is left
3704
                 * behind, because it can't be converted to DIM_FETCH_R. */
3705
20
                break;
3706
0
              case ZEND_FREE:
3707
                /* This may happen if the using opcode is DCEd.  */
3708
0
                break;
3709
0
              default: ZEND_UNREACHABLE();
3710
8.74k
            }
3711
8.74k
            j = zend_ssa_next_use(ssa->ops, ssa_op->result_def, j);
3712
8.74k
            if (j >= 0) {
3713
0
              tmp |= key_type | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
3714
0
              break;
3715
0
            }
3716
8.74k
          }
3717
8.74k
          if (opline->opcode != ZEND_FETCH_DIM_FUNC_ARG) {
3718
7.63k
            tmp &= ~MAY_BE_ARRAY_EMPTY;
3719
7.63k
          }
3720
8.74k
        }
3721
9.20k
        if (!(tmp & MAY_BE_ARRAY)
3722
9.00k
         || (tmp & MAY_BE_ARRAY_KEY_ANY)
3723
57
         || opline->opcode == ZEND_FETCH_DIM_FUNC_ARG
3724
34
         || opline->opcode == ZEND_FETCH_DIM_R
3725
34
         || opline->opcode == ZEND_FETCH_DIM_IS
3726
34
         || opline->opcode == ZEND_FETCH_DIM_UNSET
3727
9.16k
         || opline->opcode == ZEND_FETCH_LIST_R) {
3728
9.16k
          UPDATE_SSA_TYPE(tmp, ssa_op->op1_def);
3729
9.16k
        } else {
3730
          /* invalid key type */
3731
34
          return SUCCESS;
3732
34
        }
3733
9.16k
        COPY_SSA_OBJ_TYPE(ssa_op->op1_use, ssa_op->op1_def);
3734
9.16k
      }
3735
      /* FETCH_LIST on a string behaves like FETCH_R on null */
3736
29.2k
      tmp = zend_array_element_type(
3737
29.2k
        opline->opcode != ZEND_FETCH_LIST_R ? t1 : ((t1 & ~MAY_BE_STRING) | MAY_BE_NULL),
3738
29.2k
        opline->op1_type,
3739
29.2k
        opline->opcode != ZEND_FETCH_DIM_R && opline->opcode != ZEND_FETCH_DIM_IS
3740
14.7k
          && opline->opcode != ZEND_FETCH_LIST_R,
3741
29.2k
        opline->op2_type == IS_UNUSED);
3742
29.2k
      if (opline->opcode == ZEND_FETCH_DIM_FUNC_ARG && (t1 & (MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE|MAY_BE_RESOURCE))) {
3743
921
        tmp |= MAY_BE_NULL;
3744
921
      }
3745
29.2k
      if (opline->opcode == ZEND_FETCH_DIM_IS && (t1 & MAY_BE_STRING)) {
3746
1.25k
        tmp |= MAY_BE_NULL;
3747
1.25k
      }
3748
29.2k
      if ((tmp & (MAY_BE_RC1|MAY_BE_RCN)) == MAY_BE_RCN && opline->result_type == IS_TMP_VAR) {
3749
        /* refcount may be indirectly decremented. Make an exception if the result is used in the next instruction */
3750
2.12k
        if (!ssa_opcodes) {
3751
2.12k
          if (ssa->vars[ssa_op->result_def].use_chain < 0
3752
2.12k
           || opline + 1 != op_array->opcodes + ssa->vars[ssa_op->result_def].use_chain) {
3753
470
            tmp |= MAY_BE_RC1;
3754
470
            }
3755
2.12k
        } else {
3756
0
          if (ssa->vars[ssa_op->result_def].use_chain < 0
3757
0
           || opline + 1 != ssa_opcodes[ssa->vars[ssa_op->result_def].use_chain]) {
3758
0
            tmp |= MAY_BE_RC1;
3759
0
            }
3760
0
        }
3761
2.12k
      }
3762
29.2k
      UPDATE_SSA_TYPE(tmp, ssa_op->result_def);
3763
29.2k
      break;
3764
29.2k
    case ZEND_FETCH_THIS:
3765
3.11k
      if (!(op_array->fn_flags & ZEND_ACC_TRAIT_CLONE)) {
3766
3.11k
        UPDATE_SSA_OBJ_TYPE(op_array->scope, 1, ssa_op->result_def);
3767
3.11k
      }
3768
3.11k
      UPDATE_SSA_TYPE(MAY_BE_RCN|MAY_BE_OBJECT, ssa_op->result_def);
3769
3.11k
      break;
3770
63.0k
    case ZEND_FETCH_OBJ_R:
3771
64.8k
    case ZEND_FETCH_OBJ_IS:
3772
65.0k
    case ZEND_FETCH_OBJ_RW:
3773
69.1k
    case ZEND_FETCH_OBJ_W:
3774
69.4k
    case ZEND_FETCH_OBJ_UNSET:
3775
69.8k
    case ZEND_FETCH_OBJ_FUNC_ARG:
3776
69.8k
      if (ssa_op->result_def >= 0) {
3777
69.8k
        uint32_t tmp = 0;
3778
69.8k
        ce = NULL;
3779
69.8k
        if (opline->op1_type != IS_UNUSED
3780
63.9k
            && (t1 & (MAY_BE_ANY | MAY_BE_UNDEF) & ~MAY_BE_OBJECT)) {
3781
62.6k
          tmp |= MAY_BE_NULL;
3782
62.6k
        }
3783
69.8k
        if (opline->op1_type == IS_UNUSED || (t1 & MAY_BE_OBJECT)) {
3784
68.6k
          const zend_property_info *prop_info = zend_fetch_prop_info(op_array, ssa, opline, ssa_op);
3785
68.6k
          tmp |= zend_fetch_prop_type(script, prop_info, &ce);
3786
68.6k
          if (opline->opcode != ZEND_FETCH_OBJ_R && opline->opcode != ZEND_FETCH_OBJ_IS) {
3787
4.81k
            tmp |= MAY_BE_REF | MAY_BE_INDIRECT;
3788
4.81k
            if ((opline->extended_value & ZEND_FETCH_OBJ_FLAGS) == ZEND_FETCH_DIM_WRITE) {
3789
2.09k
              tmp |= MAY_BE_UNDEF;
3790
2.09k
            }
3791
4.81k
            ce = NULL;
3792
63.8k
          } else if (!(opline->op1_type & (IS_VAR|IS_TMP_VAR)) || !(t1 & MAY_BE_RC1)) {
3793
58.1k
            const zend_class_entry *ce = NULL;
3794
3795
58.1k
            if (opline->op1_type == IS_UNUSED) {
3796
4.14k
              ce = op_array->scope;
3797
53.9k
            } else if (ssa_op->op1_use >= 0 && !ssa->var_info[ssa_op->op1_use].is_instanceof) {
3798
53.6k
              ce = ssa->var_info[ssa_op->op1_use].ce;
3799
53.6k
            }
3800
            /* Unset properties will resort back to __get/__set */
3801
58.1k
            if (ce
3802
4.48k
             && !ce->create_object
3803
4.43k
             && ce->default_object_handlers->read_property == zend_std_read_property
3804
4.43k
             && !ce->__get
3805
3.75k
             && !result_may_be_separated(ssa, ssa_op)) {
3806
3.32k
              tmp &= ~MAY_BE_RC1;
3807
3.32k
            }
3808
58.1k
            if (opline->opcode == ZEND_FETCH_OBJ_IS) {
3809
              /* IS check may return null for uninitialized typed property. */
3810
1.35k
              tmp |= MAY_BE_NULL;
3811
1.35k
            }
3812
58.1k
          }
3813
68.6k
        }
3814
69.8k
        UPDATE_SSA_TYPE(tmp, ssa_op->result_def);
3815
69.8k
        if (ce) {
3816
94
          UPDATE_SSA_OBJ_TYPE(ce, 1, ssa_op->result_def);
3817
94
        }
3818
69.8k
      }
3819
69.8k
      break;
3820
69.8k
    case ZEND_FETCH_STATIC_PROP_R:
3821
2.40k
    case ZEND_FETCH_STATIC_PROP_IS:
3822
2.40k
    case ZEND_FETCH_STATIC_PROP_RW:
3823
2.76k
    case ZEND_FETCH_STATIC_PROP_W:
3824
2.86k
    case ZEND_FETCH_STATIC_PROP_UNSET:
3825
3.13k
    case ZEND_FETCH_STATIC_PROP_FUNC_ARG:
3826
3.13k
      tmp = zend_fetch_prop_type(script,
3827
3.13k
        zend_fetch_static_prop_info(script, op_array, ssa, opline), &ce);
3828
3.13k
      if (opline->opcode != ZEND_FETCH_STATIC_PROP_R
3829
1.16k
          && opline->opcode != ZEND_FETCH_STATIC_PROP_IS) {
3830
730
        tmp |= MAY_BE_REF | MAY_BE_INDIRECT;
3831
730
        if ((opline->extended_value & ZEND_FETCH_OBJ_FLAGS) == ZEND_FETCH_DIM_WRITE) {
3832
252
          tmp |= MAY_BE_UNDEF;
3833
252
        }
3834
730
        ce = NULL;
3835
2.40k
      } else {
3836
2.40k
        if (!result_may_be_separated(ssa, ssa_op)) {
3837
2.36k
          tmp &= ~MAY_BE_RC1;
3838
2.36k
        }
3839
2.40k
        if (opline->opcode == ZEND_FETCH_STATIC_PROP_IS) {
3840
431
          tmp |= MAY_BE_NULL;
3841
431
        }
3842
2.40k
      }
3843
3.13k
      UPDATE_SSA_TYPE(tmp, ssa_op->result_def);
3844
3.13k
      if (ce) {
3845
28
        UPDATE_SSA_OBJ_TYPE(ce, 1, ssa_op->result_def);
3846
28
      }
3847
3.13k
      break;
3848
0
    case ZEND_FRAMELESS_ICALL_1:
3849
0
    case ZEND_FRAMELESS_ICALL_2:
3850
0
    case ZEND_FRAMELESS_ICALL_3:
3851
0
      if (ssa_op->op1_def >= 0) {
3852
0
        ZEND_ASSERT(ssa_op->op1_use >= 0);
3853
0
        tmp = ssa->var_info[ssa_op->op1_use].type;
3854
0
        if (tmp & MAY_BE_RC1) {
3855
0
          tmp |= MAY_BE_RCN;
3856
0
        }
3857
0
        UPDATE_SSA_TYPE(tmp, ssa_op->op1_def);
3858
0
      }
3859
0
      if (ssa_op->op2_def >= 0) {
3860
0
        ZEND_ASSERT(ssa_op->op2_use >= 0);
3861
0
        tmp = ssa->var_info[ssa_op->op2_use].type;
3862
0
        if (tmp & MAY_BE_RC1) {
3863
0
          tmp |= MAY_BE_RCN;
3864
0
        }
3865
0
        UPDATE_SSA_TYPE(tmp, ssa_op->op2_def);
3866
0
      }
3867
0
      if (opline->opcode == ZEND_FRAMELESS_ICALL_3) {
3868
0
        zend_ssa_op *next_ssa_op = ssa_op + 1;
3869
0
        if (next_ssa_op->op1_def >= 0) {
3870
0
          ZEND_ASSERT(next_ssa_op->op1_use >= 0);
3871
0
          tmp = ssa->var_info[next_ssa_op->op1_use].type;
3872
0
          if (tmp & MAY_BE_RC1) {
3873
0
            tmp |= MAY_BE_RCN;
3874
0
          }
3875
0
          UPDATE_SSA_TYPE(tmp, next_ssa_op->op1_def);
3876
0
        }
3877
0
      }
3878
0
      ZEND_FALLTHROUGH;
3879
0
    case ZEND_FRAMELESS_ICALL_0:
3880
47.4k
    case ZEND_DO_FCALL:
3881
47.4k
    case ZEND_DO_ICALL:
3882
52.2k
    case ZEND_DO_UCALL:
3883
52.2k
    case ZEND_DO_FCALL_BY_NAME:
3884
52.2k
      if (ssa_op->result_def >= 0) {
3885
52.2k
        zend_func_info *func_info = ZEND_FUNC_INFO(op_array);
3886
52.2k
        zend_call_info *call_info;
3887
3888
52.2k
        if (!func_info || !func_info->call_map) {
3889
6.81k
          goto unknown_opcode;
3890
6.81k
        }
3891
45.4k
        call_info = func_info->call_map[opline - op_array->opcodes];
3892
45.4k
        if (!call_info) {
3893
14.4k
          goto unknown_opcode;
3894
14.4k
        }
3895
3896
31.0k
        zend_class_entry *ce;
3897
31.0k
        bool ce_is_instanceof;
3898
31.0k
        tmp = zend_get_func_info(call_info, ssa, &ce, &ce_is_instanceof);
3899
31.0k
        UPDATE_SSA_TYPE(tmp, ssa_op->result_def);
3900
31.0k
        if (ce) {
3901
1.53k
          UPDATE_SSA_OBJ_TYPE(ce, ce_is_instanceof, ssa_op->result_def);
3902
1.53k
        }
3903
31.0k
      }
3904
31.0k
      break;
3905
31.0k
    case ZEND_CALLABLE_CONVERT:
3906
1.50k
    case ZEND_CALLABLE_CONVERT_PARTIAL:
3907
1.50k
      UPDATE_SSA_TYPE(MAY_BE_OBJECT | MAY_BE_RC1 | MAY_BE_RCN, ssa_op->result_def);
3908
1.50k
      UPDATE_SSA_OBJ_TYPE(zend_ce_closure, /* is_instanceof */ false, ssa_op->result_def);
3909
1.50k
      break;
3910
22.5k
    case ZEND_FETCH_CONSTANT:
3911
22.5k
      UPDATE_SSA_TYPE(MAY_BE_RC1|MAY_BE_RCN|MAY_BE_ANY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY, ssa_op->result_def);
3912
22.5k
      break;
3913
22.5k
    case ZEND_FETCH_CLASS_CONSTANT: {
3914
3.20k
      bool is_prototype;
3915
3.20k
      const zend_class_constant *cc = zend_fetch_class_const_info(script, op_array, opline, &is_prototype);
3916
3.20k
      if (!cc || !ZEND_TYPE_IS_SET(cc->type)) {
3917
3.06k
        UPDATE_SSA_TYPE(MAY_BE_RC1|MAY_BE_RCN|MAY_BE_ANY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY, ssa_op->result_def);
3918
3.06k
        break;
3919
3.06k
      }
3920
142
      UPDATE_SSA_TYPE(zend_convert_type(script, cc->type, &ce), ssa_op->result_def);
3921
142
      if (ce) {
3922
0
        UPDATE_SSA_OBJ_TYPE(ce, /* is_instanceof */ true, ssa_op->result_def);
3923
0
      }
3924
142
      break;
3925
142
    }
3926
2.05k
    case ZEND_STRLEN:
3927
3.21k
    case ZEND_COUNT:
3928
3.40k
    case ZEND_FUNC_NUM_ARGS:
3929
3.40k
      UPDATE_SSA_TYPE(MAY_BE_LONG, ssa_op->result_def);
3930
3.40k
      break;
3931
3.40k
    case ZEND_FUNC_GET_ARGS:
3932
252
      UPDATE_SSA_TYPE(MAY_BE_RC1|MAY_BE_RCN|MAY_BE_ARRAY|MAY_BE_ARRAY_EMPTY|MAY_BE_ARRAY_PACKED|MAY_BE_ARRAY_OF_ANY, ssa_op->result_def);
3933
252
      break;
3934
586
    case ZEND_GET_CLASS:
3935
672
    case ZEND_GET_CALLED_CLASS:
3936
672
      UPDATE_SSA_TYPE(MAY_BE_STRING|MAY_BE_RCN, ssa_op->result_def);
3937
672
      break;
3938
672
    case ZEND_GET_TYPE:
3939
80
      UPDATE_SSA_TYPE(MAY_BE_STRING|MAY_BE_RC1|MAY_BE_RCN, ssa_op->result_def);
3940
80
      break;
3941
1.62k
    case ZEND_TYPE_CHECK: {
3942
1.62k
      uint32_t expected_type_mask = opline->extended_value;
3943
1.62k
      if (t1 & MAY_BE_UNDEF) {
3944
202
        t1 |= MAY_BE_NULL;
3945
202
      }
3946
1.62k
      tmp = 0;
3947
1.62k
      if (t1 & expected_type_mask) {
3948
1.47k
        tmp |= MAY_BE_TRUE;
3949
1.47k
        if ((t1 & expected_type_mask) & MAY_BE_RESOURCE) {
3950
178
          tmp |= MAY_BE_FALSE;
3951
178
        }
3952
1.47k
      }
3953
1.62k
      if (t1 & (MAY_BE_ANY - expected_type_mask)) {
3954
1.48k
        tmp |= MAY_BE_FALSE;
3955
1.48k
      }
3956
1.62k
      UPDATE_SSA_TYPE(tmp, ssa_op->result_def);
3957
1.62k
      break;
3958
1.62k
    }
3959
1.62k
    case ZEND_DEFINED:
3960
150
      UPDATE_SSA_TYPE(MAY_BE_FALSE|MAY_BE_TRUE, ssa_op->result_def);
3961
150
      break;
3962
2.62k
    case ZEND_VERIFY_RETURN_TYPE:
3963
2.62k
      if (t1 & MAY_BE_REF) {
3964
90
        tmp = t1;
3965
90
        ce = NULL;
3966
2.53k
      } else {
3967
2.53k
        zend_arg_info *ret_info = op_array->arg_info - 1;
3968
2.53k
        tmp = zend_fetch_arg_info_type(script, ret_info, &ce);
3969
2.53k
        if ((tmp & MAY_BE_NULL) && opline->op1_type == IS_CV) {
3970
110
          tmp |= MAY_BE_UNDEF;
3971
110
        }
3972
2.53k
        tmp |= (t1 & MAY_BE_INDIRECT);
3973
3974
        // TODO: We could model more precisely how illegal types are converted.
3975
2.53k
        uint32_t extra_types = t1 & ~tmp;
3976
2.53k
        if (!extra_types) {
3977
1.66k
          tmp &= t1;
3978
1.66k
        }
3979
2.53k
      }
3980
2.62k
      if (opline->op1_type & (IS_TMP_VAR|IS_VAR|IS_CV)) {
3981
2.43k
        UPDATE_SSA_TYPE(tmp, ssa_op->op1_def);
3982
2.43k
        if (ce) {
3983
245
          UPDATE_SSA_OBJ_TYPE(ce, 1, ssa_op->op1_def);
3984
2.19k
        } else {
3985
2.19k
          UPDATE_SSA_OBJ_TYPE(NULL, 0, ssa_op->op1_def);
3986
2.19k
        }
3987
2.43k
      } else {
3988
185
        UPDATE_SSA_TYPE(tmp, ssa_op->result_def);
3989
185
        if (ce) {
3990
19
          UPDATE_SSA_OBJ_TYPE(ce, 1, ssa_op->result_def);
3991
166
        } else {
3992
166
          UPDATE_SSA_OBJ_TYPE(NULL, 0, ssa_op->result_def);
3993
166
        }
3994
185
      }
3995
2.62k
      break;
3996
2.62k
    case ZEND_MAKE_REF:
3997
1.37k
      tmp = MAY_BE_REF|MAY_BE_RC1|MAY_BE_RCN|MAY_BE_ANY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF;
3998
1.37k
      UPDATE_SSA_TYPE(tmp, ssa_op->result_def);
3999
1.37k
      if (ssa_op->op1_def >= 0) {
4000
336
        UPDATE_SSA_TYPE(tmp, ssa_op->op1_def);
4001
336
      }
4002
1.37k
      break;
4003
1.37k
    case ZEND_CATCH:
4004
      /* Forbidden opcodes */
4005
0
      ZEND_UNREACHABLE();
4006
0
      break;
4007
514
    case ZEND_FETCH_CLASS_NAME:
4008
514
      UPDATE_SSA_TYPE(MAY_BE_STRING|MAY_BE_RCN, ssa_op->result_def);
4009
514
      break;
4010
514
    case ZEND_ISSET_ISEMPTY_THIS:
4011
88
      UPDATE_SSA_TYPE(MAY_BE_BOOL, ssa_op->result_def);
4012
88
      break;
4013
7.73k
    case ZEND_DECLARE_LAMBDA_FUNCTION:
4014
7.73k
      UPDATE_SSA_TYPE(MAY_BE_OBJECT|MAY_BE_RC1|MAY_BE_RCN, ssa_op->result_def);
4015
7.73k
      UPDATE_SSA_OBJ_TYPE(zend_ce_closure, /* is_instanceof */ false, ssa_op->result_def);
4016
7.73k
      break;
4017
0
    case ZEND_PRE_DEC_STATIC_PROP:
4018
12
    case ZEND_PRE_INC_STATIC_PROP:
4019
34
    case ZEND_POST_DEC_STATIC_PROP:
4020
126
    case ZEND_POST_INC_STATIC_PROP: {
4021
126
      if (ssa_op->result_def >= 0) {
4022
126
        const zend_property_info *prop_info = zend_fetch_static_prop_info(script, op_array, ssa, opline);
4023
126
        zend_class_entry *prop_ce;
4024
126
        tmp = zend_fetch_prop_type(script, prop_info, &prop_ce);
4025
        /* Internal objects may result in essentially anything. */
4026
126
        if (tmp & MAY_BE_OBJECT) {
4027
114
          goto unknown_opcode;
4028
114
        }
4029
12
        tmp &= MAY_BE_LONG|MAY_BE_DOUBLE|MAY_BE_STRING|MAY_BE_BOOL|MAY_BE_NULL;
4030
12
        if (tmp & MAY_BE_STRING) {
4031
0
          tmp |= MAY_BE_RC1 | MAY_BE_RCN;
4032
0
        }
4033
12
        UPDATE_SSA_TYPE(tmp, ssa_op->result_def);
4034
12
      }
4035
12
      break;
4036
126
    }
4037
86
    case ZEND_SPACESHIP:
4038
86
      UPDATE_SSA_TYPE(MAY_BE_LONG, ssa_op->result_def);
4039
86
      break;
4040
705
    case ZEND_FETCH_GLOBALS:
4041
705
      UPDATE_SSA_TYPE(MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF|MAY_BE_RC1|MAY_BE_RCN, ssa_op->result_def);
4042
705
      break;
4043
1.60k
    default:
4044
#ifdef ZEND_DEBUG_TYPE_INFERENCE
4045
      if (ssa_op->result_def >= 0) {
4046
        switch (opline->opcode) {
4047
          case ZEND_FETCH_R:
4048
          case ZEND_FETCH_W:
4049
          case ZEND_FETCH_RW:
4050
          case ZEND_FETCH_IS:
4051
          case ZEND_FETCH_UNSET:
4052
          case ZEND_YIELD_FROM:
4053
          /* Currently unimplemented due to some assumptions in JIT. See:
4054
           * https://github.com/php/php-src/pull/13304#issuecomment-1926668141 */
4055
          case ZEND_SEPARATE:
4056
            break;
4057
          default:
4058
            fprintf(stderr, "Missing result type inference for opcode %s, line %d\n", zend_get_opcode_name(opline->opcode), opline->lineno);
4059
            break;
4060
        }
4061
      }
4062
      if (ssa_op->op1_def >= 0) {
4063
        fprintf(stderr, "Missing op1 type inference for opcode %s, line %d\n", zend_get_opcode_name(opline->opcode), opline->lineno);
4064
      }
4065
      if (ssa_op->op2_def >= 0) {
4066
        fprintf(stderr, "Missing op2 type inference for opcode %s, line %d\n", zend_get_opcode_name(opline->opcode), opline->lineno);
4067
      }
4068
#endif
4069
1.60k
      if (ssa_op->op1_def >= 0) {
4070
0
        tmp = MAY_BE_ANY | MAY_BE_REF | MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
4071
0
        UPDATE_SSA_TYPE(tmp, ssa_op->op1_def);
4072
0
      }
4073
22.9k
unknown_opcode:
4074
22.9k
      if (ssa_op->result_def >= 0) {
4075
22.9k
        tmp = MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
4076
22.9k
        if (opline->result_type == IS_TMP_VAR) {
4077
20.5k
          if (opline->opcode == ZEND_FETCH_R || opline->opcode == ZEND_FETCH_IS) {
4078
            /* Variable reference counter may be decremented before use */
4079
            /* See: ext/opcache/tests/jit/fetch_r_001.phpt */
4080
397
            tmp |= MAY_BE_RC1 | MAY_BE_RCN;
4081
20.1k
          } else {
4082
20.1k
            tmp |= MAY_BE_RC1 | MAY_BE_RCN;
4083
20.1k
          }
4084
20.5k
        } else if (opline->result_type == IS_CV) {
4085
0
          tmp |= MAY_BE_RC1 | MAY_BE_RCN;
4086
2.42k
        } else {
4087
2.42k
          tmp |= MAY_BE_REF | MAY_BE_RC1 | MAY_BE_RCN;
4088
2.42k
          switch (opline->opcode) {
4089
566
            case ZEND_FETCH_W:
4090
692
            case ZEND_FETCH_RW:
4091
715
            case ZEND_FETCH_FUNC_ARG:
4092
723
            case ZEND_FETCH_UNSET:
4093
723
            case ZEND_FETCH_DIM_W:
4094
723
            case ZEND_FETCH_DIM_RW:
4095
723
            case ZEND_FETCH_DIM_FUNC_ARG:
4096
723
            case ZEND_FETCH_DIM_UNSET:
4097
723
            case ZEND_FETCH_OBJ_W:
4098
723
            case ZEND_FETCH_OBJ_RW:
4099
723
            case ZEND_FETCH_OBJ_FUNC_ARG:
4100
723
            case ZEND_FETCH_OBJ_UNSET:
4101
723
            case ZEND_FETCH_STATIC_PROP_W:
4102
723
            case ZEND_FETCH_STATIC_PROP_RW:
4103
723
            case ZEND_FETCH_STATIC_PROP_FUNC_ARG:
4104
723
            case ZEND_FETCH_STATIC_PROP_UNSET:
4105
723
              tmp |= MAY_BE_INDIRECT;
4106
723
              break;
4107
2.42k
          }
4108
2.42k
        }
4109
22.9k
        UPDATE_SSA_TYPE(tmp, ssa_op->result_def);
4110
22.9k
      }
4111
22.9k
      break;
4112
1.16M
  }
4113
4114
1.16M
  return SUCCESS;
4115
1.16M
}
4116
4117
ZEND_API zend_result zend_update_type_info(
4118
      const zend_op_array *op_array,
4119
      zend_ssa            *ssa,
4120
      const zend_script   *script,
4121
      const zend_op       *opline,
4122
      zend_ssa_op         *ssa_op,
4123
      const zend_op      **ssa_opcodes,
4124
      zend_long            optimization_level)
4125
0
{
4126
0
  return _zend_update_type_info(op_array, ssa, script, NULL, opline, ssa_op, ssa_opcodes, optimization_level,
4127
0
              false);
4128
0
}
4129
4130
34
static uint32_t get_class_entry_rank(const zend_class_entry *ce) {
4131
34
  uint32_t rank = 0;
4132
34
  if (ce->ce_flags & ZEND_ACC_LINKED) {
4133
34
    while (ce->parent) {
4134
0
      rank++;
4135
0
      ce = ce->parent;
4136
0
    }
4137
34
  }
4138
34
  return rank;
4139
34
}
4140
4141
/* Compute least common ancestor on class inheritance tree only */
4142
static zend_class_entry *join_class_entries(
4143
68.7k
    zend_class_entry *ce1, zend_class_entry *ce2, bool *is_instanceof) {
4144
68.7k
  uint32_t rank1, rank2;
4145
68.7k
  if (ce1 == ce2) {
4146
68.2k
    return ce1;
4147
68.2k
  }
4148
463
  if (!ce1 || !ce2) {
4149
446
    return NULL;
4150
446
  }
4151
4152
17
  rank1 = get_class_entry_rank(ce1);
4153
17
  rank2 = get_class_entry_rank(ce2);
4154
4155
17
  while (rank1 != rank2) {
4156
0
    if (rank1 > rank2) {
4157
0
      ce1 = !(ce1->ce_flags & ZEND_ACC_LINKED) ? NULL : ce1->parent;
4158
0
      rank1--;
4159
0
    } else {
4160
0
      ce2 = !(ce2->ce_flags & ZEND_ACC_LINKED) ? NULL : ce2->parent;
4161
0
      rank2--;
4162
0
    }
4163
0
  }
4164
4165
34
  while (ce1 != ce2) {
4166
17
    ce1 = !(ce1->ce_flags & ZEND_ACC_LINKED) ? NULL : ce1->parent;
4167
17
    ce2 = !(ce2->ce_flags & ZEND_ACC_LINKED) ? NULL : ce2->parent;
4168
17
  }
4169
4170
17
  if (ce1) {
4171
0
    *is_instanceof = true;
4172
0
  }
4173
17
  return ce1;
4174
463
}
4175
4176
0
static bool safe_instanceof(const zend_class_entry *ce1, const zend_class_entry *ce2) {
4177
0
  if (ce1 == ce2) {
4178
0
    return 1;
4179
0
  }
4180
0
  if (!(ce1->ce_flags & ZEND_ACC_LINKED)) {
4181
    /* This case could be generalized, similarly to unlinked_instanceof */
4182
0
    return 0;
4183
0
  }
4184
0
  return instanceof_function(ce1, ce2);
4185
0
}
4186
4187
static zend_result zend_infer_types_ex(const zend_op_array *op_array, const zend_script *script, zend_ssa *ssa, zend_bitset worklist, zend_long optimization_level)
4188
89.1k
{
4189
89.1k
  const zend_basic_block *blocks = ssa->cfg.blocks;
4190
89.1k
  zend_ssa_var *ssa_vars = ssa->vars;
4191
89.1k
  zend_ssa_var_info *ssa_var_info = ssa->var_info;
4192
89.1k
  int ssa_vars_count = ssa->vars_count;
4193
89.1k
  int j;
4194
89.1k
  uint32_t tmp, worklist_len = zend_bitset_len(ssa_vars_count);
4195
89.1k
  bool update_worklist = 1;
4196
89.1k
  const zend_op **ssa_opcodes = NULL;
4197
4198
1.47M
  while (!zend_bitset_empty(worklist, worklist_len)) {
4199
1.38M
    j = zend_bitset_first(worklist, worklist_len);
4200
1.38M
    zend_bitset_excl(worklist, j);
4201
1.38M
    if (ssa_vars[j].definition_phi) {
4202
219k
      zend_ssa_phi *p = ssa_vars[j].definition_phi;
4203
219k
      if (p->pi >= 0) {
4204
57.7k
        zend_class_entry *ce = ssa_var_info[p->sources[0]].ce;
4205
57.7k
        bool is_instanceof = ssa_var_info[p->sources[0]].is_instanceof;
4206
57.7k
        tmp = get_ssa_var_info(ssa, p->sources[0]);
4207
4208
57.7k
        if (!p->has_range_constraint) {
4209
39.4k
          const zend_ssa_type_constraint *constraint = &p->constraint.type;
4210
39.4k
          tmp &= constraint->type_mask;
4211
39.4k
          if (!(tmp & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE))) {
4212
1.68k
            tmp &= ~(MAY_BE_RC1|MAY_BE_RCN);
4213
1.68k
          }
4214
39.4k
          if ((tmp & MAY_BE_OBJECT) && constraint->ce && ce != constraint->ce) {
4215
28
            if (!ce) {
4216
28
              ce = constraint->ce;
4217
28
              is_instanceof = true;
4218
28
            } else if (is_instanceof && safe_instanceof(constraint->ce, ce)) {
4219
0
              ce = constraint->ce;
4220
0
            } else {
4221
              /* Ignore the constraint (either ce instanceof constraint->ce or
4222
               * they are unrelated, as far as we can statically determine) */
4223
0
            }
4224
28
          }
4225
39.4k
        }
4226
4227
57.7k
        UPDATE_SSA_TYPE(tmp, j);
4228
57.7k
        if (tmp & MAY_BE_REF) {
4229
31.8k
          UPDATE_SSA_OBJ_TYPE(NULL, 0, j);
4230
31.8k
        } else {
4231
25.8k
          UPDATE_SSA_OBJ_TYPE(ce, is_instanceof, j);
4232
25.8k
        }
4233
161k
      } else {
4234
161k
        bool first = true;
4235
161k
        bool is_instanceof = false;
4236
161k
        zend_class_entry *ce = NULL;
4237
161k
        uint32_t i;
4238
4239
161k
        tmp = 0;
4240
498k
        for (i = 0; i < blocks[p->block].predecessors_count; i++) {
4241
336k
          tmp |= get_ssa_var_info(ssa, p->sources[i]);
4242
336k
        }
4243
161k
        UPDATE_SSA_TYPE(tmp, j);
4244
498k
        for (i = 0; i < blocks[p->block].predecessors_count; i++) {
4245
336k
          zend_ssa_var_info *info;
4246
4247
336k
          ZEND_ASSERT(p->sources[i] >= 0);
4248
336k
          info = &ssa_var_info[p->sources[i]];
4249
336k
          if (info->type & MAY_BE_OBJECT) {
4250
176k
            if (first) {
4251
107k
              ce = info->ce;
4252
107k
              is_instanceof = info->is_instanceof;
4253
107k
              first = false;
4254
107k
            } else {
4255
68.7k
              is_instanceof |= info->is_instanceof;
4256
68.7k
              ce = join_class_entries(ce, info->ce, &is_instanceof);
4257
68.7k
            }
4258
176k
          }
4259
336k
        }
4260
161k
        UPDATE_SSA_OBJ_TYPE(ce, ce ? is_instanceof : 0, j);
4261
161k
      }
4262
1.16M
    } else if (ssa_vars[j].definition >= 0) {
4263
1.16M
      int i = ssa_vars[j].definition;
4264
1.16M
      if (_zend_update_type_info(op_array, ssa, script, worklist, op_array->opcodes + i, ssa->ops + i, NULL, optimization_level, true) == FAILURE) {
4265
0
        return FAILURE;
4266
0
      }
4267
1.16M
    }
4268
1.38M
  }
4269
89.1k
  return SUCCESS;
4270
89.1k
}
4271
4272
4.32k
static bool is_narrowable_instr(const zend_op *opline)  {
4273
4.32k
  return opline->opcode == ZEND_ADD || opline->opcode == ZEND_SUB
4274
4.04k
    || opline->opcode == ZEND_MUL || opline->opcode == ZEND_DIV;
4275
4.32k
}
4276
4277
70
static bool is_effective_op1_double_cast(const zend_op *opline, const zval *op2) {
4278
70
  return (opline->opcode == ZEND_ADD && Z_LVAL_P(op2) == 0)
4279
48
    || (opline->opcode == ZEND_SUB && Z_LVAL_P(op2) == 0)
4280
46
    || (opline->opcode == ZEND_MUL && Z_LVAL_P(op2) == 1)
4281
46
    || (opline->opcode == ZEND_DIV && Z_LVAL_P(op2) == 1);
4282
70
}
4283
33
static bool is_effective_op2_double_cast(const zend_op *opline, const zval *op1) {
4284
  /* In PHP it holds that (double)(0-$int) is bitwise identical to 0.0-(double)$int,
4285
   * so allowing SUB here is fine. */
4286
33
  return (opline->opcode == ZEND_ADD && Z_LVAL_P(op1) == 0)
4287
16
    || (opline->opcode == ZEND_SUB && Z_LVAL_P(op1) == 0)
4288
12
    || (opline->opcode == ZEND_MUL && Z_LVAL_P(op1) == 1);
4289
33
}
4290
4291
/* This function recursively checks whether it's possible to convert an integer variable
4292
 * initialization to a double initialization. The basic idea is that if the value is used
4293
 * only in add/sub/mul/div ("narrowable" instructions) with a double result value, then it
4294
 * will be cast to double at that point anyway, so we may as well do it earlier already.
4295
 *
4296
 * The tricky case are chains of operations, where it's not necessarily a given that converting
4297
 * an integer to double before the chain of operations is the same as converting it after the
4298
 * chain. What this function does is detect two cases where it is safe:
4299
 *  * If the operations only involve constants, then we can simply verify that performing the
4300
 *    calculation on integers and doubles yields the same value.
4301
 *  * Even if one operand is not known, we may be able to determine that the operations with the
4302
 *    integer replaced by a double only acts as an effective double cast on the unknown operand.
4303
 *    E.g. 0+$i and 0.0+$i only differ by that cast. If then the consuming instruction of this
4304
 *    result will perform a double cast anyway, the conversion is safe.
4305
 *
4306
 * The checks happens recursively, while keeping track of which variables are already visited to
4307
 * avoid infinite loops. An iterative, worklist driven approach would be possible, but the state
4308
 * management more cumbersome to implement, so we don't bother for now.
4309
 */
4310
static bool can_convert_to_double(
4311
    const zend_op_array *op_array, zend_ssa *ssa, int var_num,
4312
8.40k
    zval *value, zend_bitset visited) {
4313
8.40k
  zend_ssa_var *var = &ssa->vars[var_num];
4314
8.40k
  zend_ssa_phi *phi;
4315
8.40k
  int use;
4316
8.40k
  uint32_t type;
4317
4318
8.40k
  if (zend_bitset_in(visited, var_num)) {
4319
6
    return 1;
4320
6
  }
4321
8.39k
  zend_bitset_incl(visited, var_num);
4322
4323
8.79k
  for (use = var->use_chain; use >= 0; use = zend_ssa_next_use(ssa->ops, var_num, use)) {
4324
4.65k
    zend_op *opline = &op_array->opcodes[use];
4325
4.65k
    zend_ssa_op *ssa_op = &ssa->ops[use];
4326
4327
4.65k
    if (zend_ssa_is_no_val_use(opline, ssa_op, var_num)) {
4328
330
      continue;
4329
330
    }
4330
4331
4.32k
    if (!is_narrowable_instr(opline)) {
4332
4.01k
      return 0;
4333
4.01k
    }
4334
4335
    /* Instruction always returns double, the conversion is certainly fine */
4336
304
    type = ssa->var_info[ssa_op->result_def].type;
4337
304
    if ((type & MAY_BE_ANY) == MAY_BE_DOUBLE) {
4338
34
      continue;
4339
34
    }
4340
4341
    /* UNDEF signals that the previous result is an effective double cast, this is only allowed
4342
     * if this instruction would have done the cast anyway (previous check). */
4343
270
    if (Z_ISUNDEF_P(value)) {
4344
2
      return 0;
4345
2
    }
4346
4347
    /* Check that narrowing can actually be useful */
4348
268
    if ((type & MAY_BE_ANY) & ~(MAY_BE_LONG|MAY_BE_DOUBLE)) {
4349
112
      return 0;
4350
112
    }
4351
4352
156
    {
4353
      /* For calculation on original values */
4354
156
      zval orig_op1, orig_op2, orig_result;
4355
      /* For calculation with var_num cast to double */
4356
156
      zval dval_op1, dval_op2, dval_result;
4357
4358
156
      ZVAL_UNDEF(&orig_op1);
4359
156
      ZVAL_UNDEF(&dval_op1);
4360
156
      if (ssa_op->op1_use == var_num) {
4361
83
        ZVAL_COPY_VALUE(&orig_op1, value);
4362
83
        ZVAL_DOUBLE(&dval_op1, (double) Z_LVAL_P(value));
4363
83
      } else if (opline->op1_type == IS_CONST) {
4364
3
        zval *zv = CRT_CONSTANT(opline->op1);
4365
3
        if (Z_TYPE_P(zv) == IS_LONG || Z_TYPE_P(zv) == IS_DOUBLE) {
4366
3
          ZVAL_COPY_VALUE(&orig_op1, zv);
4367
3
          ZVAL_COPY_VALUE(&dval_op1, zv);
4368
3
        }
4369
3
      }
4370
4371
156
      ZVAL_UNDEF(&orig_op2);
4372
156
      ZVAL_UNDEF(&dval_op2);
4373
156
      if (ssa_op->op2_use == var_num) {
4374
73
        ZVAL_COPY_VALUE(&orig_op2, value);
4375
73
        ZVAL_DOUBLE(&dval_op2, (double) Z_LVAL_P(value));
4376
83
      } else if (opline->op2_type == IS_CONST) {
4377
52
        zval *zv = CRT_CONSTANT(opline->op2);
4378
52
        if (Z_TYPE_P(zv) == IS_LONG || Z_TYPE_P(zv) == IS_DOUBLE) {
4379
50
          ZVAL_COPY_VALUE(&orig_op2, zv);
4380
50
          ZVAL_COPY_VALUE(&dval_op2, zv);
4381
50
        }
4382
52
      }
4383
4384
156
      ZEND_ASSERT(!Z_ISUNDEF(orig_op1) || !Z_ISUNDEF(orig_op2));
4385
156
      if (Z_ISUNDEF(orig_op1)) {
4386
70
        if (opline->opcode == ZEND_MUL && Z_LVAL(orig_op2) == 0) {
4387
0
          ZVAL_LONG(&orig_result, 0);
4388
70
        } else if (is_effective_op1_double_cast(opline, &orig_op2)) {
4389
24
          ZVAL_UNDEF(&orig_result);
4390
46
        } else {
4391
46
          return 0;
4392
46
        }
4393
86
      } else if (Z_ISUNDEF(orig_op2)) {
4394
33
        if (opline->opcode == ZEND_MUL && Z_LVAL(orig_op1) == 0) {
4395
0
          ZVAL_LONG(&orig_result, 0);
4396
33
        } else if (is_effective_op2_double_cast(opline, &orig_op1)) {
4397
21
          ZVAL_UNDEF(&orig_result);
4398
21
        } else {
4399
12
          return 0;
4400
12
        }
4401
53
      } else {
4402
53
        uint8_t opcode = opline->opcode;
4403
4404
53
        if (opcode == ZEND_ASSIGN_OP) {
4405
0
          opcode = opline->extended_value;
4406
0
        }
4407
4408
        /* Avoid division by zero */
4409
53
        if (opcode == ZEND_DIV && zval_get_double(&orig_op2) == 0.0) {
4410
0
          return 0;
4411
0
        }
4412
4413
53
        get_binary_op(opcode)(&orig_result, &orig_op1, &orig_op2);
4414
53
        get_binary_op(opcode)(&dval_result, &dval_op1, &dval_op2);
4415
53
        ZEND_ASSERT(Z_TYPE(dval_result) == IS_DOUBLE);
4416
53
        if (zval_get_double(&orig_result) != Z_DVAL(dval_result)) {
4417
4
          return 0;
4418
4
        }
4419
53
      }
4420
4421
94
      if (!can_convert_to_double(op_array, ssa, ssa_op->result_def, &orig_result, visited)) {
4422
66
        return 0;
4423
66
      }
4424
94
    }
4425
94
  }
4426
4427
4.16k
  for (phi = var->phi_use_chain; phi; phi = zend_ssa_next_use_phi(ssa, var_num, phi)) {
4428
    /* Check that narrowing can actually be useful */
4429
4.09k
    type = ssa->var_info[phi->ssa_var].type;
4430
4.09k
    if ((type & MAY_BE_ANY) & ~(MAY_BE_LONG|MAY_BE_DOUBLE)) {
4431
402
      return 0;
4432
402
    }
4433
4434
3.69k
    if (!can_convert_to_double(op_array, ssa, phi->ssa_var, value, visited)) {
4435
3.67k
      return 0;
4436
3.67k
    }
4437
3.69k
  }
4438
4439
62
  return 1;
4440
4.14k
}
4441
4442
static zend_result zend_type_narrowing(const zend_op_array *op_array, const zend_script *script, zend_ssa *ssa, zend_long optimization_level)
4443
89.1k
{
4444
89.1k
  uint32_t bitset_len = zend_bitset_len(ssa->vars_count);
4445
89.1k
  zend_bitset visited, worklist;
4446
89.1k
  int i, v;
4447
89.1k
  zend_op *opline;
4448
89.1k
  bool narrowed = 0;
4449
89.1k
  ALLOCA_FLAG(use_heap)
4450
4451
89.1k
  visited = ZEND_BITSET_ALLOCA(2 * bitset_len, use_heap);
4452
89.1k
  worklist = visited + bitset_len;
4453
4454
89.1k
  zend_bitset_clear(worklist, bitset_len);
4455
4456
1.41M
  for (v = op_array->last_var; v < ssa->vars_count; v++) {
4457
1.32M
    if ((ssa->var_info[v].type & (MAY_BE_REF | MAY_BE_ANY | MAY_BE_UNDEF)) != MAY_BE_LONG) continue;
4458
127k
    if (ssa->vars[v].definition < 0) continue;
4459
117k
    if (ssa->vars[v].no_val) continue;
4460
114k
    opline = op_array->opcodes + ssa->vars[v].definition;
4461
    /* Go through assignments of literal integers and check if they can be converted to
4462
     * doubles instead, in the hope that we'll narrow long|double to double. */
4463
114k
    if (opline->opcode == ZEND_ASSIGN && opline->result_type == IS_UNUSED &&
4464
6.07k
        opline->op1_type == IS_CV && opline->op2_type == IS_CONST) {
4465
4.61k
      zval *value = CRT_CONSTANT(opline->op2);
4466
4467
4.61k
      zend_bitset_clear(visited, bitset_len);
4468
4.61k
      if (can_convert_to_double(op_array, ssa, v, value, visited)) {
4469
20
        narrowed = 1;
4470
20
        ssa->var_info[v].use_as_double = 1;
4471
        /* The "visited" vars are exactly those which may change their type due to
4472
         * narrowing. Reset their types and add them to the type inference worklist */
4473
486
        ZEND_BITSET_FOREACH(visited, bitset_len, i) {
4474
48
          ssa->var_info[i].type &= ~MAY_BE_ANY;
4475
48
        } ZEND_BITSET_FOREACH_END();
4476
20
        zend_bitset_union(worklist, visited, bitset_len);
4477
20
      }
4478
4.61k
    }
4479
114k
  }
4480
4481
89.1k
  if (!narrowed) {
4482
89.0k
    free_alloca(visited, use_heap);
4483
89.0k
    return SUCCESS;
4484
89.0k
  }
4485
4486
20
  if (zend_infer_types_ex(op_array, script, ssa, worklist, optimization_level) == FAILURE) {
4487
0
    free_alloca(visited, use_heap);
4488
0
    return FAILURE;
4489
0
  }
4490
4491
20
  free_alloca(visited, use_heap);
4492
20
  return SUCCESS;
4493
20
}
4494
4495
static bool is_recursive_tail_call(const zend_op_array *op_array, const zend_op *opline)
4496
87.6k
{
4497
87.6k
  const zend_func_info *info = ZEND_FUNC_INFO(op_array);
4498
4499
87.6k
  if (info->ssa.ops && info->ssa.vars && info->call_map &&
4500
41.8k
      info->ssa.ops[opline - op_array->opcodes].op1_use >= 0 &&
4501
3.61k
      info->ssa.vars[info->ssa.ops[opline - op_array->opcodes].op1_use].definition >= 0) {
4502
4503
3.54k
    const zend_op *op = op_array->opcodes + info->ssa.vars[info->ssa.ops[opline - op_array->opcodes].op1_use].definition;
4504
4505
3.54k
    if (op->opcode == ZEND_DO_UCALL) {
4506
335
      const zend_call_info *call_info = info->call_map[op - op_array->opcodes];
4507
335
      if (call_info && op_array == &call_info->callee_func->op_array) {
4508
8
        return 1;
4509
8
      }
4510
335
    }
4511
3.54k
  }
4512
87.6k
  return 0;
4513
87.6k
}
4514
4515
uint32_t zend_get_return_info_from_signature_only(
4516
    const zend_function *func, const zend_script *script,
4517
38.1k
    zend_class_entry **ce, bool *ce_is_instanceof, bool use_tentative_return_info) {
4518
38.1k
  uint32_t type;
4519
38.1k
  if (func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE &&
4520
29.7k
    (use_tentative_return_info || !ZEND_ARG_TYPE_IS_TENTATIVE(func->common.arg_info - 1))
4521
38.1k
  ) {
4522
29.7k
    const zend_arg_info *ret_info = func->common.arg_info - 1;
4523
29.7k
    type = zend_fetch_arg_info_type(script, ret_info, ce);
4524
29.7k
    *ce_is_instanceof = ce != NULL;
4525
29.7k
  } else {
4526
8.40k
    type = MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF
4527
8.40k
      | MAY_BE_RC1 | MAY_BE_RCN;
4528
8.40k
    *ce = NULL;
4529
8.40k
    *ce_is_instanceof = false;
4530
8.40k
  }
4531
4532
  /* For generators RETURN_REFERENCE refers to the yielded values. */
4533
38.1k
  if ((func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE)
4534
1.43k
      && !(func->common.fn_flags & ZEND_ACC_GENERATOR)) {
4535
1.35k
    type |= MAY_BE_REF;
4536
1.35k
    *ce = NULL;
4537
1.35k
    *ce_is_instanceof = false;
4538
1.35k
  }
4539
38.1k
  return type;
4540
38.1k
}
4541
4542
ZEND_API void zend_init_func_return_info(
4543
  const zend_op_array *op_array, const zend_script *script, zend_ssa_var_info *ret)
4544
8.66k
{
4545
8.66k
  ZEND_ASSERT((op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE));
4546
4547
8.66k
  zend_ssa_range tmp_range = {0, 0, 0, 0};
4548
8.66k
  bool is_instanceof = false;
4549
8.66k
  ret->type = zend_get_return_info_from_signature_only(
4550
8.66k
    (zend_function *) op_array, script, &ret->ce, &is_instanceof, /* use_tentative_return_info */ true);
4551
8.66k
  ret->is_instanceof = is_instanceof;
4552
8.66k
  ret->range = tmp_range;
4553
8.66k
  ret->has_range = 0;
4554
8.66k
}
4555
4556
static void zend_func_return_info(const zend_op_array   *op_array,
4557
                                  const zend_script     *script,
4558
                                  bool                   recursive,
4559
                                  bool                   widening,
4560
                                  zend_ssa_var_info     *ret)
4561
89.1k
{
4562
89.1k
  const zend_func_info *info = ZEND_FUNC_INFO(op_array);
4563
89.1k
  const zend_ssa *ssa = &info->ssa;
4564
89.1k
  uint32_t blocks_count = info->ssa.cfg.blocks_count;
4565
89.1k
  const zend_basic_block *blocks = info->ssa.cfg.blocks;
4566
89.1k
  uint32_t t1;
4567
89.1k
  uint32_t tmp = 0;
4568
89.1k
  zend_class_entry *tmp_ce = NULL;
4569
89.1k
  int tmp_is_instanceof = -1;
4570
89.1k
  zend_class_entry *arg_ce;
4571
89.1k
  bool arg_is_instanceof;
4572
89.1k
  zend_ssa_range tmp_range = {0, 0, 0, 0};
4573
89.1k
  int tmp_has_range = -1;
4574
4575
89.1k
  if (op_array->fn_flags & ZEND_ACC_GENERATOR) {
4576
1.99k
    ret->type = MAY_BE_OBJECT | MAY_BE_RC1 | MAY_BE_RCN;
4577
1.99k
    ret->ce = zend_ce_generator;
4578
1.99k
    ret->is_instanceof = 0;
4579
1.99k
    ret->range = tmp_range;
4580
1.99k
    ret->has_range = 0;
4581
1.99k
    return;
4582
1.99k
  }
4583
4584
87.1k
  if (!ret->type) {
4585
    /* We will intersect the type later. */
4586
78.7k
    ret->type = MAY_BE_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF | MAY_BE_ARRAY_KEY_ANY
4587
78.7k
      | MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_REF;
4588
78.7k
  }
4589
4590
344k
  for (uint32_t j = 0; j < blocks_count; j++) {
4591
257k
    if ((blocks[j].flags & ZEND_BB_REACHABLE) && blocks[j].len != 0) {
4592
257k
      zend_op *opline = op_array->opcodes + blocks[j].start + blocks[j].len - 1;
4593
4594
257k
      if (opline->opcode == ZEND_RETURN || opline->opcode == ZEND_RETURN_BY_REF) {
4595
87.6k
        const zend_ssa_op *ssa_op = ssa->ops ? &ssa->ops[opline - op_array->opcodes] : NULL;
4596
87.6k
        if (!recursive && ssa_op && info->ssa.var_info &&
4597
0
            ssa_op->op1_use >= 0 &&
4598
0
            info->ssa.var_info[ssa_op->op1_use].recursive) {
4599
0
          continue;
4600
0
        }
4601
87.6k
        if (is_recursive_tail_call(op_array, opline)) {
4602
8
          continue;
4603
8
        }
4604
87.6k
        t1 = OP1_INFO();
4605
87.6k
        if (t1 & MAY_BE_UNDEF) {
4606
348
          t1 |= MAY_BE_NULL;
4607
348
        }
4608
87.6k
        if (opline->opcode == ZEND_RETURN) {
4609
86.2k
          if (t1 & MAY_BE_RC1) {
4610
8.61k
            t1 |= MAY_BE_RCN;
4611
8.61k
          }
4612
86.2k
          t1 &= ~(MAY_BE_UNDEF | MAY_BE_REF);
4613
86.2k
        } else {
4614
1.36k
          t1 |= MAY_BE_REF;
4615
1.36k
          t1 &= ~(MAY_BE_UNDEF | MAY_BE_RC1 | MAY_BE_RCN);
4616
1.36k
        }
4617
87.6k
        tmp |= t1;
4618
4619
87.6k
        if (ssa_op && info->ssa.var_info &&
4620
87.6k
            ssa_op->op1_use >= 0 && !(t1 & MAY_BE_REF) &&
4621
11.8k
            info->ssa.var_info[ssa_op->op1_use].ce) {
4622
1.98k
          arg_ce = info->ssa.var_info[ssa_op->op1_use].ce;
4623
1.98k
          arg_is_instanceof = info->ssa.var_info[ssa_op->op1_use].is_instanceof;
4624
85.6k
        } else {
4625
85.6k
          arg_ce = NULL;
4626
85.6k
          arg_is_instanceof = false;
4627
85.6k
        }
4628
4629
87.6k
        if (tmp_is_instanceof < 0) {
4630
84.7k
          tmp_ce = arg_ce;
4631
84.7k
          tmp_is_instanceof = arg_is_instanceof;
4632
84.7k
        } else if (arg_ce && arg_ce == tmp_ce) {
4633
38
          if (tmp_is_instanceof != arg_is_instanceof) {
4634
0
            tmp_is_instanceof = 1;
4635
0
          }
4636
2.81k
        } else {
4637
2.81k
          tmp_ce = NULL;
4638
2.81k
          tmp_is_instanceof = 0;
4639
2.81k
        }
4640
4641
87.6k
        if (opline->op1_type == IS_CONST) {
4642
74.5k
          const zval *zv = CRT_CONSTANT(opline->op1);
4643
4644
74.5k
          if (Z_TYPE_P(zv) == IS_LONG) {
4645
39.8k
            if (tmp_has_range < 0) {
4646
39.4k
              tmp_has_range = 1;
4647
39.4k
              tmp_range.underflow = 0;
4648
39.4k
              tmp_range.min = Z_LVAL_P(zv);
4649
39.4k
              tmp_range.max = Z_LVAL_P(zv);
4650
39.4k
              tmp_range.overflow = 0;
4651
39.4k
            } else if (tmp_has_range) {
4652
264
              if (!tmp_range.underflow) {
4653
131
                tmp_range.min = MIN(tmp_range.min, Z_LVAL_P(zv));
4654
131
              }
4655
264
              if (!tmp_range.overflow) {
4656
131
                tmp_range.max = MAX(tmp_range.max, Z_LVAL_P(zv));
4657
131
              }
4658
264
            }
4659
39.8k
          } else {
4660
34.7k
            tmp_has_range = 0;
4661
34.7k
          }
4662
74.5k
        } else if (ssa_op && info->ssa.var_info && ssa_op->op1_use >= 0) {
4663
13.0k
          if (info->ssa.var_info[ssa_op->op1_use].has_range) {
4664
12.3k
            if (tmp_has_range < 0) {
4665
11.3k
              tmp_has_range = 1;
4666
11.3k
              tmp_range = info->ssa.var_info[ssa_op->op1_use].range;
4667
11.3k
            } else if (tmp_has_range) {
4668
              /* union */
4669
819
              if (info->ssa.var_info[ssa_op->op1_use].range.underflow) {
4670
809
                tmp_range.underflow = 1;
4671
809
                tmp_range.min = ZEND_LONG_MIN;
4672
809
              } else {
4673
10
                tmp_range.min = MIN(tmp_range.min, info->ssa.var_info[ssa_op->op1_use].range.min);
4674
10
              }
4675
819
              if (info->ssa.var_info[ssa_op->op1_use].range.overflow) {
4676
809
                tmp_range.overflow = 1;
4677
809
                tmp_range.max = ZEND_LONG_MAX;
4678
809
              } else {
4679
10
                tmp_range.max = MAX(tmp_range.max, info->ssa.var_info[ssa_op->op1_use].range.max);
4680
10
              }
4681
819
            }
4682
12.3k
          } else if (!widening) {
4683
696
            tmp_has_range = 1;
4684
696
            tmp_range.underflow = 1;
4685
696
            tmp_range.min = ZEND_LONG_MIN;
4686
696
            tmp_range.max = ZEND_LONG_MAX;
4687
696
            tmp_range.overflow = 1;
4688
696
          }
4689
13.0k
        } else {
4690
0
          tmp_has_range = 0;
4691
0
        }
4692
87.6k
      }
4693
257k
    }
4694
257k
  }
4695
4696
87.1k
  if (!(op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE)) {
4697
78.7k
    if (tmp_is_instanceof < 0) {
4698
2.18k
      tmp_is_instanceof = 0;
4699
2.18k
      tmp_ce = NULL;
4700
2.18k
    }
4701
78.7k
    if (tmp_has_range < 0) {
4702
2.18k
      tmp_has_range = 0;
4703
2.18k
    }
4704
78.7k
    ret->ce = tmp_ce;
4705
78.7k
    ret->is_instanceof = tmp_is_instanceof;
4706
78.7k
  }
4707
87.1k
  ret->type &= tmp;
4708
87.1k
  ret->range = tmp_range;
4709
87.1k
  ret->has_range = tmp_has_range;
4710
87.1k
}
4711
4712
static zend_result zend_infer_types(const zend_op_array *op_array, const zend_script *script, zend_ssa *ssa, zend_long optimization_level)
4713
89.1k
{
4714
89.1k
  int ssa_vars_count = ssa->vars_count;
4715
89.1k
  int j;
4716
89.1k
  zend_bitset worklist;
4717
89.1k
  ALLOCA_FLAG(use_heap);
4718
4719
89.1k
  worklist = do_alloca(sizeof(zend_ulong) * zend_bitset_len(ssa_vars_count), use_heap);
4720
89.1k
  memset(worklist, 0, sizeof(zend_ulong) * zend_bitset_len(ssa_vars_count));
4721
4722
  /* Type Inference */
4723
1.41M
  for (j = op_array->last_var; j < ssa_vars_count; j++) {
4724
1.32M
    zend_bitset_incl(worklist, j);
4725
1.32M
  }
4726
4727
89.1k
  if (zend_infer_types_ex(op_array, script, ssa, worklist, optimization_level) == FAILURE) {
4728
0
    free_alloca(worklist,  use_heap);
4729
0
    return FAILURE;
4730
0
  }
4731
4732
89.1k
  if (optimization_level & ZEND_OPTIMIZER_NARROW_TO_DOUBLE) {
4733
    /* Narrowing integer initialization to doubles */
4734
89.1k
    zend_type_narrowing(op_array, script, ssa, optimization_level);
4735
89.1k
  }
4736
4737
89.1k
  if (ZEND_FUNC_INFO(op_array)) {
4738
89.1k
    zend_func_return_info(op_array, script, 1, 0, &ZEND_FUNC_INFO(op_array)->return_info);
4739
89.1k
  }
4740
4741
89.1k
  free_alloca(worklist,  use_heap);
4742
89.1k
  return SUCCESS;
4743
89.1k
}
4744
4745
static void zend_mark_cv_references(const zend_op_array *op_array, const zend_script *script, const zend_ssa *ssa)
4746
89.1k
{
4747
89.1k
  int var, def;
4748
89.1k
  const zend_op *opline;
4749
89.1k
  zend_arg_info *arg_info;
4750
89.1k
  uint32_t worklist_len = zend_bitset_len(ssa->vars_count);
4751
89.1k
  zend_bitset worklist;
4752
89.1k
  ALLOCA_FLAG(use_heap);
4753
4754
89.1k
  worklist = do_alloca(sizeof(zend_ulong) * worklist_len, use_heap);
4755
89.1k
  memset(worklist, 0, sizeof(zend_ulong) * worklist_len);
4756
4757
  /* Collect SSA variables which definitions creates PHP reference */
4758
1.57M
  for (var = 0; var < ssa->vars_count; var++) {
4759
1.48M
    def = ssa->vars[var].definition;
4760
1.48M
    if (def >= 0 && ssa->vars[var].var < op_array->last_var) {
4761
192k
      opline = op_array->opcodes + def;
4762
192k
      if (ssa->ops[def].result_def == var) {
4763
32.6k
        switch (opline->opcode) {
4764
27.6k
          case ZEND_RECV:
4765
32.0k
          case ZEND_RECV_INIT:
4766
32.0k
            arg_info = &op_array->arg_info[opline->op1.num-1];
4767
32.0k
            if (!ZEND_ARG_SEND_MODE(arg_info)) {
4768
29.6k
              continue;
4769
29.6k
            }
4770
2.34k
            break;
4771
2.34k
          default:
4772
626
            continue;
4773
32.6k
        }
4774
159k
      } else if (ssa->ops[def].op1_def == var) {
4775
152k
        switch (opline->opcode) {
4776
2.78k
          case ZEND_ASSIGN_REF:
4777
2.96k
          case ZEND_MAKE_REF:
4778
3.79k
          case ZEND_FE_RESET_RW:
4779
4.86k
          case ZEND_BIND_GLOBAL:
4780
7.47k
          case ZEND_SEND_REF:
4781
14.7k
          case ZEND_SEND_VAR_EX:
4782
14.7k
          case ZEND_SEND_FUNC_ARG:
4783
14.9k
          case ZEND_BIND_INIT_STATIC_OR_JMP:
4784
14.9k
            break;
4785
268
          case ZEND_INIT_ARRAY:
4786
330
          case ZEND_ADD_ARRAY_ELEMENT:
4787
330
            if (!(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
4788
0
              continue;
4789
0
            }
4790
330
            break;
4791
9.49k
          case ZEND_BIND_STATIC:
4792
9.49k
            if (!(opline->extended_value & ZEND_BIND_REF)) {
4793
8.08k
              continue;
4794
8.08k
            }
4795
1.41k
            break;
4796
1.41k
          case ZEND_YIELD:
4797
66
            if (!(op_array->fn_flags & ZEND_ACC_RETURN_REFERENCE)) {
4798
0
              continue;
4799
0
            }
4800
66
            break;
4801
392
          case ZEND_OP_DATA:
4802
392
            switch ((opline-1)->opcode) {
4803
336
              case ZEND_ASSIGN_OBJ_REF:
4804
392
              case ZEND_ASSIGN_STATIC_PROP_REF:
4805
392
                break;
4806
0
              default:
4807
0
                continue;
4808
392
            }
4809
392
            break;
4810
127k
          default:
4811
127k
            continue;
4812
152k
        }
4813
152k
      } else if (ssa->ops[def].op2_def == var) {
4814
7.06k
        switch (opline->opcode) {
4815
1.92k
          case ZEND_ASSIGN_REF:
4816
2.87k
          case ZEND_FE_FETCH_RW:
4817
2.87k
            break;
4818
614
          case ZEND_BIND_LEXICAL:
4819
614
            if (!(opline->extended_value & ZEND_BIND_REF)) {
4820
0
              continue;
4821
0
            }
4822
614
            break;
4823
3.57k
          default:
4824
3.57k
            continue;
4825
7.06k
        }
4826
7.06k
      } else {
4827
0
        ZEND_UNREACHABLE();
4828
0
      }
4829
22.9k
      zend_bitset_incl(worklist, var);
4830
1.28M
    } else if (ssa->var_info[var].type & MAY_BE_REF) {
4831
80.8k
      zend_bitset_incl(worklist, var);
4832
1.20M
    } else if (ssa->vars[var].alias == SYMTABLE_ALIAS) {
4833
0
      zend_bitset_incl(worklist, var);
4834
0
    }
4835
1.48M
  }
4836
4837
  /* Set and propagate MAY_BE_REF */
4838
3.58M
  WHILE_WORKLIST(worklist, worklist_len, var) {
4839
4840
3.58M
    ssa->var_info[var].type |= MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_REF | MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
4841
4842
3.58M
    if (ssa->vars[var].phi_use_chain) {
4843
96.9k
      zend_ssa_phi *p = ssa->vars[var].phi_use_chain;
4844
129k
      do {
4845
129k
        if (!(ssa->var_info[p->ssa_var].type & MAY_BE_REF)) {
4846
111k
          zend_bitset_incl(worklist, p->ssa_var);
4847
111k
        }
4848
129k
        p = zend_ssa_next_use_phi(ssa, var, p);
4849
129k
      } while (p);
4850
96.9k
    }
4851
4852
3.58M
    if (ssa->vars[var].use_chain >= 0) {
4853
207k
      int use = ssa->vars[var].use_chain;
4854
548k
      FOREACH_USE(&ssa->vars[var], use) {
4855
548k
        zend_ssa_op *op = ssa->ops + use;
4856
548k
        if (op->op1_use == var && op->op1_def >= 0) {
4857
84.3k
          if (!(ssa->var_info[op->op1_def].type & MAY_BE_REF)) {
4858
            /* Unset breaks references (outside global scope). */
4859
78.7k
            if (op_array->opcodes[use].opcode == ZEND_UNSET_CV
4860
1.76k
                && op_array->function_name) {
4861
73
              continue;
4862
73
            }
4863
78.7k
            zend_bitset_incl(worklist, op->op1_def);
4864
78.7k
          }
4865
84.3k
        }
4866
340k
        if (op->op2_use == var && op->op2_def >= 0) {
4867
5.34k
          if (!(ssa->var_info[op->op2_def].type & MAY_BE_REF)) {
4868
3.11k
            zend_bitset_incl(worklist, op->op2_def);
4869
3.11k
          }
4870
5.34k
        }
4871
340k
        if (op->result_use == var && op->result_def >= 0) {
4872
0
          if (!(ssa->var_info[op->result_def].type & MAY_BE_REF)) {
4873
0
            zend_bitset_incl(worklist, op->result_def);
4874
0
          }
4875
0
        }
4876
340k
      } FOREACH_USE_END();
4877
207k
    }
4878
3.58M
  } WHILE_WORKLIST_END();
4879
4880
89.1k
  free_alloca(worklist,  use_heap);
4881
89.1k
}
4882
4883
ZEND_API zend_result zend_ssa_inference(zend_arena **arena, const zend_op_array *op_array, const zend_script *script, zend_ssa *ssa, zend_long optimization_level) /* {{{ */
4884
89.1k
{
4885
89.1k
  zend_ssa_var_info *ssa_var_info;
4886
89.1k
  int i;
4887
4888
89.1k
  if (!ssa->var_info) {
4889
89.1k
    ssa->var_info = zend_arena_calloc(arena, ssa->vars_count, sizeof(zend_ssa_var_info));
4890
89.1k
  }
4891
89.1k
  ssa_var_info = ssa->var_info;
4892
4893
89.1k
  if (!op_array->function_name) {
4894
120k
    for (i = 0; i < op_array->last_var; i++) {
4895
80.8k
      ssa_var_info[i].type = MAY_BE_UNDEF | MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_REF | MAY_BE_ANY  | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
4896
80.8k
      ssa_var_info[i].has_range = 0;
4897
80.8k
    }
4898
49.5k
  } else {
4899
128k
    for (i = 0; i < op_array->last_var; i++) {
4900
78.7k
      ssa_var_info[i].type = MAY_BE_UNDEF;
4901
78.7k
      ssa_var_info[i].has_range = 0;
4902
78.7k
      if (ssa->vars[i].alias) {
4903
0
        ssa_var_info[i].type |= get_ssa_alias_types(ssa->vars[i].alias);
4904
0
      }
4905
78.7k
    }
4906
49.5k
  }
4907
1.41M
  for (i = op_array->last_var; i < ssa->vars_count; i++) {
4908
1.32M
    ssa_var_info[i].type = 0;
4909
1.32M
    ssa_var_info[i].has_range = 0;
4910
1.32M
  }
4911
4912
89.1k
  zend_mark_cv_references(op_array, script, ssa);
4913
4914
89.1k
  zend_infer_ranges(op_array, ssa);
4915
4916
89.1k
  if (zend_infer_types(op_array, script, ssa, optimization_level) == FAILURE) {
4917
0
    return FAILURE;
4918
0
  }
4919
4920
89.1k
  return SUCCESS;
4921
89.1k
}
4922
/* }}} */
4923
4924
ZEND_API bool zend_may_throw_ex(const zend_op *opline, const zend_ssa_op *ssa_op, const zend_op_array *op_array, const zend_ssa *ssa, uint32_t t1, uint32_t t2)
4925
86.0k
{
4926
86.0k
  if (opline->op1_type == IS_CV) {
4927
29.8k
    if (t1 & MAY_BE_UNDEF) {
4928
18.6k
      switch (opline->opcode) {
4929
0
        case ZEND_UNSET_VAR:
4930
0
        case ZEND_ISSET_ISEMPTY_VAR:
4931
0
          return 1;
4932
10
        case ZEND_ISSET_ISEMPTY_DIM_OBJ:
4933
10
        case ZEND_ISSET_ISEMPTY_PROP_OBJ:
4934
10.6k
        case ZEND_ASSIGN:
4935
10.9k
        case ZEND_ASSIGN_DIM:
4936
10.9k
        case ZEND_ASSIGN_REF:
4937
10.9k
        case ZEND_BIND_GLOBAL:
4938
11.1k
        case ZEND_BIND_STATIC:
4939
11.1k
        case ZEND_BIND_INIT_STATIC_OR_JMP:
4940
11.2k
        case ZEND_FETCH_DIM_IS:
4941
11.2k
        case ZEND_FETCH_OBJ_IS:
4942
11.2k
        case ZEND_SEND_REF:
4943
11.7k
        case ZEND_UNSET_CV:
4944
11.7k
        case ZEND_ISSET_ISEMPTY_CV:
4945
11.7k
        case ZEND_MAKE_REF:
4946
11.7k
        case ZEND_FETCH_DIM_W:
4947
11.7k
          break;
4948
6.86k
        default:
4949
          /* undefined variable warning */
4950
6.86k
          return 1;
4951
18.6k
      }
4952
18.6k
    }
4953
56.1k
  } else if (opline->op1_type & (IS_TMP_VAR|IS_VAR)) {
4954
46.0k
    if ((t1 & MAY_BE_RC1)
4955
29.5k
     && (t1 & (MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_ARRAY_OF_OBJECT|MAY_BE_ARRAY_OF_RESOURCE|MAY_BE_ARRAY_OF_ARRAY))) {
4956
21.1k
      switch (opline->opcode) {
4957
14
        case ZEND_CASE:
4958
14
        case ZEND_CASE_STRICT:
4959
14
        case ZEND_FE_FETCH_R:
4960
14
        case ZEND_FE_FETCH_RW:
4961
14
        case ZEND_FETCH_LIST_R:
4962
14
        case ZEND_QM_ASSIGN:
4963
14
        case ZEND_SEND_VAL:
4964
14
        case ZEND_SEND_VAL_EX:
4965
14
        case ZEND_SEND_VAR:
4966
14
        case ZEND_SEND_VAR_EX:
4967
14
        case ZEND_SEND_FUNC_ARG:
4968
14
        case ZEND_SEND_VAR_NO_REF:
4969
14
        case ZEND_SEND_VAR_NO_REF_EX:
4970
14
        case ZEND_SEND_REF:
4971
14
        case ZEND_SEPARATE:
4972
14
        case ZEND_END_SILENCE:
4973
14
        case ZEND_MAKE_REF:
4974
14
          break;
4975
21.1k
        default:
4976
          /* destructor may be called */
4977
21.1k
          return 1;
4978
21.1k
      }
4979
21.1k
    }
4980
46.0k
  }
4981
4982
58.0k
  if (opline->op2_type == IS_CV) {
4983
2.62k
    if (t2 & MAY_BE_UNDEF) {
4984
1.48k
      switch (opline->opcode) {
4985
0
        case ZEND_ASSIGN_REF:
4986
0
        case ZEND_FE_FETCH_R:
4987
0
        case ZEND_FE_FETCH_RW:
4988
0
          break;
4989
1.48k
        default:
4990
          /* undefined variable warning */
4991
1.48k
          return 1;
4992
1.48k
      }
4993
1.48k
    }
4994
55.4k
  } else if (opline->op2_type & (IS_TMP_VAR|IS_VAR)) {
4995
8.41k
    if ((t2 & MAY_BE_RC1)
4996
2.45k
     && (t2 & (MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_ARRAY_OF_OBJECT|MAY_BE_ARRAY_OF_RESOURCE|MAY_BE_ARRAY_OF_ARRAY))) {
4997
1.50k
      switch (opline->opcode) {
4998
234
        case ZEND_ASSIGN:
4999
234
        case ZEND_FE_FETCH_R:
5000
234
        case ZEND_FE_FETCH_RW:
5001
234
          break;
5002
1.26k
        default:
5003
          /* destructor may be called */
5004
1.26k
          return 1;
5005
1.50k
      }
5006
1.50k
    }
5007
8.41k
  }
5008
5009
55.2k
  switch (opline->opcode) {
5010
4.18k
    case ZEND_NOP:
5011
7.12k
    case ZEND_QM_ASSIGN:
5012
7.12k
    case ZEND_JMP:
5013
7.25k
    case ZEND_CHECK_VAR:
5014
7.25k
    case ZEND_MAKE_REF:
5015
7.25k
    case ZEND_BEGIN_SILENCE:
5016
7.25k
    case ZEND_END_SILENCE:
5017
20.8k
    case ZEND_FREE:
5018
21.9k
    case ZEND_FE_FREE:
5019
21.9k
    case ZEND_SEPARATE:
5020
22.1k
    case ZEND_TYPE_CHECK:
5021
22.2k
    case ZEND_DEFINED:
5022
22.2k
    case ZEND_ISSET_ISEMPTY_THIS:
5023
22.2k
    case ZEND_COALESCE:
5024
22.2k
    case ZEND_SWITCH_LONG:
5025
22.2k
    case ZEND_SWITCH_STRING:
5026
22.2k
    case ZEND_MATCH:
5027
22.2k
    case ZEND_ISSET_ISEMPTY_VAR:
5028
22.2k
    case ZEND_ISSET_ISEMPTY_CV:
5029
22.2k
    case ZEND_FUNC_NUM_ARGS:
5030
22.2k
    case ZEND_FUNC_GET_ARGS:
5031
23.6k
    case ZEND_COPY_TMP:
5032
23.6k
    case ZEND_JMP_NULL:
5033
23.6k
    case ZEND_JMP_FRAMELESS:
5034
23.6k
      return 0;
5035
102
    case ZEND_IS_IDENTICAL:
5036
135
    case ZEND_IS_NOT_IDENTICAL:
5037
135
    case ZEND_CASE_STRICT:
5038
      /* Array to array comparison may lead to recursion. */
5039
135
      return (t1 & t2) & MAY_BE_ARRAY_OF_ARRAY;
5040
0
    case ZEND_SEND_VAR:
5041
0
    case ZEND_SEND_VAL:
5042
0
    case ZEND_SEND_REF:
5043
0
    case ZEND_SEND_VAR_EX:
5044
0
    case ZEND_SEND_FUNC_ARG:
5045
0
    case ZEND_CHECK_FUNC_ARG:
5046
      /* May throw for named params. */
5047
0
      return opline->op2_type == IS_CONST;
5048
0
    case ZEND_INIT_FCALL:
5049
      /* can't throw, because call is resolved at compile time */
5050
0
      return 0;
5051
0
    case ZEND_BIND_GLOBAL:
5052
0
      if ((opline+1)->opcode == ZEND_BIND_GLOBAL) {
5053
0
        return zend_may_throw(opline + 1, ssa_op ? ssa_op + 1 : NULL, op_array, ssa);
5054
0
      }
5055
0
      return 0;
5056
1.37k
    case ZEND_ADD:
5057
1.37k
      if ((t1 & MAY_BE_ANY) == MAY_BE_ARRAY
5058
4
       && (t2 & MAY_BE_ANY) == MAY_BE_ARRAY) {
5059
2
        return 0;
5060
2
      }
5061
1.37k
      return (t1 & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)) ||
5062
1.26k
        (t2 & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE));
5063
135
    case ZEND_DIV:
5064
135
      if (!OP2_HAS_RANGE() ||
5065
127
        (OP2_MIN_RANGE() <= 0 && OP2_MAX_RANGE() >= 0)) {
5066
        /* Division by zero */
5067
127
        return 1;
5068
127
      }
5069
8
      ZEND_FALLTHROUGH;
5070
751
    case ZEND_SUB:
5071
1.57k
    case ZEND_MUL:
5072
1.62k
    case ZEND_POW:
5073
1.62k
      return (t1 & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)) ||
5074
1.26k
        (t2 & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE));
5075
    /* Ops may throw if not an integer */
5076
228
    case ZEND_MOD:
5077
228
      if (!OP2_HAS_RANGE() ||
5078
171
        (OP2_MIN_RANGE() <= 0 && OP2_MAX_RANGE() >= 0)) {
5079
        /* Division by zero */
5080
125
        return 1;
5081
125
      }
5082
103
      ZEND_FALLTHROUGH;
5083
382
    case ZEND_SL:
5084
613
    case ZEND_SR:
5085
613
      return (t1 & (MAY_BE_STRING|MAY_BE_DOUBLE|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)) ||
5086
288
        (t2 & (MAY_BE_STRING|MAY_BE_DOUBLE|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)) ||
5087
159
        !OP2_HAS_RANGE() ||
5088
159
        OP2_MIN_RANGE() < 0;
5089
697
    case ZEND_CONCAT:
5090
983
    case ZEND_FAST_CONCAT:
5091
983
      return (t1 & (MAY_BE_ARRAY|MAY_BE_OBJECT)) ||
5092
975
        (t2 & (MAY_BE_ARRAY|MAY_BE_OBJECT));
5093
140
    case ZEND_BW_OR:
5094
326
    case ZEND_BW_AND:
5095
785
    case ZEND_BW_XOR:
5096
785
      if ((t1 & MAY_BE_ANY) == MAY_BE_STRING
5097
27
       && (t2 & MAY_BE_ANY) == MAY_BE_STRING) {
5098
10
        return 0;
5099
10
      }
5100
775
      return (t1 & (MAY_BE_STRING|MAY_BE_DOUBLE|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)) ||
5101
631
        (t2 & (MAY_BE_STRING|MAY_BE_DOUBLE|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE));
5102
1.92k
    case ZEND_BW_NOT:
5103
1.92k
      return (t1 & (MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_DOUBLE|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE));
5104
1.95k
    case ZEND_PRE_INC:
5105
2.28k
    case ZEND_POST_INC:
5106
2.28k
      return (t1 & (MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE));
5107
    /* null emits a warning as it has no effect compared to ++ which converts the value to 1 */
5108
195
    case ZEND_PRE_DEC:
5109
361
    case ZEND_POST_DEC:
5110
361
      return (t1 & (MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE));
5111
0
    case ZEND_JMPZ:
5112
0
    case ZEND_JMPNZ:
5113
0
    case ZEND_JMPZ_EX:
5114
0
    case ZEND_JMPNZ_EX:
5115
0
    case ZEND_JMP_SET:
5116
0
      return (t1 & MAY_BE_OBJECT);
5117
396
    case ZEND_BOOL:
5118
771
    case ZEND_BOOL_NOT:
5119
      /* NAN Cast to bool will warn, but if we have a range it is fine */
5120
771
      return (t1 & MAY_BE_OBJECT) || ((t1 & MAY_BE_DOUBLE) && !OP1_HAS_RANGE());
5121
300
    case ZEND_BOOL_XOR:
5122
300
      return (t1 & MAY_BE_OBJECT) || (t2 & MAY_BE_OBJECT);
5123
377
    case ZEND_IS_EQUAL:
5124
759
    case ZEND_IS_NOT_EQUAL:
5125
1.17k
    case ZEND_IS_SMALLER:
5126
1.24k
    case ZEND_IS_SMALLER_OR_EQUAL:
5127
1.26k
    case ZEND_CASE:
5128
1.26k
    case ZEND_SPACESHIP:
5129
1.26k
      if ((t1 & MAY_BE_ANY) == MAY_BE_NULL
5130
1.02k
       || (t2 & MAY_BE_ANY) == MAY_BE_NULL) {
5131
308
        return 0;
5132
308
      }
5133
955
      return (t1 & (MAY_BE_OBJECT|MAY_BE_ARRAY_OF_ARRAY|MAY_BE_ARRAY_OF_OBJECT)) || (t2 & (MAY_BE_OBJECT|MAY_BE_ARRAY_OF_ARRAY|MAY_BE_ARRAY_OF_OBJECT));
5134
10
    case ZEND_ASSIGN_OP:
5135
10
      if (opline->extended_value == ZEND_ADD) {
5136
10
        if ((t1 & MAY_BE_ANY) == MAY_BE_ARRAY
5137
0
         && (t2 & MAY_BE_ANY) == MAY_BE_ARRAY) {
5138
0
          return 0;
5139
0
        }
5140
10
        return (t1 & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)) ||
5141
6
          (t2 & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE));
5142
10
      } else if (opline->extended_value == ZEND_DIV ||
5143
0
        opline->extended_value == ZEND_MOD) {
5144
0
        if (!OP2_HAS_RANGE() ||
5145
0
          (OP2_MIN_RANGE() <= 0 && OP2_MAX_RANGE() >= 0)) {
5146
          /* Division by zero */
5147
0
          return 1;
5148
0
        }
5149
0
        return (t1 & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)) ||
5150
0
          (t2 & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE));
5151
0
      } else if (opline->extended_value == ZEND_SUB ||
5152
0
        opline->extended_value == ZEND_MUL ||
5153
0
        opline->extended_value == ZEND_POW) {
5154
0
        return (t1 & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)) ||
5155
0
          (t2 & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE));
5156
0
      } else if (opline->extended_value == ZEND_SL ||
5157
0
        opline->extended_value == ZEND_SR) {
5158
0
        return (t1 & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)) ||
5159
0
          (t2 & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)) ||
5160
0
          !OP2_HAS_RANGE() ||
5161
0
          OP2_MIN_RANGE() < 0;
5162
0
      } else if (opline->extended_value == ZEND_CONCAT) {
5163
0
        return (t1 & (MAY_BE_ARRAY|MAY_BE_OBJECT)) ||
5164
0
          (t2 & (MAY_BE_ARRAY|MAY_BE_OBJECT));
5165
0
      } else if (opline->extended_value == ZEND_BW_OR ||
5166
0
        opline->extended_value == ZEND_BW_AND ||
5167
0
        opline->extended_value == ZEND_BW_XOR) {
5168
0
        if ((t1 & MAY_BE_ANY) == MAY_BE_STRING
5169
0
         && (t2 & MAY_BE_ANY) == MAY_BE_STRING) {
5170
0
          return 0;
5171
0
        }
5172
0
        return (t1 & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)) ||
5173
0
          (t2 & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE));
5174
0
      }
5175
0
      return 1;
5176
15.3k
    case ZEND_ASSIGN:
5177
15.3k
      if (t1 & MAY_BE_REF) {
5178
0
        return 1;
5179
0
      }
5180
15.3k
      ZEND_FALLTHROUGH;
5181
15.3k
    case ZEND_UNSET_VAR:
5182
15.3k
      return (t1 & (MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_ARRAY_OF_OBJECT|MAY_BE_ARRAY_OF_RESOURCE|MAY_BE_ARRAY_OF_ARRAY));
5183
136
    case ZEND_BIND_STATIC:
5184
136
    case ZEND_BIND_INIT_STATIC_OR_JMP:
5185
136
      if (t1 & (MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_ARRAY_OF_OBJECT|MAY_BE_ARRAY_OF_RESOURCE|MAY_BE_ARRAY_OF_ARRAY)) {
5186
        /* Destructor may throw. */
5187
48
        return 1;
5188
48
      }
5189
88
      return 0;
5190
322
    case ZEND_ASSIGN_DIM:
5191
322
      if ((opline+1)->op1_type == IS_CV) {
5192
122
        if (OP1_DATA_INFO() & MAY_BE_UNDEF) {
5193
116
          return 1;
5194
116
        }
5195
122
      }
5196
206
      if (t1 & (MAY_BE_ARRAY_OF_OBJECT|MAY_BE_ARRAY_OF_RESOURCE|MAY_BE_ARRAY_OF_ARRAY|MAY_BE_ARRAY_OF_REF)) {
5197
26
        return 1;
5198
26
      }
5199
180
      return (t1 & (MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_TRUE|MAY_BE_FALSE|MAY_BE_STRING|MAY_BE_LONG|MAY_BE_DOUBLE)) || opline->op2_type == IS_UNUSED ||
5200
101
        (t2 & (MAY_BE_UNDEF|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE));
5201
81
    case ZEND_ASSIGN_OBJ:
5202
81
      if (t1 & (MAY_BE_ANY-MAY_BE_OBJECT)) {
5203
0
        return 1;
5204
0
      }
5205
81
      if ((opline+1)->op1_type == IS_CV) {
5206
27
        if (OP1_DATA_INFO() & MAY_BE_UNDEF) {
5207
17
          return 1;
5208
17
        }
5209
27
      }
5210
64
      if (ssa_op->op1_use) {
5211
64
        const zend_ssa_var_info *var_info = ssa->var_info + ssa_op->op1_use;
5212
64
        const zend_class_entry *ce = var_info->ce;
5213
5214
64
        if (var_info->is_instanceof
5215
64
         || !ce
5216
50
         || ce->create_object
5217
50
         || ce->default_object_handlers->write_property != zend_std_write_property
5218
50
         || ce->default_object_handlers->get_property_ptr_ptr != zend_std_get_property_ptr_ptr
5219
50
         || ce->__get
5220
50
         || ce->__set
5221
50
         || ce->parent) {
5222
14
          return 1;
5223
14
        }
5224
5225
50
        if (opline->op2_type != IS_CONST) {
5226
0
          return 1;
5227
0
        }
5228
5229
50
        zend_string *prop_name = Z_STR_P(CRT_CONSTANT(opline->op2));
5230
50
        if (ZSTR_LEN(prop_name) > 0 && ZSTR_VAL(prop_name)[0] == '\0') {
5231
0
          return 1;
5232
0
        }
5233
5234
50
        zend_property_info *prop_info =
5235
50
          zend_hash_find_ptr(&ce->properties_info, prop_name);
5236
50
        if (prop_info) {
5237
17
          if (ZEND_TYPE_IS_SET(prop_info->type)) {
5238
6
            return 1;
5239
6
          }
5240
11
          return !(prop_info->flags & ZEND_ACC_PUBLIC)
5241
0
            && prop_info->ce != op_array->scope;
5242
33
        } else {
5243
33
          return !(ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES);
5244
33
        }
5245
50
      }
5246
0
      return 1;
5247
0
    case ZEND_ROPE_INIT:
5248
0
    case ZEND_ROPE_ADD:
5249
0
    case ZEND_ROPE_END:
5250
0
      return t2 & (MAY_BE_ARRAY|MAY_BE_OBJECT);
5251
179
    case ZEND_INIT_ARRAY:
5252
179
      return (opline->op2_type != IS_UNUSED) && (t2 & (MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE));
5253
146
    case ZEND_ADD_ARRAY_ELEMENT:
5254
146
      return (opline->op2_type == IS_UNUSED) || (t2 & (MAY_BE_NULL|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE));
5255
1.38k
    case ZEND_STRLEN:
5256
1.38k
      return (t1 & MAY_BE_ANY) != MAY_BE_STRING;
5257
244
    case ZEND_COUNT:
5258
244
      return (t1 & MAY_BE_ANY) != MAY_BE_ARRAY;
5259
0
    case ZEND_RECV_INIT:
5260
0
      if (Z_TYPE_P(CRT_CONSTANT(opline->op2)) == IS_CONSTANT_AST) {
5261
0
        return 1;
5262
0
      }
5263
0
      if (op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) {
5264
0
        uint32_t arg_num = opline->op1.num;
5265
0
        const zend_arg_info *cur_arg_info;
5266
5267
0
        if (EXPECTED(arg_num <= op_array->num_args)) {
5268
0
          cur_arg_info = &op_array->arg_info[arg_num-1];
5269
0
        } else if (UNEXPECTED(op_array->fn_flags & ZEND_ACC_VARIADIC)) {
5270
0
          cur_arg_info = &op_array->arg_info[op_array->num_args];
5271
0
        } else {
5272
0
          return 0;
5273
0
        }
5274
0
        return ZEND_TYPE_IS_SET(cur_arg_info->type);
5275
0
      } else {
5276
0
        return 0;
5277
0
      }
5278
0
    case ZEND_FETCH_IS:
5279
0
      return (t2 & (MAY_BE_ARRAY|MAY_BE_OBJECT));
5280
172
    case ZEND_ISSET_ISEMPTY_DIM_OBJ:
5281
172
      return (t1 & MAY_BE_OBJECT) || (t2 & (MAY_BE_DOUBLE|MAY_BE_ARRAY|MAY_BE_OBJECT));
5282
132
    case ZEND_FETCH_DIM_IS:
5283
132
      return (t1 & MAY_BE_OBJECT) || (t2 & (MAY_BE_DOUBLE|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE));
5284
162
    case ZEND_CAST:
5285
162
      switch (opline->extended_value) {
5286
70
        case IS_LONG:
5287
70
          return (t1 & (MAY_BE_DOUBLE|MAY_BE_STRING|MAY_BE_OBJECT));
5288
18
        case IS_DOUBLE:
5289
18
          return (t1 & MAY_BE_OBJECT);
5290
74
        case IS_STRING:
5291
74
          return (t1 & (MAY_BE_ARRAY|MAY_BE_OBJECT));
5292
0
        case IS_ARRAY:
5293
0
          return (t1 & MAY_BE_OBJECT);
5294
0
        case IS_OBJECT:
5295
0
          return 0;
5296
0
        default: ZEND_UNREACHABLE();
5297
162
      }
5298
      /* GCC is getting confused here for the Wimplicit-fallthrough warning with
5299
       * default: ZEND_UNREACHABLE(); macro */
5300
0
      return 0;
5301
2
    case ZEND_ARRAY_KEY_EXISTS:
5302
2
      if ((t2 & MAY_BE_ANY) != MAY_BE_ARRAY) {
5303
0
        return 1;
5304
0
      }
5305
2
      if ((t1 & (MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE))) {
5306
0
        return 1;
5307
0
      }
5308
2
      return 0;
5309
10
    case ZEND_FE_RESET_R:
5310
10
    case ZEND_FE_RESET_RW:
5311
10
      if ((t1 & (MAY_BE_ANY|MAY_BE_REF)) != MAY_BE_ARRAY) {
5312
0
        return 1;
5313
0
      }
5314
10
      return 0;
5315
0
    case ZEND_FE_FETCH_R:
5316
0
      if ((t1 & (MAY_BE_ANY|MAY_BE_REF)) != MAY_BE_ARRAY) {
5317
0
        return 1;
5318
0
      }
5319
0
      if (opline->op2_type == IS_CV
5320
0
       && (t2 & MAY_BE_RC1)
5321
0
       && (t2 & (MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_ARRAY_OF_OBJECT|MAY_BE_ARRAY_OF_RESOURCE|MAY_BE_ARRAY_OF_ARRAY))) {
5322
0
        return 1;
5323
0
      }
5324
0
      return 0;
5325
0
    case ZEND_FETCH_DIM_W:
5326
0
    case ZEND_FETCH_LIST_W:
5327
0
      if (t1 & (MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE|MAY_BE_STRING|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF)) {
5328
0
        return 1;
5329
0
      }
5330
0
      if (t2 & (MAY_BE_RESOURCE|MAY_BE_ARRAY|MAY_BE_OBJECT)) {
5331
0
        return 1;
5332
0
      }
5333
0
      if (opline->op2_type == IS_UNUSED) {
5334
0
        return 1;
5335
0
      }
5336
0
      return 0;
5337
14
    case ZEND_YIELD_FROM: {
5338
14
      uint32_t t1 = OP1_INFO();
5339
14
      if ((t1 & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY && MAY_BE_EMPTY_ONLY(t1)) {
5340
14
        return false;
5341
14
      }
5342
0
      return true;
5343
14
    }
5344
621
    default:
5345
621
      return 1;
5346
55.2k
  }
5347
55.2k
}
5348
5349
ZEND_API bool zend_may_throw(const zend_op *opline, const zend_ssa_op *ssa_op, const zend_op_array *op_array, const zend_ssa *ssa)
5350
86.0k
{
5351
86.0k
  return zend_may_throw_ex(opline, ssa_op, op_array, ssa, OP1_INFO(), OP2_INFO());
5352
86.0k
}