Coverage Report

Created: 2026-10-28 06:20

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