Coverage Report

Created: 2025-07-23 06:33

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