Coverage Report

Created: 2025-12-14 06:10

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