Coverage Report

Created: 2026-04-01 06:49

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