source: src/router/php7/ext/opcache/Optimizer/zend_inference.c @ 31874

Last change on this file since 31874 was 31874, checked in by brainslayer, 6 weeks ago

update php

File size: 116.9 KB
Line 
1/*
2   +----------------------------------------------------------------------+
3   | Zend Engine, e-SSA based Type & Range Inference                      |
4   +----------------------------------------------------------------------+
5   | Copyright (c) 1998-2017 The PHP Group                                |
6   +----------------------------------------------------------------------+
7   | This source file is subject to version 3.01 of the PHP license,      |
8   | that is bundled with this package in the file LICENSE, and is        |
9   | available through the world-wide-web at the following url:           |
10   | http://www.php.net/license/3_01.txt                                  |
11   | If you did not receive a copy of the PHP license and are unable to   |
12   | obtain it through the world-wide-web, please send a note to          |
13   | license@php.net so we can mail you a copy immediately.               |
14   +----------------------------------------------------------------------+
15   | Authors: Dmitry Stogov <dmitry@zend.com>                             |
16   +----------------------------------------------------------------------+
17*/
18
19#include "php.h"
20#include "zend_compile.h"
21#include "zend_generators.h"
22#include "zend_inference.h"
23#include "zend_func_info.h"
24#include "zend_call_graph.h"
25#include "zend_worklist.h"
26
27/* The used range inference algorithm is described in:
28 *     V. Campos, R. Rodrigues, I. de Assis Costa and F. Pereira.
29 *     "Speed and Precision in Range Analysis", SBLP'12.
30 *
31 * There are a couple degrees of freedom, we use:
32 *  * Propagation on SCCs.
33 *  * e-SSA for live range splitting.
34 *  * Only intra-procedural inference.
35 *  * Widening with warmup passes, but without jump sets.
36 */
37
38/* Whether to handle symbolic range constraints */
39#define SYM_RANGE
40
41/* Whether to handle negative range constraints */
42#define NEG_RANGE
43
44/* Number of warmup passes to use prior to widening */
45#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#define WHILE_WORKLIST(worklist, len, i) do { \
63        zend_bool _done = 0; \
64        while (!_done) { \
65                _done = 1; \
66                ZEND_BITSET_FOREACH(worklist, len, i) { \
67                        zend_bitset_excl(worklist, i); \
68                        _done = 0;
69
70#define WHILE_WORKLIST_END() \
71                } ZEND_BITSET_FOREACH_END(); \
72        } \
73} while (0)
74
75#define CHECK_SCC_VAR(var2) \
76        do { \
77                if (!ssa->vars[var2].no_val) { \
78                        if (dfs[var2] < 0) { \
79                                zend_ssa_check_scc_var(op_array, ssa, var2, index, dfs, root, stack); \
80                        } \
81                        if (ssa->vars[var2].scc < 0 && dfs[root[var]] >= dfs[root[var2]]) { \
82                                root[var] = root[var2]; \
83                        } \
84                } \
85        } while (0)
86
87#define CHECK_SCC_ENTRY(var2) \
88        do { \
89                if (ssa->vars[var2].scc != ssa->vars[var].scc) { \
90                        ssa->vars[var2].scc_entry = 1; \
91                } \
92        } while (0)
93
94#define ADD_SCC_VAR(_var) \
95        do { \
96                if (ssa->vars[_var].scc == scc) { \
97                        zend_bitset_incl(worklist, _var); \
98                } \
99        } while (0)
100
101#define ADD_SCC_VAR_1(_var) \
102        do { \
103                if (ssa->vars[_var].scc == scc && \
104                    !zend_bitset_in(visited, _var)) { \
105                        zend_bitset_incl(worklist, _var); \
106                } \
107        } while (0)
108
109#define FOR_EACH_DEFINED_VAR(line, MACRO) \
110        do { \
111                if (ssa->ops[line].op1_def >= 0) { \
112                        MACRO(ssa->ops[line].op1_def); \
113                } \
114                if (ssa->ops[line].op2_def >= 0) { \
115                        MACRO(ssa->ops[line].op2_def); \
116                } \
117                if (ssa->ops[line].result_def >= 0) { \
118                        MACRO(ssa->ops[line].result_def); \
119                } \
120                if (op_array->opcodes[line].opcode == ZEND_OP_DATA) { \
121                        if (ssa->ops[line-1].op1_def >= 0) { \
122                                MACRO(ssa->ops[line-1].op1_def); \
123                        } \
124                        if (ssa->ops[line-1].op2_def >= 0) { \
125                                MACRO(ssa->ops[line-1].op2_def); \
126                        } \
127                        if (ssa->ops[line-1].result_def >= 0) { \
128                                MACRO(ssa->ops[line-1].result_def); \
129                        } \
130                } else if ((uint32_t)line+1 < op_array->last && \
131                           op_array->opcodes[line+1].opcode == ZEND_OP_DATA) { \
132                        if (ssa->ops[line+1].op1_def >= 0) { \
133                                MACRO(ssa->ops[line+1].op1_def); \
134                        } \
135                        if (ssa->ops[line+1].op2_def >= 0) { \
136                                MACRO(ssa->ops[line+1].op2_def); \
137                        } \
138                        if (ssa->ops[line+1].result_def >= 0) { \
139                                MACRO(ssa->ops[line+1].result_def); \
140                        } \
141                } \
142        } while (0)
143
144
145#define FOR_EACH_VAR_USAGE(_var, MACRO) \
146        do { \
147                zend_ssa_phi *p = ssa->vars[_var].phi_use_chain; \
148                int use = ssa->vars[_var].use_chain; \
149                while (use >= 0) { \
150                        FOR_EACH_DEFINED_VAR(use, MACRO); \
151                        use = zend_ssa_next_use(ssa->ops, _var, use); \
152                } \
153                p = ssa->vars[_var].phi_use_chain; \
154                while (p) { \
155                        MACRO(p->ssa_var); \
156                        p = zend_ssa_next_use_phi(ssa, _var, p); \
157                } \
158        } while (0)
159
160static void zend_ssa_check_scc_var(const zend_op_array *op_array, zend_ssa *ssa, int var, int *index, int *dfs, int *root, zend_worklist_stack *stack) /* {{{ */
161{
162#ifdef SYM_RANGE
163        zend_ssa_phi *p;
164#endif
165
166        dfs[var] = *index;
167        (*index)++;
168        root[var] = var;
169
170        FOR_EACH_VAR_USAGE(var, CHECK_SCC_VAR);
171
172#ifdef SYM_RANGE
173        /* Process symbolic control-flow constraints */
174        p = ssa->vars[var].sym_use_chain;
175        while (p) {
176                CHECK_SCC_VAR(p->ssa_var);
177                p = p->sym_use_chain;
178        }
179#endif
180
181        if (root[var] == var) {
182                ssa->vars[var].scc = ssa->sccs;
183                while (stack->len > 0) {
184                        int var2 = zend_worklist_stack_peek(stack);
185                        if (dfs[var2] <= dfs[var]) {
186                                break;
187                        }
188                        zend_worklist_stack_pop(stack);
189                        ssa->vars[var2].scc = ssa->sccs;
190                }
191                ssa->sccs++;
192        } else {
193                zend_worklist_stack_push(stack, var);
194        }
195}
196/* }}} */
197
198int zend_ssa_find_sccs(const zend_op_array *op_array, zend_ssa *ssa) /* {{{ */
199{
200        int index = 0, *dfs, *root;
201        zend_worklist_stack stack;
202        int j;
203        ALLOCA_FLAG(dfs_use_heap)
204        ALLOCA_FLAG(root_use_heap)
205        ALLOCA_FLAG(stack_use_heap)
206
207        dfs = do_alloca(sizeof(int) * ssa->vars_count, dfs_use_heap);
208        memset(dfs, -1, sizeof(int) * ssa->vars_count);
209        root = do_alloca(sizeof(int) * ssa->vars_count, root_use_heap);
210        ZEND_WORKLIST_STACK_ALLOCA(&stack, ssa->vars_count, stack_use_heap);
211
212        /* Find SCCs using Tarjan's algorithm. */
213        for (j = 0; j < ssa->vars_count; j++) {
214                if (!ssa->vars[j].no_val && dfs[j] < 0) {
215                        zend_ssa_check_scc_var(op_array, ssa, j, &index, dfs, root, &stack);
216                }
217        }
218
219        /* Revert SCC order. This results in a topological order. */
220        for (j = 0; j < ssa->vars_count; j++) {
221                if (ssa->vars[j].scc >= 0) {
222                        ssa->vars[j].scc = ssa->sccs - (ssa->vars[j].scc + 1);
223                }
224        }
225
226        for (j = 0; j < ssa->vars_count; j++) {
227                if (ssa->vars[j].scc >= 0) {
228                        int var = j;
229                        if (root[j] == j) {
230                                ssa->vars[j].scc_entry = 1;
231                        }
232                        FOR_EACH_VAR_USAGE(var, CHECK_SCC_ENTRY);
233                }
234        }
235
236        ZEND_WORKLIST_STACK_FREE_ALLOCA(&stack, stack_use_heap);
237        free_alloca(root, root_use_heap);
238        free_alloca(dfs, dfs_use_heap);
239
240        return SUCCESS;
241}
242/* }}} */
243
244static inline zend_bool is_no_val_use(const zend_op *opline, const zend_ssa_op *ssa_op, int var)
245{
246        if (opline->opcode == ZEND_ASSIGN ||
247                        (opline->opcode == ZEND_UNSET_VAR && (opline->extended_value & ZEND_QUICK_SET))) {
248                return ssa_op->op1_use == var && ssa_op->op2_use != var;
249        }
250        if (opline->opcode == ZEND_FE_FETCH_R) {
251                return ssa_op->op2_use == var && ssa_op->op1_use != var;
252        }
253        return 0;
254}
255
256int zend_ssa_find_false_dependencies(const zend_op_array *op_array, zend_ssa *ssa) /* {{{ */
257{
258        zend_ssa_var *ssa_vars = ssa->vars;
259        zend_ssa_op *ssa_ops = ssa->ops;
260        int ssa_vars_count = ssa->vars_count;
261        zend_bitset worklist;
262        int i, j, use;
263        zend_ssa_phi *p;
264        ALLOCA_FLAG(use_heap);
265
266        if (!op_array->function_name || !ssa->vars || !ssa->ops) {
267                return SUCCESS;
268        }
269
270        worklist = do_alloca(sizeof(zend_ulong) * zend_bitset_len(ssa_vars_count), use_heap);
271        memset(worklist, 0, sizeof(zend_ulong) * zend_bitset_len(ssa_vars_count));
272
273        for (i = 0; i < ssa_vars_count; i++) {
274                ssa_vars[i].no_val = 1; /* mark as unused */
275                use = ssa->vars[i].use_chain;
276                while (use >= 0) {
277                        if (!is_no_val_use(&op_array->opcodes[use], &ssa->ops[use], i)) {
278                                ssa_vars[i].no_val = 0; /* used directly */
279                                zend_bitset_incl(worklist, i);
280                                break;
281                        }
282                        use = zend_ssa_next_use(ssa_ops, i, use);
283                }
284        }
285
286        WHILE_WORKLIST(worklist, zend_bitset_len(ssa_vars_count), i) {
287                if (ssa_vars[i].definition_phi) {
288                        /* mark all possible sources as used */
289                        p = ssa_vars[i].definition_phi;
290                        if (p->pi >= 0) {
291                                if (ssa_vars[p->sources[0]].no_val) {
292                                        ssa_vars[p->sources[0]].no_val = 0; /* used indirectly */
293                                        zend_bitset_incl(worklist, p->sources[0]);
294                                }
295                        } else {
296                                for (j = 0; j < ssa->cfg.blocks[p->block].predecessors_count; j++) {
297                                        if (p->sources[j] >= 0 && ssa->vars[p->sources[j]].no_val) {
298                                                ssa_vars[p->sources[j]].no_val = 0; /* used indirectly */
299                                                zend_bitset_incl(worklist, p->sources[j]);
300                                        }
301                                }
302                        }
303                }
304        } WHILE_WORKLIST_END();
305
306        free_alloca(worklist, use_heap);
307
308        return SUCCESS;
309}
310/* }}} */
311
312/* From "Hacker's Delight" */
313zend_ulong minOR(zend_ulong a, zend_ulong b, zend_ulong c, zend_ulong d)
314{
315        zend_ulong m, temp;
316
317        m = 1L << (sizeof(zend_ulong) * 8 - 1);
318        while (m != 0) {
319                if (~a & c & m) {
320                        temp = (a | m) & -m;
321                        if (temp <= b) {
322                                a = temp;
323                                break;
324                        }
325                } else if (a & ~c & m) {
326                        temp = (c | m) & -m;
327                        if (temp <= d) {
328                                c = temp;
329                                break;
330                        }
331                }
332                m = m >> 1;
333        }
334        return a | c;
335}
336
337zend_ulong maxOR(zend_ulong a, zend_ulong b, zend_ulong c, zend_ulong d)
338{
339        zend_ulong m, temp;
340
341        m = 1L << (sizeof(zend_ulong) * 8 - 1);
342        while (m != 0) {
343                if (b & d & m) {
344                        temp = (b - m) | (m - 1);
345                        if (temp >= a) {
346                                b = temp;
347                                break;
348                        }
349                        temp = (d - m) | (m - 1);
350                        if (temp >= c) {
351                                d = temp;
352                                break;
353                        }
354                }
355                m = m >> 1;
356        }
357        return b | d;
358}
359
360zend_ulong minAND(zend_ulong a, zend_ulong b, zend_ulong c, zend_ulong d)
361{
362        zend_ulong m, temp;
363
364        m = 1L << (sizeof(zend_ulong) * 8 - 1);
365        while (m != 0) {
366                if (~a & ~c & m) {
367                        temp = (a | m) & -m;
368                        if (temp <= b) {
369                                a = temp;
370                                break;
371                        }
372                        temp = (c | m) & -m;
373                        if (temp <= d) {
374                                c = temp;
375                                break;
376                        }
377                }
378                m = m >> 1;
379        }
380        return a & c;
381}
382
383zend_ulong maxAND(zend_ulong a, zend_ulong b, zend_ulong c, zend_ulong d)
384{
385        zend_ulong m, temp;
386
387        m = 1L << (sizeof(zend_ulong) * 8 - 1);
388        while (m != 0) {
389                if (b & ~d & m) {
390                        temp = (b | ~m) | (m - 1);
391                        if (temp >= a) {
392                                b = temp;
393                                break;
394                        }
395                } else if (~b & d & m) {
396                        temp = (d | ~m) | (m - 1);
397                        if (temp >= c) {
398                                d = temp;
399                                break;
400                        }
401                }
402                m = m >> 1;
403        }
404        return b & d;
405}
406
407zend_ulong minXOR(zend_ulong a, zend_ulong b, zend_ulong c, zend_ulong d)
408{
409        return minAND(a, b, ~d, ~c) | minAND(~b, ~a, c, d);
410}
411
412zend_ulong maxXOR(zend_ulong a, zend_ulong b, zend_ulong c, zend_ulong d)
413{
414        return maxOR(0, maxAND(a, b, ~d, ~c), 0, maxAND(~b, ~a, c, d));
415}
416
417/* Based on "Hacker's Delight" */
418
419/*
4200: + + + + 0 0 0 0 => 0 0 + min/max
4212: + + - + 0 0 1 0 => 1 0 ? min(a,b,c,-1)/max(a,b,0,d)
4223: + + - - 0 0 1 1 => 1 1 - min/max
4238: - + + + 1 0 0 0 => 1 0 ? min(a,-1,b,d)/max(0,b,c,d)
424a: - + - + 1 0 1 0 => 1 0 ? MIN(a,c)/max(0,b,0,d)
425b: - + - - 1 0 1 1 => 1 1 - c/-1
426c: - - + + 1 1 0 0 => 1 1 - min/max
427e: - - - + 1 1 1 0 => 1 1 - a/-1
428f  - - - - 1 1 1 1 => 1 1 - min/max
429*/
430static void zend_ssa_range_or(zend_long a, zend_long b, zend_long c, zend_long d, zend_ssa_range *tmp)
431{
432        int x = ((a < 0) ? 8 : 0) |
433                ((b < 0) ? 4 : 0) |
434                ((c < 0) ? 2 : 0) |
435                ((d < 0) ? 2 : 0);
436        switch (x) {
437                case 0x0:
438                case 0x3:
439                case 0xc:
440                case 0xf:
441                        tmp->min = minOR(a, b, c, d);
442                        tmp->max = maxOR(a, b, c, d);
443                        break;
444                case 0x2:
445                        tmp->min = minOR(a, b, c, -1);
446                        tmp->max = maxOR(a, b, 0, d);
447                        break;
448                case 0x8:
449                        tmp->min = minOR(a, -1, c, d);
450                        tmp->max = maxOR(0, b, c, d);
451                        break;
452                case 0xa:
453                        tmp->min = MIN(a, c);
454                        tmp->max = maxOR(0, b, 0, d);
455                        break;
456                case 0xb:
457                        tmp->min = c;
458                        tmp->max = -1;
459                        break;
460                case 0xe:
461                        tmp->min = a;
462                        tmp->max = -1;
463                        break;
464        }
465}
466
467/*
4680: + + + + 0 0 0 0 => 0 0 + min/max
4692: + + - + 0 0 1 0 => 0 0 + 0/b
4703: + + - - 0 0 1 1 => 0 0 + min/max
4718: - + + + 1 0 0 0 => 0 0 + 0/d
472a: - + - + 1 0 1 0 => 1 0 ? min(a,-1,c,-1)/NAX(b,d)
473b: - + - - 1 0 1 1 => 1 0 ? min(a,-1,c,d)/max(0,b,c,d)
474c: - - + + 1 1 0 0 => 1 1 - min/max
475e: - - - + 1 1 1 0 => 1 0 ? min(a,b,c,-1)/max(a,b,0,d)
476f  - - - - 1 1 1 1 => 1 1 - min/max
477*/
478static void zend_ssa_range_and(zend_long a, zend_long b, zend_long c, zend_long d, zend_ssa_range *tmp)
479{
480        int x = ((a < 0) ? 8 : 0) |
481                ((b < 0) ? 4 : 0) |
482                ((c < 0) ? 2 : 0) |
483                ((d < 0) ? 2 : 0);
484        switch (x) {
485                case 0x0:
486                case 0x3:
487                case 0xc:
488                case 0xf:
489                        tmp->min = minAND(a, b, c, d);
490                        tmp->max = maxAND(a, b, c, d);
491                        break;
492                case 0x2:
493                        tmp->min = 0;
494                        tmp->max = b;
495                        break;
496                case 0x8:
497                        tmp->min = 0;
498                        tmp->max = d;
499                        break;
500                case 0xa:
501                        tmp->min = minAND(a, -1, c, -1);
502                        tmp->max = MAX(b, d);
503                        break;
504                case 0xb:
505                        tmp->min = minAND(a, -1, c, d);
506                        tmp->max = maxAND(0, b, c, d);
507                        break;
508                case 0xe:
509                        tmp->min = minAND(a, b, c, -1);
510                        tmp->max = maxAND(a, b, 0, d);
511                        break;
512        }
513}
514
515/* Get the normal op corresponding to a compound assignment op */
516static inline zend_uchar get_compound_assign_op(zend_uchar opcode) {
517        switch (opcode) {
518                case ZEND_ASSIGN_ADD: return ZEND_ADD;
519                case ZEND_ASSIGN_SUB: return ZEND_SUB;
520                case ZEND_ASSIGN_MUL: return ZEND_MUL;
521                case ZEND_ASSIGN_DIV: return ZEND_DIV;
522                case ZEND_ASSIGN_MOD: return ZEND_MOD;
523                case ZEND_ASSIGN_SL: return ZEND_SL;
524                case ZEND_ASSIGN_SR: return ZEND_SR;
525                case ZEND_ASSIGN_CONCAT: return ZEND_CONCAT;
526                case ZEND_ASSIGN_BW_OR: return ZEND_BW_OR;
527                case ZEND_ASSIGN_BW_AND: return ZEND_BW_AND;
528                case ZEND_ASSIGN_BW_XOR: return ZEND_BW_XOR;
529                case ZEND_ASSIGN_POW: return ZEND_POW;
530                EMPTY_SWITCH_DEFAULT_CASE()
531        }
532}
533
534static int zend_inference_calc_binary_op_range(
535                const zend_op_array *op_array, zend_ssa *ssa,
536                zend_op *opline, zend_ssa_op *ssa_op, zend_uchar opcode, zend_ssa_range *tmp) {
537        zend_long op1_min, op2_min, op1_max, op2_max, t1, t2, t3, t4;
538
539        switch (opcode) {
540                case ZEND_ADD:
541                        if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) {
542                                op1_min = OP1_MIN_RANGE();
543                                op2_min = OP2_MIN_RANGE();
544                                op1_max = OP1_MAX_RANGE();
545                                op2_max = OP2_MAX_RANGE();
546                                tmp->min = op1_min + op2_min;
547                                tmp->max = op1_max + op2_max;
548                                if (OP1_RANGE_UNDERFLOW() ||
549                                        OP2_RANGE_UNDERFLOW() ||
550                                        (op1_min < 0 && op2_min < 0 && tmp->min >= 0)) {
551                                        tmp->underflow = 1;
552                                        tmp->min = ZEND_LONG_MIN;
553                                }
554                                if (OP1_RANGE_OVERFLOW() ||
555                                        OP2_RANGE_OVERFLOW() ||
556                                        (op1_max > 0 && op2_max > 0 && tmp->max <= 0)) {
557                                        tmp->overflow = 1;
558                                        tmp->max = ZEND_LONG_MAX;
559                                }
560                                return 1;
561                        }
562                        break;
563                case ZEND_SUB:
564                        if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) {
565                                op1_min = OP1_MIN_RANGE();
566                                op2_min = OP2_MIN_RANGE();
567                                op1_max = OP1_MAX_RANGE();
568                                op2_max = OP2_MAX_RANGE();
569                                tmp->min = op1_min - op2_max;
570                                tmp->max = op1_max - op2_min;
571                                if (OP1_RANGE_UNDERFLOW() ||
572                                        OP2_RANGE_OVERFLOW() ||
573                                        (op1_min < 0 && op2_max > 0 && tmp->min >= 0)) {
574                                        tmp->underflow = 1;
575                                        tmp->min = ZEND_LONG_MIN;
576                                }
577                                if (OP1_RANGE_OVERFLOW() ||
578                                        OP2_RANGE_UNDERFLOW() ||
579                                        (op1_max > 0 && op2_min < 0 && tmp->max <= 0)) {
580                                        tmp->overflow = 1;
581                                        tmp->max = ZEND_LONG_MAX;
582                                }
583                                return 1;
584                        }
585                        break;
586                case ZEND_MUL:
587                        if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) {
588                                op1_min = OP1_MIN_RANGE();
589                                op2_min = OP2_MIN_RANGE();
590                                op1_max = OP1_MAX_RANGE();
591                                op2_max = OP2_MAX_RANGE();
592                                t1 = op1_min * op2_min;
593                                t2 = op1_min * op2_max;
594                                t3 = op1_max * op2_min;
595                                t4 = op1_max * op2_max;
596                                // FIXME: more careful overflow checks?
597                                if (OP1_RANGE_UNDERFLOW() ||
598                                        OP2_RANGE_UNDERFLOW() ||
599                                        OP1_RANGE_OVERFLOW()  ||
600                                        OP2_RANGE_OVERFLOW()  ||
601                                        (double)t1 != (double)op1_min * (double)op2_min ||
602                                        (double)t2 != (double)op1_min * (double)op2_max ||
603                                        (double)t3 != (double)op1_max * (double)op2_min ||
604                                        (double)t4 != (double)op1_max * (double)op2_max) {
605                                        tmp->underflow = 1;
606                                        tmp->overflow = 1;
607                                        tmp->min = ZEND_LONG_MIN;
608                                        tmp->max = ZEND_LONG_MAX;
609                                } else {
610                                        tmp->min = MIN(MIN(t1, t2), MIN(t3, t4));
611                                        tmp->max = MAX(MAX(t1, t2), MAX(t3, t4));
612                                }
613                                return 1;
614                        }
615                        break;
616                case ZEND_DIV:
617                        if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) {
618                                op1_min = OP1_MIN_RANGE();
619                                op2_min = OP2_MIN_RANGE();
620                                op1_max = OP1_MAX_RANGE();
621                                op2_max = OP2_MAX_RANGE();
622                                if (op2_min <= 0 && op2_max >= 0) {
623                                        break;
624                                }
625                                if (op1_min == ZEND_LONG_MIN && op2_max == -1) {
626                                        /* Avoid ill-defined division, which may trigger SIGFPE. */
627                                        break;
628                                }
629                                t1 = op1_min / op2_min;
630                                t2 = op1_min / op2_max;
631                                t3 = op1_max / op2_min;
632                                t4 = op1_max / op2_max;
633                                // FIXME: more careful overflow checks?
634                                if (OP1_RANGE_UNDERFLOW() ||
635                                        OP2_RANGE_UNDERFLOW() ||
636                                        OP1_RANGE_OVERFLOW()  ||
637                                        OP2_RANGE_OVERFLOW()  ||
638                                        t1 != (zend_long)((double)op1_min / (double)op2_min) ||
639                                        t2 != (zend_long)((double)op1_min / (double)op2_max) ||
640                                        t3 != (zend_long)((double)op1_max / (double)op2_min) ||
641                                        t4 != (zend_long)((double)op1_max / (double)op2_max)) {
642                                        tmp->underflow = 1;
643                                        tmp->overflow = 1;
644                                        tmp->min = ZEND_LONG_MIN;
645                                        tmp->max = ZEND_LONG_MAX;
646                                } else {
647                                        tmp->min = MIN(MIN(t1, t2), MIN(t3, t4));
648                                        tmp->max = MAX(MAX(t1, t2), MAX(t3, t4));
649                                }
650                                return 1;
651                        }
652                        break;
653                case ZEND_MOD:
654                        if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) {
655                                if (OP1_RANGE_UNDERFLOW() ||
656                                        OP2_RANGE_UNDERFLOW() ||
657                                        OP1_RANGE_OVERFLOW()  ||
658                                        OP2_RANGE_OVERFLOW()) {
659                                        tmp->min = ZEND_LONG_MIN;
660                                        tmp->max = ZEND_LONG_MAX;
661                                } else {
662                                        op1_min = OP1_MIN_RANGE();
663                                        op2_min = OP2_MIN_RANGE();
664                                        op1_max = OP1_MAX_RANGE();
665                                        op2_max = OP2_MAX_RANGE();
666                                        if (op2_min == 0 || op2_max == 0) {
667                                                /* avoid division by zero */
668                                                break;
669                                        }
670                                        t1 = (op2_min == -1) ? 0 : (op1_min % op2_min);
671                                        t2 = (op2_max == -1) ? 0 : (op1_min % op2_max);
672                                        t3 = (op2_min == -1) ? 0 : (op1_max % op2_min);
673                                        t4 = (op2_max == -1) ? 0 : (op1_max % op2_max);
674                                        tmp->min = MIN(MIN(t1, t2), MIN(t3, t4));
675                                        tmp->max = MAX(MAX(t1, t2), MAX(t3, t4));
676                                }
677                                return 1;
678                        }
679                        break;
680                case ZEND_SL:
681                        if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) {
682                                if (OP1_RANGE_UNDERFLOW() ||
683                                        OP2_RANGE_UNDERFLOW() ||
684                                        OP1_RANGE_OVERFLOW() ||
685                                        OP2_RANGE_OVERFLOW()) {
686                                        tmp->min = ZEND_LONG_MIN;
687                                        tmp->max = ZEND_LONG_MAX;
688                                } else {
689                                        op1_min = OP1_MIN_RANGE();
690                                        op2_min = OP2_MIN_RANGE();
691                                        op1_max = OP1_MAX_RANGE();
692                                        op2_max = OP2_MAX_RANGE();
693                                        t1 = op1_min << op2_min;
694                                        t2 = op1_min << op2_max;
695                                        t3 = op1_max << op2_min;
696                                        t4 = op1_max << op2_max;
697                                        tmp->min = MIN(MIN(t1, t2), MIN(t3, t4));
698                                        tmp->max = MAX(MAX(t1, t2), MAX(t3, t4));
699                                }
700                                return 1;
701                        }
702                        break;
703                case ZEND_SR:
704                        if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) {
705                                if (OP1_RANGE_UNDERFLOW() ||
706                                        OP2_RANGE_UNDERFLOW() ||
707                                        OP1_RANGE_OVERFLOW() ||
708                                        OP2_RANGE_OVERFLOW()) {
709                                        tmp->min = ZEND_LONG_MIN;
710                                        tmp->max = ZEND_LONG_MAX;
711                                } else {
712                                        op1_min = OP1_MIN_RANGE();
713                                        op2_min = OP2_MIN_RANGE();
714                                        op1_max = OP1_MAX_RANGE();
715                                        op2_max = OP2_MAX_RANGE();
716                                        t1 = op1_min >> op2_min;
717                                        t2 = op1_min >> op2_max;
718                                        t3 = op1_max >> op2_min;
719                                        t4 = op1_max >> op2_max;
720                                        tmp->min = MIN(MIN(t1, t2), MIN(t3, t4));
721                                        tmp->max = MAX(MAX(t1, t2), MAX(t3, t4));
722                                }
723                                return 1;
724                        }
725                        break;
726                case ZEND_BW_OR:
727                        if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) {
728                                if (OP1_RANGE_UNDERFLOW() ||
729                                        OP2_RANGE_UNDERFLOW() ||
730                                        OP1_RANGE_OVERFLOW() ||
731                                        OP2_RANGE_OVERFLOW()) {
732                                        tmp->min = ZEND_LONG_MIN;
733                                        tmp->max = ZEND_LONG_MAX;
734                                } else {
735                                        op1_min = OP1_MIN_RANGE();
736                                        op2_min = OP2_MIN_RANGE();
737                                        op1_max = OP1_MAX_RANGE();
738                                        op2_max = OP2_MAX_RANGE();
739                                        zend_ssa_range_or(op1_min, op1_max, op2_min, op2_max, tmp);
740                                }
741                                return 1;
742                        }
743                        break;
744                case ZEND_BW_AND:
745                        if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) {
746                                if (OP1_RANGE_UNDERFLOW() ||
747                                        OP2_RANGE_UNDERFLOW() ||
748                                        OP1_RANGE_OVERFLOW() ||
749                                        OP2_RANGE_OVERFLOW()) {
750                                        tmp->min = ZEND_LONG_MIN;
751                                        tmp->max = ZEND_LONG_MAX;
752                                } else {
753                                        op1_min = OP1_MIN_RANGE();
754                                        op2_min = OP2_MIN_RANGE();
755                                        op1_max = OP1_MAX_RANGE();
756                                        op2_max = OP2_MAX_RANGE();
757                                        zend_ssa_range_and(op1_min, op1_max, op2_min, op2_max, tmp);
758                                }
759                                return 1;
760                        }
761                        break;
762                case ZEND_BW_XOR:
763                        // TODO
764                        break;
765                EMPTY_SWITCH_DEFAULT_CASE()
766        }
767        return 0;
768}
769
770int zend_inference_calc_range(const zend_op_array *op_array, zend_ssa *ssa, int var, int widening, int narrowing, zend_ssa_range *tmp)
771{
772        uint32_t line;
773        zend_op *opline;
774        zend_long op1_min, op2_min, op1_max, op2_max;
775
776        if (ssa->vars[var].definition_phi) {
777                zend_ssa_phi *p = ssa->vars[var].definition_phi;
778                int i;
779
780                tmp->underflow = 0;
781                tmp->min = ZEND_LONG_MAX;
782                tmp->max = ZEND_LONG_MIN;
783                tmp->overflow = 0;
784                if (p->pi >= 0 && p->has_range_constraint) {
785                        zend_ssa_range_constraint *constraint = &p->constraint.range;
786                        if (constraint->negative) {
787                                if (ssa->var_info[p->sources[0]].has_range) {
788                                        *tmp = ssa->var_info[p->sources[0]].range;
789                                } else if (narrowing) {
790                                        tmp->underflow = 1;
791                                        tmp->min = ZEND_LONG_MIN;
792                                        tmp->max = ZEND_LONG_MAX;
793                                        tmp->overflow = 1;
794                                }
795
796#ifdef NEG_RANGE
797                                if (constraint->min_ssa_var < 0 &&
798                                    constraint->max_ssa_var < 0 &&
799                                    ssa->var_info[p->ssa_var].has_range) {
800                                        LOG_NEG_RANGE("%s() #%d [%ld..%ld] -> [%ld..%ld]?\n",
801                                                ZSTR_VAL(op_array->function_name),
802                                                p->ssa_var,
803                                                ssa->var_info[p->ssa_var].range.min,
804                                                ssa->var_info[p->ssa_var].range.max,
805                                                tmp->min,
806                                                tmp->max);
807                                        if (constraint->negative == NEG_USE_LT &&
808                                            tmp->max >= constraint->range.min) {
809                                                tmp->overflow = 0;
810                                                tmp->max = constraint->range.min - 1;
811                                                LOG_NEG_RANGE("  => [%ld..%ld]\n", tmp->min, tmp->max);
812                                        } else if (constraint->negative == NEG_USE_GT &&
813                                                   tmp->min <= constraint->range.max) {
814                                                tmp->underflow = 0;
815                                                tmp->min = constraint->range.max + 1;
816                                                LOG_NEG_RANGE("  => [%ld..%ld]\n", tmp->min, tmp->max);
817                                        }
818                                }
819#endif
820                        } else if (ssa->var_info[p->sources[0]].has_range) {
821                                /* intersection */
822                                *tmp = ssa->var_info[p->sources[0]].range;
823                                if (constraint->min_ssa_var < 0) {
824                                        tmp->underflow = constraint->range.underflow && tmp->underflow;
825                                        tmp->min = MAX(constraint->range.min, tmp->min);
826#ifdef SYM_RANGE
827                                } else if (narrowing && ssa->var_info[constraint->min_ssa_var].has_range) {
828                                        tmp->underflow = ssa->var_info[constraint->min_ssa_var].range.underflow && tmp->underflow;
829                                        tmp->min = MAX(ssa->var_info[constraint->min_ssa_var].range.min + constraint->range.min, tmp->min);
830#endif
831                                }
832                                if (constraint->max_ssa_var < 0) {
833                                        tmp->max = MIN(constraint->range.max, tmp->max);
834                                        tmp->overflow = constraint->range.overflow && tmp->overflow;
835#ifdef SYM_RANGE
836                                } else if (narrowing && ssa->var_info[constraint->max_ssa_var].has_range) {
837                                        tmp->max = MIN(ssa->var_info[constraint->max_ssa_var].range.max + constraint->range.max, tmp->max);
838                                        tmp->overflow = ssa->var_info[constraint->max_ssa_var].range.overflow && tmp->overflow;
839#endif
840                                }
841                        } else if (narrowing) {
842                                if (constraint->min_ssa_var < 0) {
843                                        tmp->underflow = constraint->range.underflow;
844                                        tmp->min = constraint->range.min;
845#ifdef SYM_RANGE
846                                } else if (narrowing && ssa->var_info[constraint->min_ssa_var].has_range) {
847                                        tmp->underflow = ssa->var_info[constraint->min_ssa_var].range.underflow;
848                                        tmp->min = ssa->var_info[constraint->min_ssa_var].range.min + constraint->range.min;
849#endif
850                                } else {
851                                        tmp->underflow = 1;
852                                        tmp->min = ZEND_LONG_MIN;
853                                }
854                                if (constraint->max_ssa_var < 0) {
855                                        tmp->max = constraint->range.max;
856                                        tmp->overflow = constraint->range.overflow;
857#ifdef SYM_RANGE
858                                } else if (narrowing && ssa->var_info[constraint->max_ssa_var].has_range) {
859                                        tmp->max = ssa->var_info[constraint->max_ssa_var].range.max + constraint->range.max;
860                                        tmp->overflow = ssa->var_info[constraint->max_ssa_var].range.overflow;
861#endif
862                                } else {
863                                        tmp->max = ZEND_LONG_MAX;
864                                        tmp->overflow = 1;
865                                }
866                        }
867                } else {
868                        for (i = 0; i < ssa->cfg.blocks[p->block].predecessors_count; i++) {
869                                if (p->sources[i] >= 0 && ssa->var_info[p->sources[i]].has_range) {
870                                        /* union */
871                                        tmp->underflow |= ssa->var_info[p->sources[i]].range.underflow;
872                                        tmp->min = MIN(tmp->min, ssa->var_info[p->sources[i]].range.min);
873                                        tmp->max = MAX(tmp->max, ssa->var_info[p->sources[i]].range.max);
874                                        tmp->overflow |= ssa->var_info[p->sources[i]].range.overflow;
875                                } else if (narrowing) {
876                                        tmp->underflow = 1;
877                                        tmp->min = ZEND_LONG_MIN;
878                                        tmp->max = ZEND_LONG_MAX;
879                                        tmp->overflow = 1;
880                                }
881                        }
882                }
883                return (tmp->min <= tmp->max);
884        } else if (ssa->vars[var].definition < 0) {
885                if (var < op_array->last_var &&
886                    op_array->function_name) {
887
888                        tmp->min = 0;
889                        tmp->max = 0;
890                        tmp->underflow = 0;
891                        tmp->overflow = 0;
892                        return 1;
893                }
894                return 0;
895        }
896        line = ssa->vars[var].definition;
897        opline = op_array->opcodes + line;
898
899        tmp->underflow = 0;
900        tmp->overflow = 0;
901        switch (opline->opcode) {
902                case ZEND_ADD:
903                case ZEND_SUB:
904                case ZEND_MUL:
905                case ZEND_DIV:
906                case ZEND_MOD:
907                case ZEND_SL:
908                case ZEND_SR:
909                case ZEND_BW_OR:
910                case ZEND_BW_AND:
911                case ZEND_BW_XOR:
912                        if (ssa->ops[line].result_def == var) {
913                                return zend_inference_calc_binary_op_range(
914                                        op_array, ssa, opline, &ssa->ops[line], opline->opcode, tmp);
915                        }
916                        break;
917
918                case ZEND_BW_NOT:
919                        if (ssa->ops[line].result_def == var) {
920                                if (OP1_HAS_RANGE()) {
921                                        if (OP1_RANGE_UNDERFLOW() ||
922                                            OP1_RANGE_OVERFLOW()) {
923                                                tmp->min = ZEND_LONG_MIN;
924                                                tmp->max = ZEND_LONG_MAX;
925                                        } else {
926                                                op1_min = OP1_MIN_RANGE();
927                                                op1_max = OP1_MAX_RANGE();
928                                                tmp->min = ~op1_max;
929                                                tmp->max = ~op1_min;
930                                        }
931                                        return 1;
932                                }
933                        }
934                        break;
935                case ZEND_CAST:
936                        if (ssa->ops[line].op1_def == var) {
937                                if (ssa->ops[line].op1_def >= 0) {
938                                        if (OP1_HAS_RANGE()) {
939                                                tmp->underflow = OP1_RANGE_UNDERFLOW();
940                                                tmp->min = OP1_MIN_RANGE();
941                                                tmp->max = OP1_MAX_RANGE();
942                                                tmp->overflow  = OP1_RANGE_OVERFLOW();
943                                                return 1;
944                                        }
945                                }
946                        } else if (ssa->ops[line].result_def == var) {
947                                if (opline->extended_value == IS_NULL) {
948                                        tmp->min = 0;
949                                        tmp->max = 0;
950                                        return 1;
951                                } else if (opline->extended_value == _IS_BOOL) {
952                                        if (OP1_HAS_RANGE()) {
953                                                op1_min = OP1_MIN_RANGE();
954                                                op1_max = OP1_MAX_RANGE();
955                                                tmp->min = (op1_min > 0 || op1_max < 0);
956                                                tmp->max = (op1_min != 0 || op1_max != 0);
957                                                return 1;
958                                        } else {
959                                                tmp->min = 0;
960                                                tmp->max = 1;
961                                                return 1;
962                                        }
963                                } else if (opline->extended_value == IS_LONG) {
964                                        if (OP1_HAS_RANGE()) {
965                                                tmp->min = OP1_MIN_RANGE();
966                                                tmp->max = OP1_MAX_RANGE();
967                                                return 1;
968                                        } else {
969                                                tmp->min = ZEND_LONG_MIN;
970                                                tmp->max = ZEND_LONG_MAX;
971                                                return 1;
972                                        }
973                                }
974                        }
975                        break;
976                case ZEND_BOOL:
977                case ZEND_JMPZ_EX:
978                case ZEND_JMPNZ_EX:
979                        if (ssa->ops[line].result_def == var) {
980                                if (OP1_HAS_RANGE()) {
981                                        op1_min = OP1_MIN_RANGE();
982                                        op1_max = OP1_MAX_RANGE();
983                                        tmp->min = (op1_min > 0 || op1_max < 0);
984                                        tmp->max = (op1_min != 0 || op1_max != 0);
985                                        return 1;
986                                } else {
987                                        tmp->min = 0;
988                                        tmp->max = 1;
989                                        return 1;
990                                }
991                        }
992                        break;
993                case ZEND_BOOL_NOT:
994                        if (ssa->ops[line].result_def == var) {
995                                if (OP1_HAS_RANGE()) {
996                                        op1_min = OP1_MIN_RANGE();
997                                        op1_max = OP1_MAX_RANGE();
998                                        tmp->min = (op1_min == 0 && op1_max == 0);
999                                        tmp->max = (op1_min <= 0 && op1_max >= 0);
1000                                        return 1;
1001                                } else {
1002                                        tmp->min = 0;
1003                                        tmp->max = 1;
1004                                        return 1;
1005                                }
1006                        }
1007                        break;
1008                case ZEND_BOOL_XOR:
1009                        if (ssa->ops[line].result_def == var) {
1010                                if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) {
1011                                        op1_min = OP1_MIN_RANGE();
1012                                        op2_min = OP2_MIN_RANGE();
1013                                        op1_max = OP1_MAX_RANGE();
1014                                        op2_max = OP2_MAX_RANGE();
1015                                        op1_min = (op1_min > 0 || op1_max < 0);
1016                                        op1_max = (op1_min != 0 || op1_max != 0);
1017                                        op2_min = (op2_min > 0 || op2_max < 0);
1018                                        op2_max = (op2_min != 0 || op2_max != 0);
1019                                        tmp->min = 0;
1020                                        tmp->max = 1;
1021                                        if (op1_min == op1_max && op2_min == op2_max) {
1022                                                if (op1_min == op2_min) {
1023                                                        tmp->max = 0;
1024                                                } else {
1025                                                        tmp->min = 1;
1026                                                }
1027                                        }
1028                                        return 1;
1029                                } else {
1030                                        tmp->min = 0;
1031                                        tmp->max = 1;
1032                                        return 1;
1033                                }
1034                        }
1035                        break;
1036                case ZEND_IS_IDENTICAL:
1037                case ZEND_IS_EQUAL:
1038                        if (ssa->ops[line].result_def == var) {
1039                                if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) {
1040                                        op1_min = OP1_MIN_RANGE();
1041                                        op2_min = OP2_MIN_RANGE();
1042                                        op1_max = OP1_MAX_RANGE();
1043                                        op2_max = OP2_MAX_RANGE();
1044
1045                                        tmp->min = (op1_min == op1_max &&
1046                                                   op2_min == op2_max &&
1047                                                   op1_min == op2_max);
1048                                        tmp->max = (op1_min <= op2_max && op1_max >= op2_min);
1049                                        return 1;
1050                                } else {
1051                                        tmp->min = 0;
1052                                        tmp->max = 1;
1053                                        return 1;
1054                                }
1055                        }
1056                        break;
1057                case ZEND_IS_NOT_IDENTICAL:
1058                case ZEND_IS_NOT_EQUAL:
1059                        if (ssa->ops[line].result_def == var) {
1060                                if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) {
1061                                        op1_min = OP1_MIN_RANGE();
1062                                        op2_min = OP2_MIN_RANGE();
1063                                        op1_max = OP1_MAX_RANGE();
1064                                        op2_max = OP2_MAX_RANGE();
1065
1066                                        tmp->min = (op1_min > op2_max || op1_max < op2_min);
1067                                        tmp->max = (op1_min != op1_max ||
1068                                                   op2_min != op2_max ||
1069                                                   op1_min != op2_max);
1070                                        return 1;
1071                                } else {
1072                                        tmp->min = 0;
1073                                        tmp->max = 1;
1074                                        return 1;
1075                                }
1076                        }
1077                        break;
1078                case ZEND_IS_SMALLER:
1079                        if (ssa->ops[line].result_def == var) {
1080                                if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) {
1081                                        op1_min = OP1_MIN_RANGE();
1082                                        op2_min = OP2_MIN_RANGE();
1083                                        op1_max = OP1_MAX_RANGE();
1084                                        op2_max = OP2_MAX_RANGE();
1085
1086                                        tmp->min = op1_max < op2_min;
1087                                        tmp->max = op1_min < op2_max;
1088                                        return 1;
1089                                } else {
1090                                        tmp->min = 0;
1091                                        tmp->max = 1;
1092                                        return 1;
1093                                }
1094                        }
1095                        break;
1096                case ZEND_IS_SMALLER_OR_EQUAL:
1097                        if (ssa->ops[line].result_def == var) {
1098                                if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) {
1099                                        op1_min = OP1_MIN_RANGE();
1100                                        op2_min = OP2_MIN_RANGE();
1101                                        op1_max = OP1_MAX_RANGE();
1102                                        op2_max = OP2_MAX_RANGE();
1103
1104                                        tmp->min = op1_max <= op2_min;
1105                                        tmp->max = op1_min <= op2_max;
1106                                        return 1;
1107                                } else {
1108                                        tmp->min = 0;
1109                                        tmp->max = 1;
1110                                        return 1;
1111                                }
1112                        }
1113                        break;
1114                case ZEND_QM_ASSIGN:
1115                case ZEND_JMP_SET:
1116                case ZEND_COALESCE:
1117                        if (ssa->ops[line].op1_def == var) {
1118                                if (ssa->ops[line].op1_def >= 0) {
1119                                        if (OP1_HAS_RANGE()) {
1120                                                tmp->underflow = OP1_RANGE_UNDERFLOW();
1121                                                tmp->min = OP1_MIN_RANGE();
1122                                                tmp->max = OP1_MAX_RANGE();
1123                                                tmp->overflow  = OP1_RANGE_OVERFLOW();
1124                                                return 1;
1125                                        }
1126                                }
1127                        }
1128                        if (ssa->ops[line].result_def == var) {
1129                                if (OP1_HAS_RANGE()) {
1130                                        tmp->min = OP1_MIN_RANGE();
1131                                        tmp->max = OP1_MAX_RANGE();
1132                                        tmp->underflow = OP1_RANGE_UNDERFLOW();
1133                                        tmp->overflow  = OP1_RANGE_OVERFLOW();
1134                                        return 1;
1135                                }
1136                        }
1137                        break;
1138                case ZEND_ASSERT_CHECK:
1139                        if (ssa->ops[line].result_def == var) {
1140                                tmp->min = 0;
1141                                tmp->max = 1;
1142                                return 1;
1143                        }
1144                        break;
1145                case ZEND_SEND_VAR:
1146                        if (ssa->ops[line].op1_def == var) {
1147                                if (ssa->ops[line].op1_def >= 0) {
1148                                        if (OP1_HAS_RANGE()) {
1149                                                tmp->underflow = OP1_RANGE_UNDERFLOW();
1150                                                tmp->min = OP1_MIN_RANGE();
1151                                                tmp->max = OP1_MAX_RANGE();
1152                                                tmp->overflow  = OP1_RANGE_OVERFLOW();
1153                                                return 1;
1154                                        }
1155                                }
1156                        }
1157                        break;
1158                case ZEND_PRE_INC:
1159                        if (ssa->ops[line].op1_def == var || ssa->ops[line].result_def == var) {
1160                                if (OP1_HAS_RANGE()) {
1161                                        tmp->min = OP1_MIN_RANGE();
1162                                        tmp->max = OP1_MAX_RANGE();
1163                                        tmp->underflow = OP1_RANGE_UNDERFLOW();
1164                                        tmp->overflow = OP1_RANGE_OVERFLOW();
1165                                        if (tmp->max < ZEND_LONG_MAX) {
1166                                                tmp->max++;
1167                                        } else {
1168                                                tmp->overflow = 1;
1169                                        }
1170                                        if (tmp->min < ZEND_LONG_MAX && !tmp->underflow) {
1171                                                tmp->min++;
1172                                        }
1173                                        return 1;
1174                                }
1175                        }
1176                        break;
1177                case ZEND_PRE_DEC:
1178                        if (ssa->ops[line].op1_def == var || ssa->ops[line].result_def == var) {
1179                                if (OP1_HAS_RANGE()) {
1180                                        tmp->min = OP1_MIN_RANGE();
1181                                        tmp->max = OP1_MAX_RANGE();
1182                                        tmp->underflow = OP1_RANGE_UNDERFLOW();
1183                                        tmp->overflow = OP1_RANGE_OVERFLOW();
1184                                        if (tmp->min > ZEND_LONG_MIN) {
1185                                                tmp->min--;
1186                                        } else {
1187                                                tmp->underflow = 1;
1188                                        }
1189                                        if (tmp->max > ZEND_LONG_MIN && !tmp->overflow) {
1190                                                tmp->max--;
1191                                        }
1192                                        return 1;
1193                                }
1194                        }
1195                        break;
1196                case ZEND_POST_INC:
1197                        if (ssa->ops[line].op1_def == var || ssa->ops[line].result_def == var) {
1198                                if (OP1_HAS_RANGE()) {
1199                                        tmp->min = OP1_MIN_RANGE();
1200                                        tmp->max = OP1_MAX_RANGE();
1201                                        tmp->underflow = OP1_RANGE_UNDERFLOW();
1202                                        tmp->overflow = OP1_RANGE_OVERFLOW();
1203                                        if (ssa->ops[line].result_def == var) {
1204                                                return 1;
1205                                        }
1206                                        if (tmp->max < ZEND_LONG_MAX) {
1207                                                tmp->max++;
1208                                        } else {
1209                                                tmp->overflow = 1;
1210                                        }
1211                                        if (tmp->min < ZEND_LONG_MAX && !tmp->underflow) {
1212                                                tmp->min++;
1213                                        }
1214                                        return 1;
1215                                }
1216                        }
1217                        break;
1218                case ZEND_POST_DEC:
1219                        if (ssa->ops[line].op1_def == var || ssa->ops[line].result_def == var) {
1220                                if (OP1_HAS_RANGE()) {
1221                                        tmp->min = OP1_MIN_RANGE();
1222                                        tmp->max = OP1_MAX_RANGE();
1223                                        tmp->underflow = OP1_RANGE_UNDERFLOW();
1224                                        tmp->overflow = OP1_RANGE_OVERFLOW();
1225                                        if (ssa->ops[line].result_def == var) {
1226                                                return 1;
1227                                        }
1228                                        if (tmp->min > ZEND_LONG_MIN) {
1229                                                tmp->min--;
1230                                        } else {
1231                                                tmp->underflow = 1;
1232                                        }
1233                                        if (tmp->max > ZEND_LONG_MIN && !tmp->overflow) {
1234                                                tmp->max--;
1235                                        }
1236                                        return 1;
1237                                }
1238                        }
1239                        break;
1240                case ZEND_UNSET_DIM:
1241                case ZEND_UNSET_OBJ:
1242                        if (ssa->ops[line].op1_def == var) {
1243                                /* If op1 is scalar, UNSET_DIM and UNSET_OBJ have no effect, so we can keep
1244                                 * the previous ranges. */
1245                                if (OP1_HAS_RANGE()) {
1246                                        tmp->min = OP1_MIN_RANGE();
1247                                        tmp->max = OP1_MAX_RANGE();
1248                                        tmp->underflow = OP1_RANGE_UNDERFLOW();
1249                                        tmp->overflow  = OP1_RANGE_OVERFLOW();
1250                                        return 1;
1251                                }
1252                        }
1253                        break;
1254                case ZEND_ASSIGN:
1255                        if (ssa->ops[line].op1_def == var || ssa->ops[line].op2_def == var || ssa->ops[line].result_def == var) {
1256                                if (OP2_HAS_RANGE()) {
1257                                        tmp->min = OP2_MIN_RANGE();
1258                                        tmp->max = OP2_MAX_RANGE();
1259                                        tmp->underflow = OP2_RANGE_UNDERFLOW();
1260                                        tmp->overflow  = OP2_RANGE_OVERFLOW();
1261                                        return 1;
1262                                }
1263                        }
1264                        break;
1265                case ZEND_ASSIGN_DIM:
1266                case ZEND_ASSIGN_OBJ:
1267                        if (ssa->ops[line+1].op1_def == var) {
1268                                if ((opline+1)->opcode == ZEND_OP_DATA) {
1269                                        opline++;
1270                                        tmp->min = OP1_MIN_RANGE();
1271                                        tmp->max = OP1_MAX_RANGE();
1272                                        tmp->underflow = OP1_RANGE_UNDERFLOW();
1273                                        tmp->overflow  = OP1_RANGE_OVERFLOW();
1274                                        return 1;
1275                                }
1276                        }
1277                        break;
1278                case ZEND_ASSIGN_ADD:
1279                case ZEND_ASSIGN_SUB:
1280                case ZEND_ASSIGN_MUL:
1281                case ZEND_ASSIGN_DIV:
1282                case ZEND_ASSIGN_MOD:
1283                case ZEND_ASSIGN_SL:
1284                case ZEND_ASSIGN_SR:
1285                case ZEND_ASSIGN_BW_OR:
1286                case ZEND_ASSIGN_BW_AND:
1287                case ZEND_ASSIGN_BW_XOR:
1288                        if (opline->extended_value == 0) {
1289                                if (ssa->ops[line].op1_def == var || ssa->ops[line].result_def == var) {
1290                                        return zend_inference_calc_binary_op_range(
1291                                                op_array, ssa, opline, &ssa->ops[line],
1292                                                get_compound_assign_op(opline->opcode), tmp);
1293                                }
1294                        } else if ((opline+1)->opcode == ZEND_OP_DATA) {
1295                                if (ssa->ops[line+1].op1_def == var) {
1296                                        opline++;
1297                                        if (OP1_HAS_RANGE()) {
1298                                                tmp->min = OP1_MIN_RANGE();
1299                                                tmp->max = OP1_MAX_RANGE();
1300                                                tmp->underflow = OP1_RANGE_UNDERFLOW();
1301                                                tmp->overflow  = OP1_RANGE_OVERFLOW();
1302                                                return 1;
1303                                        }
1304                                }
1305                        }
1306                        break;
1307//              case ZEND_ASSIGN_CONCAT:
1308                case ZEND_OP_DATA:
1309                        if ((opline-1)->opcode == ZEND_ASSIGN_DIM ||
1310                            (opline-1)->opcode == ZEND_ASSIGN_OBJ ||
1311                            (opline-1)->opcode == ZEND_ASSIGN_ADD ||
1312                            (opline-1)->opcode == ZEND_ASSIGN_SUB ||
1313                            (opline-1)->opcode == ZEND_ASSIGN_MUL) {
1314                                if (ssa->ops[line].op1_def == var) {
1315                                        if (OP1_HAS_RANGE()) {
1316                                                tmp->min = OP1_MIN_RANGE();
1317                                                tmp->max = OP1_MAX_RANGE();
1318                                                tmp->underflow = OP1_RANGE_UNDERFLOW();
1319                                                tmp->overflow  = OP1_RANGE_OVERFLOW();
1320                                                return 1;
1321                                        }
1322                                }
1323                                break;
1324                        }
1325                        break;
1326                case ZEND_RECV:
1327                case ZEND_RECV_INIT:
1328                        if (ssa->ops[line].result_def == var) {
1329                                zend_func_info *func_info = ZEND_FUNC_INFO(op_array);
1330
1331                                if (func_info &&
1332                                    (int)opline->op1.num-1 < func_info->num_args &&
1333                                    func_info->arg_info[opline->op1.num-1].info.has_range) {
1334                                        *tmp = func_info->arg_info[opline->op1.num-1].info.range;
1335                                        return 1;
1336                                } else if (op_array->arg_info &&
1337                                    opline->op1.num <= op_array->num_args) {
1338                                        if (op_array->arg_info[opline->op1.num-1].type_hint == IS_LONG) {
1339                                                tmp->underflow = 0;
1340                                                tmp->min = ZEND_LONG_MIN;
1341                                                tmp->max = ZEND_LONG_MAX;
1342                                                tmp->overflow = 0;
1343                                                return 1;
1344                                        } else if (op_array->arg_info[opline->op1.num-1].type_hint == _IS_BOOL) {
1345                                                tmp->underflow = 0;
1346                                                tmp->min = 0;
1347                                                tmp->max = 1;
1348                                                tmp->overflow = 0;
1349                                                return 1;
1350                                        }
1351                                }
1352                        }
1353                        break;
1354                case ZEND_STRLEN:
1355                        if (ssa->ops[line].result_def == var) {
1356#if SIZEOF_ZEND_LONG == 4
1357                                /* The length of a string is a non-negative integer. However, on 32-bit
1358                                 * platforms overflows into negative lengths may occur, so it's better
1359                                 * to not assume any particular range. */
1360                                tmp->min = ZEND_LONG_MIN;
1361#else
1362                                tmp->min = 0;
1363#endif
1364                                tmp->max = ZEND_LONG_MAX;
1365                                return 1;
1366                        }
1367                        break;
1368                case ZEND_DO_FCALL:
1369                case ZEND_DO_ICALL:
1370                case ZEND_DO_UCALL:
1371                case ZEND_DO_FCALL_BY_NAME:
1372                        if (ssa->ops[line].result_def == var) {
1373                                zend_func_info *func_info = ZEND_FUNC_INFO(op_array);
1374                                zend_call_info *call_info;
1375                                if (!func_info || !func_info->call_map) {
1376                                        break;
1377                                }
1378
1379                                call_info = func_info->call_map[opline - op_array->opcodes];
1380                                if (!call_info) {
1381                                        break;
1382                                }
1383                                if (call_info->callee_func->type == ZEND_USER_FUNCTION) {
1384                                        func_info = ZEND_FUNC_INFO(&call_info->callee_func->op_array);
1385                                        if (func_info && func_info->return_info.has_range) {
1386                                                *tmp = func_info->return_info.range;
1387                                                return 1;
1388                                        }
1389                                }
1390//TODO: we can't use type inference for internal functions at this point ???
1391#if 0
1392                                        uint32_t type;
1393
1394                                        type = zend_get_func_info(call_info, ssa);
1395                                        if (!(type & (MAY_BE_ANY - (MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG)))) {
1396                                                tmp->underflow = 0;
1397                                                tmp->min = 0;
1398                                                tmp->max = 0;
1399                                                tmp->overflow = 0;
1400                                                if (type & MAY_BE_LONG) {
1401                                                        tmp->min = ZEND_LONG_MIN;
1402                                                        tmp->max = ZEND_LONG_MAX;
1403                                                } else if (type & MAY_BE_TRUE) {
1404                                                        if (!(type & (MAY_BE_NULL|MAY_BE_FALSE))) {
1405                                                                tmp->min = 1;
1406                                                        }
1407                                                        tmp->max = 1;
1408                                                }
1409                                                return 1;
1410                                        }
1411#endif
1412                        }
1413                        break;
1414                // FIXME: support for more opcodes
1415                default:
1416                        break;
1417        }
1418        return 0;
1419}
1420
1421void zend_inference_init_range(const zend_op_array *op_array, zend_ssa *ssa, int var, zend_bool underflow, zend_long min, zend_long max, zend_bool overflow)
1422{
1423        if (underflow) {
1424                min = ZEND_LONG_MIN;
1425        }
1426        if (overflow) {
1427                max = ZEND_LONG_MAX;
1428        }
1429        ssa->var_info[var].has_range = 1;
1430        ssa->var_info[var].range.underflow = underflow;
1431        ssa->var_info[var].range.min = min;
1432        ssa->var_info[var].range.max = max;
1433        ssa->var_info[var].range.overflow = overflow;
1434        LOG_SSA_RANGE("  change range (init      SCC %2d) %2d [%s%ld..%ld%s]\n", ssa->vars[var].scc, var, (underflow?"-- ":""), min, max, (overflow?" ++":""));
1435}
1436
1437int zend_inference_widening_meet(zend_ssa_var_info *var_info, zend_ssa_range *r)
1438{
1439        if (!var_info->has_range) {
1440                var_info->has_range = 1;
1441        } else {
1442                if (r->underflow ||
1443                    var_info->range.underflow ||
1444                    r->min < var_info->range.min) {
1445                        r->underflow = 1;
1446                        r->min = ZEND_LONG_MIN;
1447                }
1448                if (r->overflow ||
1449                    var_info->range.overflow ||
1450                    r->max > var_info->range.max) {
1451                        r->overflow = 1;
1452                        r->max = ZEND_LONG_MAX;
1453                }
1454                if (var_info->range.min == r->min &&
1455                    var_info->range.max == r->max &&
1456                    var_info->range.underflow == r->underflow &&
1457                    var_info->range.overflow == r->overflow) {
1458                        return 0;
1459                }
1460        }
1461        var_info->range = *r;
1462        return 1;
1463}
1464
1465static int zend_ssa_range_widening(const zend_op_array *op_array, zend_ssa *ssa, int var, int scc)
1466{
1467        zend_ssa_range tmp;
1468
1469        if (zend_inference_calc_range(op_array, ssa, var, 1, 0, &tmp)) {
1470                if (zend_inference_widening_meet(&ssa->var_info[var], &tmp)) {
1471                        LOG_SSA_RANGE("  change range (widening  SCC %2d) %2d [%s%ld..%ld%s]\n", scc, var, (tmp.underflow?"-- ":""), tmp.min, tmp.max, (tmp.overflow?" ++":""));
1472                        return 1;
1473                }
1474        }
1475        return 0;
1476}
1477
1478int zend_inference_narrowing_meet(zend_ssa_var_info *var_info, zend_ssa_range *r)
1479{
1480        if (!var_info->has_range) {
1481                var_info->has_range = 1;
1482        } else {
1483                if (!r->underflow &&
1484                    !var_info->range.underflow &&
1485                    var_info->range.min < r->min) {
1486                        r->min = var_info->range.min;
1487                }
1488                if (!r->overflow &&
1489                    !var_info->range.overflow &&
1490                    var_info->range.max > r->max) {
1491                        r->max = var_info->range.max;
1492                }
1493                if (r->underflow) {
1494                        r->min = ZEND_LONG_MIN;
1495                }
1496                if (r->overflow) {
1497                        r->max = ZEND_LONG_MAX;
1498                }
1499                if (var_info->range.min == r->min &&
1500                    var_info->range.max == r->max &&
1501                    var_info->range.underflow == r->underflow &&
1502                    var_info->range.overflow == r->overflow) {
1503                        return 0;
1504                }
1505        }
1506        var_info->range = *r;
1507        return 1;
1508}
1509
1510static int zend_ssa_range_narrowing(const zend_op_array *op_array, zend_ssa *ssa, int var, int scc)
1511{
1512        zend_ssa_range tmp;
1513
1514        if (zend_inference_calc_range(op_array, ssa, var, 0, 1, &tmp)) {
1515                if (zend_inference_narrowing_meet(&ssa->var_info[var], &tmp)) {
1516                        LOG_SSA_RANGE("  change range (narrowing SCC %2d) %2d [%s%ld..%ld%s]\n", scc, var, (tmp.underflow?"-- ":""), tmp.min, tmp.max, (tmp.overflow?" ++":""));
1517                        return 1;
1518                }
1519        }
1520        return 0;
1521}
1522
1523#ifdef NEG_RANGE
1524# define CHECK_INNER_CYCLE(var2) \
1525        do { \
1526                if (ssa->vars[var2].scc == ssa->vars[var].scc && \
1527                    !ssa->vars[var2].scc_entry && \
1528                    !zend_bitset_in(visited, var2) && \
1529                        zend_check_inner_cycles(op_array, ssa, worklist, visited, var2)) { \
1530                        return 1; \
1531                } \
1532        } while (0)
1533
1534static int zend_check_inner_cycles(const zend_op_array *op_array, zend_ssa *ssa, zend_bitset worklist, zend_bitset visited, int var)
1535{
1536        if (zend_bitset_in(worklist, var)) {
1537                return 1;
1538        }
1539        zend_bitset_incl(worklist, var);
1540        FOR_EACH_VAR_USAGE(var, CHECK_INNER_CYCLE);
1541        zend_bitset_incl(visited, var);
1542        return 0;
1543}
1544#endif
1545
1546static void zend_infer_ranges_warmup(const zend_op_array *op_array, zend_ssa *ssa, int *scc_var, int *next_scc_var, int scc)
1547{
1548        int worklist_len = zend_bitset_len(ssa->vars_count);
1549        int j, n;
1550        zend_ssa_range tmp;
1551        ALLOCA_FLAG(use_heap);
1552        zend_bitset worklist = do_alloca(sizeof(zend_ulong) * worklist_len * 2, use_heap);
1553        zend_bitset visited = worklist + worklist_len;
1554#ifdef NEG_RANGE
1555        int has_inner_cycles = 0;
1556
1557        memset(worklist, 0, sizeof(zend_ulong) * worklist_len);
1558        memset(visited, 0, sizeof(zend_ulong) * worklist_len);
1559        j = scc_var[scc];
1560        while (j >= 0) {
1561                if (!zend_bitset_in(visited, j) &&
1562                    zend_check_inner_cycles(op_array, ssa, worklist, visited, j)) {
1563                        has_inner_cycles = 1;
1564                        break;
1565                }
1566                j = next_scc_var[j];
1567        }
1568#endif
1569
1570        memset(worklist, 0, sizeof(zend_ulong) * worklist_len);
1571
1572        for (n = 0; n < RANGE_WARMUP_PASSES; n++) {
1573                j= scc_var[scc];
1574                while (j >= 0) {
1575                        if (ssa->vars[j].scc_entry) {
1576                                zend_bitset_incl(worklist, j);
1577                        }
1578                        j = next_scc_var[j];
1579                }
1580
1581                memset(visited, 0, sizeof(zend_ulong) * worklist_len);
1582
1583                WHILE_WORKLIST(worklist, worklist_len, j) {
1584                        if (zend_inference_calc_range(op_array, ssa, j, 0, 0, &tmp)) {
1585#ifdef NEG_RANGE
1586                                if (!has_inner_cycles &&
1587                                    ssa->var_info[j].has_range &&
1588                                    ssa->vars[j].definition_phi &&
1589                                    ssa->vars[j].definition_phi->pi >= 0 &&
1590                                        ssa->vars[j].definition_phi->has_range_constraint &&
1591                                    ssa->vars[j].definition_phi->constraint.range.negative &&
1592                                    ssa->vars[j].definition_phi->constraint.range.min_ssa_var < 0 &&
1593                                    ssa->vars[j].definition_phi->constraint.range.min_ssa_var < 0) {
1594                                        zend_ssa_range_constraint *constraint =
1595                                                &ssa->vars[j].definition_phi->constraint.range;
1596                                        if (tmp.min == ssa->var_info[j].range.min &&
1597                                            tmp.max == ssa->var_info[j].range.max) {
1598                                                if (constraint->negative == NEG_INIT) {
1599                                                        LOG_NEG_RANGE("#%d INVARIANT\n", j);
1600                                                        constraint->negative = NEG_INVARIANT;
1601                                                }
1602                                        } else if (tmp.min == ssa->var_info[j].range.min &&
1603                                                   tmp.max == ssa->var_info[j].range.max + 1 &&
1604                                                   tmp.max < constraint->range.min) {
1605                                                if (constraint->negative == NEG_INIT ||
1606                                                    constraint->negative == NEG_INVARIANT) {
1607                                                        LOG_NEG_RANGE("#%d LT\n", j);
1608                                                        constraint->negative = NEG_USE_LT;
1609//???NEG
1610                                                } else if (constraint->negative == NEG_USE_GT) {
1611                                                        LOG_NEG_RANGE("#%d UNKNOWN\n", j);
1612                                                        constraint->negative = NEG_UNKNOWN;
1613                                                }
1614                                        } else if (tmp.max == ssa->var_info[j].range.max &&
1615                                               tmp.min == ssa->var_info[j].range.min - 1 &&
1616                                                   tmp.min > constraint->range.max) {
1617                                                if (constraint->negative == NEG_INIT ||
1618                                                    constraint->negative == NEG_INVARIANT) {
1619                                                        LOG_NEG_RANGE("#%d GT\n", j);
1620                                                        constraint->negative = NEG_USE_GT;
1621//???NEG
1622                                                } else if (constraint->negative == NEG_USE_LT) {
1623                                                        LOG_NEG_RANGE("#%d UNKNOWN\n", j);
1624                                                        constraint->negative = NEG_UNKNOWN;
1625                                                }
1626                                        } else {
1627                                                LOG_NEG_RANGE("#%d UNKNOWN\n", j);
1628                                                constraint->negative = NEG_UNKNOWN;
1629                                        }
1630                                }
1631#endif
1632                                if (zend_inference_narrowing_meet(&ssa->var_info[j], &tmp)) {
1633                                        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?" ++":""));
1634                                        zend_bitset_incl(visited, j);
1635                                        FOR_EACH_VAR_USAGE(j, ADD_SCC_VAR_1);
1636                                }
1637                        }
1638                } WHILE_WORKLIST_END();
1639        }
1640        free_alloca(worklist, use_heap);
1641}
1642
1643static int zend_infer_ranges(const zend_op_array *op_array, zend_ssa *ssa) /* {{{ */
1644{
1645        int worklist_len = zend_bitset_len(ssa->vars_count);
1646        zend_bitset worklist;
1647        int *next_scc_var;
1648        int *scc_var;
1649        zend_ssa_phi *p;
1650        zend_ssa_range tmp;
1651        int scc, j;
1652        ALLOCA_FLAG(use_heap);
1653
1654        worklist = do_alloca(
1655                ZEND_MM_ALIGNED_SIZE(sizeof(zend_ulong) * worklist_len) +
1656                ZEND_MM_ALIGNED_SIZE(sizeof(int) * ssa->vars_count) +
1657                sizeof(int) * ssa->sccs, use_heap);
1658        next_scc_var = (int*)((char*)worklist + ZEND_MM_ALIGNED_SIZE(sizeof(zend_ulong) * worklist_len));
1659        scc_var = (int*)((char*)next_scc_var + ZEND_MM_ALIGNED_SIZE(sizeof(int) * ssa->vars_count));
1660
1661        LOG_SSA_RANGE("Range Inference\n");
1662
1663        /* Create linked lists of SSA variables for each SCC */
1664        memset(scc_var, -1, sizeof(int) * ssa->sccs);
1665        for (j = 0; j < ssa->vars_count; j++) {
1666                if (ssa->vars[j].scc >= 0) {
1667                        next_scc_var[j] = scc_var[ssa->vars[j].scc];
1668                        scc_var[ssa->vars[j].scc] = j;
1669                }
1670        }
1671
1672        for (scc = 0; scc < ssa->sccs; scc++) {
1673                j = scc_var[scc];
1674                if (next_scc_var[j] < 0) {
1675                        /* SCC with a single element */
1676                        if (zend_inference_calc_range(op_array, ssa, j, 0, 1, &tmp)) {
1677                                zend_inference_init_range(op_array, ssa, j, tmp.underflow, tmp.min, tmp.max, tmp.overflow);
1678                        } else {
1679                                zend_inference_init_range(op_array, ssa, j, 1, ZEND_LONG_MIN, ZEND_LONG_MAX, 1);
1680                        }
1681                } else {
1682                        /* Find SCC entry points */
1683                        memset(worklist, 0, sizeof(zend_ulong) * worklist_len);
1684                        do {
1685                                if (ssa->vars[j].scc_entry) {
1686                                        zend_bitset_incl(worklist, j);
1687                                }
1688                                j = next_scc_var[j];
1689                        } while (j >= 0);
1690
1691#if RANGE_WARMUP_PASSES > 0
1692                        zend_infer_ranges_warmup(op_array, ssa, scc_var, next_scc_var, scc);
1693                        j = scc_var[scc];
1694                        do {
1695                                zend_bitset_incl(worklist, j);
1696                                j = next_scc_var[j];
1697                        } while (j >= 0);
1698#endif
1699
1700                        /* widening */
1701                        WHILE_WORKLIST(worklist, worklist_len, j) {
1702                                if (zend_ssa_range_widening(op_array, ssa, j, scc)) {
1703                                        FOR_EACH_VAR_USAGE(j, ADD_SCC_VAR);
1704                                }
1705                        } WHILE_WORKLIST_END();
1706
1707                        /* Add all SCC entry variables into worklist for narrowing */
1708                        for (j = scc_var[scc]; j >= 0; j = next_scc_var[j]) {
1709                                if (!ssa->var_info[j].has_range) {
1710                                        zend_inference_init_range(op_array, ssa, j, 1, ZEND_LONG_MIN, ZEND_LONG_MAX, 1);
1711                                }
1712                                zend_bitset_incl(worklist, j);
1713                        }
1714
1715                        /* narrowing */
1716                        WHILE_WORKLIST(worklist, worklist_len, j) {
1717                                if (zend_ssa_range_narrowing(op_array, ssa, j, scc)) {
1718                                        FOR_EACH_VAR_USAGE(j, ADD_SCC_VAR);
1719#ifdef SYM_RANGE
1720                                        /* Process symbolic control-flow constraints */
1721                                        p = ssa->vars[j].sym_use_chain;
1722                                        while (p) {
1723                                                ADD_SCC_VAR(p->ssa_var);
1724                                                p = p->sym_use_chain;
1725                                        }
1726#endif
1727                                }
1728                        } WHILE_WORKLIST_END();
1729                }
1730        }
1731
1732        free_alloca(worklist, use_heap);
1733
1734        return SUCCESS;
1735}
1736/* }}} */
1737
1738#define UPDATE_SSA_TYPE(_type, _var)                                                                    \
1739        do {                                                                                                                            \
1740                uint32_t __type = (_type);                                                                              \
1741                int __var = (_var);                                                                                             \
1742                if (__type & MAY_BE_REF) {                                                                              \
1743                        __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; \
1744                }                                                                                                                               \
1745                if (__var >= 0) {                                                                                               \
1746                        if (ssa_vars[__var].var < op_array->last_var) {                         \
1747                                if (__type & (MAY_BE_REF|MAY_BE_RCN)) {                                 \
1748                                        __type |= MAY_BE_RC1 | MAY_BE_RCN;                                      \
1749                                }                                                                                                               \
1750                                if ((__type & MAY_BE_RC1) && (__type & MAY_BE_STRING)) {\
1751                                        /* TODO: support for array keys and ($str . "")*/   \
1752                                        __type |= MAY_BE_RCN;                               \
1753                                }                                                       \
1754                        }                                                                                                                       \
1755                        if (ssa_var_info[__var].type != __type) {                                       \
1756                                check_type_narrowing(op_array, ssa, worklist,                   \
1757                                        __var, ssa_var_info[__var].type, __type);                       \
1758                                ssa_var_info[__var].type = __type;                                              \
1759                                add_usages(op_array, ssa, worklist, __var);                             \
1760                        }                                                                                                                       \
1761                        /*zend_bitset_excl(worklist, var);*/                                            \
1762                }                                                                                                                               \
1763        } while (0)
1764
1765#define UPDATE_SSA_OBJ_TYPE(_ce, _is_instanceof, var)                               \
1766        do {                                                                \
1767                if (var >= 0) {                                                                                                 \
1768                        if (ssa_var_info[var].ce != (_ce) ||                        \
1769                            ssa_var_info[var].is_instanceof != (_is_instanceof)) {  \
1770                                ssa_var_info[var].ce = (_ce);                                               \
1771                                ssa_var_info[var].is_instanceof = (_is_instanceof);     \
1772                                add_usages(op_array, ssa, worklist, var);                               \
1773                        }                                                                                                                       \
1774                        /*zend_bitset_excl(worklist, var);*/                                            \
1775                }                                                                                                                               \
1776        } while (0)
1777
1778#define COPY_SSA_OBJ_TYPE(from_var, to_var) do { \
1779        if ((from_var) >= 0 && (ssa_var_info[(from_var)].type & MAY_BE_OBJECT) \
1780                        && ssa_var_info[(from_var)].ce) { \
1781                UPDATE_SSA_OBJ_TYPE(ssa_var_info[(from_var)].ce, \
1782                        ssa_var_info[(from_var)].is_instanceof, (to_var)); \
1783        } else { \
1784                UPDATE_SSA_OBJ_TYPE(NULL, 0, (to_var)); \
1785        } \
1786} while (0)
1787
1788static void add_usages(const zend_op_array *op_array, zend_ssa *ssa, zend_bitset worklist, int var)
1789{
1790        if (ssa->vars[var].phi_use_chain) {
1791                zend_ssa_phi *p = ssa->vars[var].phi_use_chain;
1792                do {
1793                        zend_bitset_incl(worklist, p->ssa_var);
1794                        p = zend_ssa_next_use_phi(ssa, var, p);
1795                } while (p);
1796        }
1797        if (ssa->vars[var].use_chain >= 0) {
1798                int use = ssa->vars[var].use_chain;
1799                zend_ssa_op *op;
1800
1801                do {
1802                        op = ssa->ops + use;
1803                        if (op->result_def >= 0) {
1804                                zend_bitset_incl(worklist, op->result_def);
1805                        }
1806                        if (op->op1_def >= 0) {
1807                                zend_bitset_incl(worklist, op->op1_def);
1808                        }
1809                        if (op->op2_def >= 0) {
1810                                zend_bitset_incl(worklist, op->op2_def);
1811                        }
1812                        if (op_array->opcodes[use].opcode == ZEND_OP_DATA) {
1813                                op--;
1814                                if (op->result_def >= 0) {
1815                                        zend_bitset_incl(worklist, op->result_def);
1816                                }
1817                                if (op->op1_def >= 0) {
1818                                        zend_bitset_incl(worklist, op->op1_def);
1819                                }
1820                                if (op->op2_def >= 0) {
1821                                        zend_bitset_incl(worklist, op->op2_def);
1822                                }
1823                        }
1824                        use = zend_ssa_next_use(ssa->ops, var, use);
1825                } while (use >= 0);
1826        }
1827}
1828
1829static void reset_dependent_vars(const zend_op_array *op_array, zend_ssa *ssa, zend_bitset worklist, int var)
1830{
1831        zend_ssa_op *ssa_ops = ssa->ops;
1832        zend_ssa_var *ssa_vars = ssa->vars;
1833        zend_ssa_var_info *ssa_var_info = ssa->var_info;
1834        zend_ssa_phi *p;
1835        int use;
1836
1837        p = ssa_vars[var].phi_use_chain;
1838        while (p) {
1839                if (ssa_var_info[p->ssa_var].type) {
1840                        ssa_var_info[p->ssa_var].type = 0;
1841                        zend_bitset_incl(worklist, p->ssa_var);
1842                        reset_dependent_vars(op_array, ssa, worklist, p->ssa_var);
1843                }
1844                p = zend_ssa_next_use_phi(ssa, var, p);
1845        }
1846        use = ssa_vars[var].use_chain;
1847        while (use >= 0) {
1848                if (ssa_ops[use].op1_def >= 0 && ssa_var_info[ssa_ops[use].op1_def].type) {
1849                        ssa_var_info[ssa_ops[use].op1_def].type = 0;
1850                        zend_bitset_incl(worklist, ssa_ops[use].op1_def);
1851                        reset_dependent_vars(op_array, ssa, worklist, ssa_ops[use].op1_def);
1852                }
1853                if (ssa_ops[use].op2_def >= 0 && ssa_var_info[ssa_ops[use].op2_def].type) {
1854                        ssa_var_info[ssa_ops[use].op2_def].type = 0;
1855                        zend_bitset_incl(worklist, ssa_ops[use].op2_def);
1856                        reset_dependent_vars(op_array, ssa, worklist, ssa_ops[use].op2_def);
1857                }
1858                if (ssa_ops[use].result_def >= 0 && ssa_var_info[ssa_ops[use].result_def].type) {
1859                        ssa_var_info[ssa_ops[use].result_def].type = 0;
1860                        zend_bitset_incl(worklist, ssa_ops[use].result_def);
1861                        reset_dependent_vars(op_array, ssa, worklist, ssa_ops[use].result_def);
1862                }
1863                if (op_array->opcodes[use+1].opcode == ZEND_OP_DATA) {
1864                        if (ssa_ops[use+1].op1_def >= 0 && ssa_var_info[ssa_ops[use+1].op1_def].type) {
1865                                ssa_var_info[ssa_ops[use+1].op1_def].type = 0;
1866                                zend_bitset_incl(worklist, ssa_ops[use+1].op1_def);
1867                                reset_dependent_vars(op_array, ssa, worklist, ssa_ops[use+1].op1_def);
1868                        }
1869                        if (ssa_ops[use+1].op2_def >= 0 && ssa_var_info[ssa_ops[use+1].op2_def].type) {
1870                                ssa_var_info[ssa_ops[use+1].op2_def].type = 0;
1871                                zend_bitset_incl(worklist, ssa_ops[use+1].op2_def);
1872                                reset_dependent_vars(op_array, ssa, worklist, ssa_ops[use+1].op2_def);
1873                        }
1874                        if (ssa_ops[use+1].result_def >= 0 && ssa_var_info[ssa_ops[use+1].result_def].type) {
1875                                ssa_var_info[ssa_ops[use+1].result_def].type = 0;
1876                                zend_bitset_incl(worklist, ssa_ops[use+1].result_def);
1877                                reset_dependent_vars(op_array, ssa, worklist, ssa_ops[use+1].result_def);
1878                        }
1879                }
1880                use = zend_ssa_next_use(ssa_ops, var, use);
1881        }
1882#ifdef SYM_RANGE
1883        /* Process symbolic control-flow constraints */
1884        p = ssa->vars[var].sym_use_chain;
1885        while (p) {
1886                ssa_var_info[p->ssa_var].type = 0;
1887                zend_bitset_incl(worklist, p->ssa_var);
1888                reset_dependent_vars(op_array, ssa, worklist, p->ssa_var);
1889                p = p->sym_use_chain;
1890        }
1891#endif
1892}
1893
1894static void check_type_narrowing(const zend_op_array *op_array, zend_ssa *ssa, zend_bitset worklist, int var, uint32_t old_type, uint32_t new_type)
1895{
1896        /* if new_type set resets some bits from old_type set
1897         * We have completely recalculate types of some dependent SSA variables
1898         * (this may occurs mainly because of incremental inter-precudure
1899         * type inference)
1900         */
1901        if (old_type & ~new_type) {
1902                ZEND_ASSERT(0); /* Currently this should never happen */
1903                reset_dependent_vars(op_array, ssa, worklist, var);
1904        }
1905}
1906
1907uint32_t zend_array_element_type(uint32_t t1, int write, int insert)
1908{
1909        uint32_t tmp = 0;
1910
1911        if (t1 & MAY_BE_OBJECT) {
1912                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;
1913        }
1914        if (t1 & MAY_BE_ARRAY) {
1915                if (insert) {
1916                        tmp |= MAY_BE_NULL;
1917                } else {
1918                        tmp |= MAY_BE_NULL | ((t1 & MAY_BE_ARRAY_OF_ANY) >> MAY_BE_ARRAY_SHIFT);
1919                        if (tmp & MAY_BE_ARRAY) {
1920                                tmp |= MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
1921                        }
1922                        if (t1 & MAY_BE_ARRAY_OF_REF) {
1923                                tmp |= MAY_BE_REF | MAY_BE_RC1 | MAY_BE_RCN;
1924                        } else if (tmp & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)) {
1925                                tmp |= MAY_BE_RC1 | MAY_BE_RCN;
1926                        }
1927                }
1928        }
1929        if (t1 & MAY_BE_STRING) {
1930                tmp |= MAY_BE_STRING | MAY_BE_RC1;
1931                if (write) {
1932                        tmp |= MAY_BE_NULL;
1933                }
1934        }
1935        if (t1 & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE)) {
1936                tmp |= MAY_BE_NULL;
1937                if (t1 & MAY_BE_ERROR) {
1938                        if (write) {
1939                                tmp |= MAY_BE_ERROR;
1940                        }
1941                }
1942        }
1943        if (t1 & (MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE|MAY_BE_RESOURCE)) {
1944                tmp |= MAY_BE_NULL;
1945                if (write) {
1946                        tmp |= MAY_BE_ERROR;
1947                }
1948        }
1949        return tmp;
1950}
1951
1952static uint32_t assign_dim_result_type(
1953                uint32_t arr_type, uint32_t dim_type, uint32_t value_type, zend_uchar dim_op_type) {
1954        uint32_t tmp = arr_type & ~(MAY_BE_RC1|MAY_BE_RCN);
1955
1956        if (arr_type & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE)) {
1957                tmp &= ~(MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE);
1958                tmp |= MAY_BE_ARRAY|MAY_BE_RC1;
1959        }
1960        if (tmp & (MAY_BE_ARRAY|MAY_BE_STRING)) {
1961                tmp |= MAY_BE_RC1;
1962        }
1963        if (tmp & (MAY_BE_OBJECT|MAY_BE_RESOURCE)) {
1964                tmp |= MAY_BE_RC1 | MAY_BE_RCN;
1965        }
1966        if (tmp & MAY_BE_ARRAY) {
1967                tmp |= (value_type & MAY_BE_ANY) << MAY_BE_ARRAY_SHIFT;
1968                if (value_type & MAY_BE_UNDEF) {
1969                        tmp |= MAY_BE_ARRAY_OF_NULL;
1970                }
1971                if (dim_op_type == IS_UNUSED) {
1972                        tmp |= MAY_BE_ARRAY_KEY_LONG;
1973                } else {
1974                        if (dim_type & (MAY_BE_LONG|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_RESOURCE|MAY_BE_DOUBLE)) {
1975                                tmp |= MAY_BE_ARRAY_KEY_LONG;
1976                        }
1977                        if (dim_type & MAY_BE_STRING) {
1978                                tmp |= MAY_BE_ARRAY_KEY_STRING;
1979                                if (dim_op_type != IS_CONST) {
1980                                        // FIXME: numeric string
1981                                        tmp |= MAY_BE_ARRAY_KEY_LONG;
1982                                }
1983                        }
1984                        if (dim_type & (MAY_BE_UNDEF|MAY_BE_NULL)) {
1985                                tmp |= MAY_BE_ARRAY_KEY_STRING;
1986                        }
1987                }
1988        }
1989        return tmp;
1990}
1991
1992/* For binary ops that have compound assignment operators */
1993static uint32_t binary_op_result_type(
1994                zend_ssa *ssa, zend_uchar opcode, uint32_t t1, uint32_t t2, uint32_t result_var) {
1995        uint32_t tmp = 0;
1996        uint32_t t1_type = (t1 & MAY_BE_ANY) | (t1 & MAY_BE_UNDEF ? MAY_BE_NULL : 0);
1997        uint32_t t2_type = (t2 & MAY_BE_ANY) | (t2 & MAY_BE_UNDEF ? MAY_BE_NULL : 0);
1998        switch (opcode) {
1999                case ZEND_ADD:
2000                        if (t1_type == MAY_BE_LONG && t2_type == MAY_BE_LONG) {
2001                                if (!ssa->var_info[result_var].has_range ||
2002                                    ssa->var_info[result_var].range.underflow ||
2003                                    ssa->var_info[result_var].range.overflow) {
2004                                        /* may overflow */
2005                                        tmp |= MAY_BE_LONG | MAY_BE_DOUBLE;
2006                                } else {
2007                                        tmp |= MAY_BE_LONG;
2008                                }
2009                        } else if (t1_type == MAY_BE_DOUBLE || t2_type == MAY_BE_DOUBLE) {
2010                                tmp |= MAY_BE_DOUBLE;
2011                        } else if (t1_type == MAY_BE_ARRAY && t2_type == MAY_BE_ARRAY) {
2012                                tmp |= MAY_BE_ARRAY | MAY_BE_RC1;
2013                                tmp |= t1 & (MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF);
2014                                tmp |= t2 & (MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF);
2015                        } else {
2016                                tmp |= MAY_BE_LONG | MAY_BE_DOUBLE;
2017                                if ((t1_type & MAY_BE_ARRAY) && (t2_type & MAY_BE_ARRAY)) {
2018                                        tmp |= MAY_BE_ARRAY | MAY_BE_RC1;
2019                                        tmp |= t1 & (MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF);
2020                                        tmp |= t2 & (MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF);
2021                                }
2022                        }
2023                        break;
2024                case ZEND_SUB:
2025                case ZEND_MUL:
2026                        if (t1_type == MAY_BE_LONG && t2_type == MAY_BE_LONG) {
2027                                if (!ssa->var_info[result_var].has_range ||
2028                                    ssa->var_info[result_var].range.underflow ||
2029                                    ssa->var_info[result_var].range.overflow) {
2030                                        /* may overflow */
2031                                        tmp |= MAY_BE_LONG | MAY_BE_DOUBLE;
2032                                } else {
2033                                        tmp |= MAY_BE_LONG;
2034                                }
2035                        } else if (t1_type == MAY_BE_DOUBLE || t2_type == MAY_BE_DOUBLE) {
2036                                tmp |= MAY_BE_DOUBLE;
2037                        } else {
2038                                tmp |= MAY_BE_LONG | MAY_BE_DOUBLE;
2039                        }
2040                        break;
2041                case ZEND_DIV:
2042                case ZEND_POW:
2043                        if (t1_type == MAY_BE_DOUBLE || t2_type == MAY_BE_DOUBLE) {
2044                                tmp |= MAY_BE_DOUBLE;
2045                        } else {
2046                                tmp |= MAY_BE_LONG | MAY_BE_DOUBLE;
2047                        }
2048                        /* Division by zero results in Inf/-Inf/Nan (double), so it doesn't need any special
2049                         * handling */
2050                        break;
2051                case ZEND_MOD:
2052                        tmp = MAY_BE_LONG;
2053                        /* Division by zero results in an exception, so it doesn't need any special handling */
2054                        break;
2055                case ZEND_BW_OR:
2056                case ZEND_BW_AND:
2057                case ZEND_BW_XOR:
2058                        if ((t1_type & MAY_BE_STRING) && (t2_type & MAY_BE_STRING)) {
2059                                tmp |= MAY_BE_STRING | MAY_BE_RC1;
2060                        }
2061                        if ((t1_type & ~MAY_BE_STRING) || (t2_type & ~MAY_BE_STRING)) {
2062                                tmp |= MAY_BE_LONG;
2063                        }
2064                        break;
2065                case ZEND_SL:
2066                case ZEND_SR:
2067                        tmp = MAY_BE_LONG;
2068                        break;
2069                case ZEND_CONCAT:
2070                case ZEND_FAST_CONCAT:
2071                        /* TODO: +MAY_BE_OBJECT ??? */
2072                        tmp = MAY_BE_STRING | MAY_BE_RC1 | MAY_BE_RCN;
2073                        break;
2074                EMPTY_SWITCH_DEFAULT_CASE()
2075        }
2076        return tmp;
2077}
2078
2079static inline zend_class_entry *get_class_entry(const zend_script *script, zend_string *lcname) {
2080        zend_class_entry *ce = script ? zend_hash_find_ptr(&script->class_table, lcname) : NULL;
2081        if (ce) {
2082                return ce;
2083        }
2084
2085        ce = zend_hash_find_ptr(CG(class_table), lcname);
2086        if (ce && ce->type == ZEND_INTERNAL_CLASS) {
2087                return ce;
2088        }
2089
2090        return NULL;
2091}
2092
2093static uint32_t zend_fetch_arg_info(const zend_script *script, zend_arg_info *arg_info, zend_class_entry **pce)
2094{
2095        uint32_t tmp = 0;
2096
2097        *pce = NULL;
2098        if (arg_info->class_name) {
2099                // class type hinting...
2100                zend_string *lcname = zend_string_tolower(arg_info->class_name);
2101                tmp |= MAY_BE_OBJECT;
2102                *pce = get_class_entry(script, lcname);
2103                zend_string_release(lcname);
2104        } else if (arg_info->type_hint != IS_UNDEF) {
2105                if (arg_info->type_hint == IS_VOID) {
2106                        tmp |= MAY_BE_NULL;
2107                } else if (arg_info->type_hint == IS_CALLABLE) {
2108                        tmp |= MAY_BE_STRING|MAY_BE_OBJECT|MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF;
2109                } else if (arg_info->type_hint == IS_ITERABLE) {
2110                        tmp |= MAY_BE_OBJECT|MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF;
2111                } else if (arg_info->type_hint == IS_ARRAY) {
2112                        tmp |= MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF;
2113                } else if (arg_info->type_hint == _IS_BOOL) {
2114                        tmp |= MAY_BE_TRUE|MAY_BE_FALSE;
2115                } else {
2116                        ZEND_ASSERT(arg_info->type_hint < IS_REFERENCE);
2117                        tmp |= 1 << arg_info->type_hint;
2118                }
2119        } else {
2120                tmp |= MAY_BE_ANY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF;
2121        }
2122        if (arg_info->allow_null) {
2123                tmp |= MAY_BE_NULL;
2124        }
2125        return tmp;
2126}
2127
2128static void zend_update_type_info(const zend_op_array *op_array,
2129                                  zend_ssa            *ssa,
2130                                  const zend_script   *script,
2131                                  zend_bitset          worklist,
2132                                  int                  i)
2133{
2134        uint32_t t1, t2;
2135        uint32_t tmp, orig;
2136        zend_op *opline = op_array->opcodes + i;
2137        zend_ssa_op *ssa_ops = ssa->ops;
2138        zend_ssa_var *ssa_vars = ssa->vars;
2139        zend_ssa_var_info *ssa_var_info = ssa->var_info;
2140        zend_class_entry *ce;
2141        int j;
2142
2143        if (opline->opcode == ZEND_OP_DATA) {
2144                opline--;
2145                i--;
2146        }
2147
2148        t1 = OP1_INFO();
2149        t2 = OP2_INFO();
2150
2151        switch (opline->opcode) {
2152                case ZEND_ADD:
2153                case ZEND_SUB:
2154                case ZEND_MUL:
2155                case ZEND_DIV:
2156                case ZEND_POW:
2157                case ZEND_MOD:
2158                case ZEND_BW_OR:
2159                case ZEND_BW_AND:
2160                case ZEND_BW_XOR:
2161                case ZEND_SL:
2162                case ZEND_SR:
2163                case ZEND_CONCAT:
2164                        tmp = binary_op_result_type(ssa, opline->opcode, t1, t2, ssa_ops[i].result_def);
2165                        UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
2166                        break;
2167                case ZEND_BW_NOT:
2168                        tmp = 0;
2169                        if (t1 & MAY_BE_STRING) {
2170                                tmp |= MAY_BE_STRING | MAY_BE_RC1;
2171                        }
2172                        if (t1 & (MAY_BE_ANY-MAY_BE_STRING)) {
2173                                tmp |= MAY_BE_LONG;
2174                        }
2175                        UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
2176                        break;
2177                case ZEND_BEGIN_SILENCE:
2178                        UPDATE_SSA_TYPE(MAY_BE_LONG, ssa_ops[i].result_def);
2179                        break;
2180                case ZEND_BOOL_NOT:
2181                case ZEND_BOOL_XOR:
2182                case ZEND_IS_IDENTICAL:
2183                case ZEND_IS_NOT_IDENTICAL:
2184                case ZEND_IS_EQUAL:
2185                case ZEND_IS_NOT_EQUAL:
2186                case ZEND_IS_SMALLER:
2187                case ZEND_IS_SMALLER_OR_EQUAL:
2188                case ZEND_INSTANCEOF:
2189                case ZEND_JMPZ_EX:
2190                case ZEND_JMPNZ_EX:
2191                case ZEND_CASE:
2192                case ZEND_BOOL:
2193                case ZEND_ISSET_ISEMPTY_VAR:
2194                case ZEND_ISSET_ISEMPTY_DIM_OBJ:
2195                case ZEND_ISSET_ISEMPTY_PROP_OBJ:
2196                case ZEND_ISSET_ISEMPTY_STATIC_PROP:
2197                case ZEND_ASSERT_CHECK:
2198                        UPDATE_SSA_TYPE(MAY_BE_FALSE|MAY_BE_TRUE, ssa_ops[i].result_def);
2199                        break;
2200                case ZEND_CAST:
2201                        if (ssa_ops[i].op1_def >= 0) {
2202                                tmp = t1;
2203                                if ((t1 & (MAY_BE_ARRAY|MAY_BE_OBJECT)) &&
2204                                    (opline->op1_type == IS_CV) &&
2205                                    (opline->extended_value == IS_ARRAY ||
2206                                     opline->extended_value == IS_OBJECT)) {
2207                                        tmp |= MAY_BE_RCN;
2208                                } else if ((t1 & MAY_BE_STRING) &&
2209                                    (opline->op1_type == IS_CV) &&
2210                                    opline->extended_value == IS_STRING) {
2211                                        tmp |= MAY_BE_RCN;
2212                                }
2213                                UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
2214                                COPY_SSA_OBJ_TYPE(ssa_ops[i].op1_use, ssa_ops[i].op1_def);
2215                        }
2216                        tmp = 0;
2217                        if (opline->extended_value == _IS_BOOL) {
2218                                tmp |= MAY_BE_TRUE|MAY_BE_FALSE;
2219                        } else {
2220                                tmp |= 1 << opline->extended_value;
2221                                if (tmp & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)) {
2222                                        if ((tmp & MAY_BE_ANY) == (t1 & MAY_BE_ANY)) {
2223                                                tmp |= (t1 & MAY_BE_RC1) | MAY_BE_RCN;
2224                                        } else if ((opline->extended_value == IS_ARRAY ||
2225                                                    opline->extended_value == IS_OBJECT) &&
2226                                                   (t1 & (MAY_BE_ARRAY|MAY_BE_OBJECT))) {
2227                                                        tmp |= MAY_BE_RC1 | MAY_BE_RCN;
2228                                        } else if (opline->extended_value == IS_STRING &&
2229                                                   (t1 & (MAY_BE_STRING|MAY_BE_OBJECT))) {
2230                                                tmp |= MAY_BE_RC1 | MAY_BE_RCN;
2231                                        } else {
2232                                                tmp |= MAY_BE_RC1;
2233                                        }
2234                                }
2235                        }
2236                        if (opline->extended_value == IS_ARRAY) {
2237                                if (t1 & MAY_BE_ARRAY) {
2238                                        tmp |= t1 & (MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF);
2239                                }
2240                                if (t1 & MAY_BE_OBJECT) {
2241                                        tmp |= MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
2242                                } else {
2243                                        tmp |= ((t1 & MAY_BE_ANY) << MAY_BE_ARRAY_SHIFT) | MAY_BE_ARRAY_KEY_LONG;
2244                                }
2245                        }
2246                        UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
2247                        break;
2248                case ZEND_QM_ASSIGN:
2249                case ZEND_JMP_SET:
2250                case ZEND_COALESCE:
2251                        if (ssa_ops[i].op1_def >= 0) {
2252                                tmp = t1;
2253                                if ((t1 & (MAY_BE_RC1|MAY_BE_REF)) && (opline->op1_type == IS_CV)) {
2254                                        tmp |= MAY_BE_RCN;
2255                                }
2256                                UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
2257                                COPY_SSA_OBJ_TYPE(ssa_ops[i].op1_use, ssa_ops[i].op1_def);
2258                        }
2259                        tmp = t1 & ~(MAY_BE_UNDEF|MAY_BE_REF);
2260                        if (t1 & MAY_BE_UNDEF) {
2261                                tmp |= MAY_BE_NULL;
2262                        }
2263                        if (t1 & (MAY_BE_RC1|MAY_BE_RCN)) {
2264                                tmp |= (t1 & (MAY_BE_RC1|MAY_BE_RCN));
2265                                if (opline->op1_type == IS_CV) {
2266                                        tmp |= MAY_BE_RCN;
2267                                }
2268                        }
2269                        if (opline->opcode != ZEND_QM_ASSIGN) {
2270                                /* COALESCE and JMP_SET result can't be null */
2271                                tmp &= ~MAY_BE_NULL;
2272                                if (opline->opcode == ZEND_JMP_SET) {
2273                                        /* JMP_SET result can't be false either */
2274                                        tmp &= ~MAY_BE_FALSE;
2275                                }
2276                        }
2277                        UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
2278                        COPY_SSA_OBJ_TYPE(ssa_ops[i].op1_use, ssa_ops[i].result_def);
2279                        break;
2280                case ZEND_ASSIGN_ADD:
2281                case ZEND_ASSIGN_SUB:
2282                case ZEND_ASSIGN_MUL:
2283                case ZEND_ASSIGN_DIV:
2284                case ZEND_ASSIGN_POW:
2285                case ZEND_ASSIGN_MOD:
2286                case ZEND_ASSIGN_SL:
2287                case ZEND_ASSIGN_SR:
2288                case ZEND_ASSIGN_BW_OR:
2289                case ZEND_ASSIGN_BW_AND:
2290                case ZEND_ASSIGN_BW_XOR:
2291                case ZEND_ASSIGN_CONCAT:
2292                        orig = 0;
2293                        tmp = 0;
2294                        if (opline->extended_value == ZEND_ASSIGN_OBJ) {
2295                        tmp |= MAY_BE_REF;
2296                                orig = t1;
2297                                t1 = MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
2298                                t2 = OP1_DATA_INFO();
2299                        } else if (opline->extended_value == ZEND_ASSIGN_DIM) {
2300                                if (t1 & MAY_BE_ARRAY_OF_REF) {
2301                                tmp |= MAY_BE_REF;
2302                                }
2303                                orig = t1;
2304                                t1 = zend_array_element_type(t1, 1, 0);
2305                                t2 = OP1_DATA_INFO();
2306                        } else {
2307                                if (t1 & MAY_BE_REF) {
2308                                tmp |= MAY_BE_REF;
2309                                }
2310                        }
2311
2312                        tmp |= binary_op_result_type(
2313                                ssa, get_compound_assign_op(opline->opcode), t1, t2, ssa_ops[i].op1_def);
2314                        if (tmp & (MAY_BE_STRING|MAY_BE_ARRAY)) {
2315                                tmp |= MAY_BE_RC1;
2316                        }
2317                        if (tmp & (MAY_BE_OBJECT|MAY_BE_RESOURCE)) {
2318                                tmp |= MAY_BE_RC1 | MAY_BE_RCN;
2319                        }
2320
2321                        if (opline->extended_value == ZEND_ASSIGN_DIM) {
2322                                if (opline->op1_type == IS_CV) {
2323                                        orig = assign_dim_result_type(orig, OP2_INFO(), tmp, opline->op1_type);
2324                                        UPDATE_SSA_TYPE(orig, ssa_ops[i].op1_def);
2325                                        COPY_SSA_OBJ_TYPE(ssa_ops[i].op1_use, ssa_ops[i].op1_def);
2326                                }
2327                        } else if (opline->extended_value == ZEND_ASSIGN_OBJ) {
2328                                if (opline->op1_type == IS_CV) {
2329                                        if (orig & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE)) {
2330                                                orig &= (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE);
2331                                                orig |= MAY_BE_OBJECT | MAY_BE_RC1 | MAY_BE_RCN;
2332                                        }
2333                                        if (orig & MAY_BE_OBJECT) {
2334                                                orig |= (MAY_BE_RC1|MAY_BE_RCN);
2335                                        }
2336                                        UPDATE_SSA_TYPE(orig, ssa_ops[i].op1_def);
2337                                        COPY_SSA_OBJ_TYPE(ssa_ops[i].op1_use, ssa_ops[i].op1_def);
2338                                }
2339                        } else {
2340                                UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
2341                        }
2342                        if (ssa_ops[i].result_def >= 0) {
2343                                if (opline->extended_value == ZEND_ASSIGN_DIM) {
2344                                        if (opline->op2_type == IS_UNUSED) {
2345                                                /* When appending to an array and the LONG_MAX key is already used
2346                                                 * null will be returned. */
2347                                                tmp |= MAY_BE_NULL;
2348                                        }
2349                                        if (t2 & (MAY_BE_ARRAY | MAY_BE_OBJECT)) {
2350                                                /* Arrays and objects cannot be used as keys. */
2351                                                tmp |= MAY_BE_NULL;
2352                                        }
2353                                        if (t1 & (MAY_BE_ANY - (MAY_BE_NULL | MAY_BE_FALSE | MAY_BE_STRING | MAY_BE_ARRAY))) {
2354                                                /* null and false are implicitly converted to array, anything else
2355                                                 * results in a null return value. */
2356                                                tmp |= MAY_BE_NULL;
2357                                        }
2358                                } else if (opline->extended_value == ZEND_ASSIGN_OBJ) {
2359                                        if (orig & (MAY_BE_ANY - (MAY_BE_NULL | MAY_BE_FALSE | MAY_BE_OBJECT))) {
2360                                                /* null and false (and empty string) are implicitly converted to object,
2361                                                 * anything else results in a null return value. */
2362                                                tmp |= MAY_BE_NULL;
2363                                        }
2364                                }
2365                                UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
2366                        }
2367                        break;
2368                case ZEND_PRE_INC:
2369                case ZEND_PRE_DEC:
2370                        tmp = 0;
2371                        if (t1 & MAY_BE_REF) {
2372                                tmp |= MAY_BE_REF;
2373                        }
2374                        if (t1 & (MAY_BE_RC1|MAY_BE_RCN)) {
2375                                tmp |= MAY_BE_RC1;
2376                                if (ssa_ops[i].result_def >= 0) {
2377                                        tmp |= MAY_BE_RCN;
2378                                }
2379                        }
2380                        if ((t1 & MAY_BE_ANY) == MAY_BE_LONG) {
2381                                if (!ssa_var_info[ssa_ops[i].op1_use].has_range ||
2382                                    (opline->opcode == ZEND_PRE_DEC &&
2383                                     (ssa_var_info[ssa_ops[i].op1_use].range.underflow ||
2384                                      ssa_var_info[ssa_ops[i].op1_use].range.min == ZEND_LONG_MIN)) ||
2385                                     (opline->opcode == ZEND_PRE_INC &&
2386                                      (ssa_var_info[ssa_ops[i].op1_use].range.overflow ||
2387                                       ssa_var_info[ssa_ops[i].op1_use].range.max == ZEND_LONG_MAX))) {
2388                                        /* may overflow */
2389                                        tmp |= MAY_BE_LONG | MAY_BE_DOUBLE;
2390                                } else {
2391                                        tmp |= MAY_BE_LONG;
2392                                }
2393                        } else {
2394                                if (t1 & MAY_BE_ERROR) {
2395                                        tmp |= MAY_BE_NULL;
2396                                }
2397                                if (t1 & (MAY_BE_UNDEF | MAY_BE_NULL)) {
2398                                        if (opline->opcode == ZEND_PRE_INC) {
2399                                                tmp |= MAY_BE_LONG;
2400                                        } else {
2401                                                tmp |= MAY_BE_NULL;
2402                                        }
2403                                }
2404                                if (t1 & MAY_BE_LONG) {
2405                                        tmp |= MAY_BE_LONG | MAY_BE_DOUBLE;
2406                                }
2407                                if (t1 & MAY_BE_DOUBLE) {
2408                                        tmp |= MAY_BE_DOUBLE;
2409                                }
2410                                if (t1 & MAY_BE_STRING) {
2411                                        tmp |= MAY_BE_STRING | MAY_BE_LONG | MAY_BE_DOUBLE;
2412                                }
2413                                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);
2414                        }
2415                        if (ssa_ops[i].op1_def >= 0) {
2416                                UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
2417                        }
2418                        if (ssa_ops[i].result_def >= 0) {
2419                                UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
2420                        }
2421                        break;
2422                case ZEND_POST_INC:
2423                case ZEND_POST_DEC:
2424                        if (ssa_ops[i].result_def >= 0) {
2425                                tmp = 0;
2426                                if (t1 & (MAY_BE_RC1|MAY_BE_RCN)) {
2427                                        tmp |= MAY_BE_RC1|MAY_BE_RCN;
2428                                }
2429                                tmp |= t1 & ~(MAY_BE_UNDEF|MAY_BE_ERROR|MAY_BE_REF|MAY_BE_RCN);
2430                                if (t1 & MAY_BE_UNDEF) {
2431                                        tmp |= MAY_BE_NULL;
2432                                }
2433                                UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
2434                        }
2435                        tmp = 0;
2436                        if (t1 & MAY_BE_REF) {
2437                                tmp |= MAY_BE_REF;
2438                        }
2439                        if (t1 & (MAY_BE_RC1|MAY_BE_RCN)) {
2440                                tmp |= MAY_BE_RC1;
2441                        }
2442                        if ((t1 & MAY_BE_ANY) == MAY_BE_LONG) {
2443                                if (!ssa_var_info[ssa_ops[i].op1_use].has_range ||
2444                                     (opline->opcode == ZEND_PRE_DEC &&
2445                                      (ssa_var_info[ssa_ops[i].op1_use].range.underflow ||
2446                                       ssa_var_info[ssa_ops[i].op1_use].range.min == ZEND_LONG_MIN)) ||
2447                                      (opline->opcode == ZEND_PRE_INC &&
2448                                       (ssa_var_info[ssa_ops[i].op1_use].range.overflow ||
2449                                        ssa_var_info[ssa_ops[i].op1_use].range.max == ZEND_LONG_MAX))) {
2450                                        /* may overflow */
2451                                        tmp |= MAY_BE_LONG | MAY_BE_DOUBLE;
2452                                } else {
2453                                        tmp |= MAY_BE_LONG;
2454                                }
2455                        } else {
2456                                if (t1 & MAY_BE_ERROR) {
2457                                        tmp |= MAY_BE_NULL;
2458                                }
2459                                if (t1 & (MAY_BE_UNDEF | MAY_BE_NULL)) {
2460                                        if (opline->opcode == ZEND_POST_INC) {
2461                                                tmp |= MAY_BE_LONG;
2462                                        } else {
2463                                                tmp |= MAY_BE_NULL;
2464                                        }
2465                                }
2466                                if (t1 & MAY_BE_LONG) {
2467                                        tmp |= MAY_BE_LONG | MAY_BE_DOUBLE;
2468                                }
2469                                if (t1 & MAY_BE_DOUBLE) {
2470                                        tmp |= MAY_BE_DOUBLE;
2471                                }
2472                                if (t1 & MAY_BE_STRING) {
2473                                        tmp |= MAY_BE_STRING | MAY_BE_LONG | MAY_BE_DOUBLE;
2474                                }
2475                                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);
2476                        }
2477                        if (ssa_ops[i].op1_def >= 0) {
2478                                UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
2479                        }
2480                        break;
2481                case ZEND_ASSIGN_DIM:
2482                        if (opline->op1_type == IS_CV) {
2483                                tmp = assign_dim_result_type(t1, t2, OP1_DATA_INFO(), opline->op2_type);
2484                                UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
2485                                COPY_SSA_OBJ_TYPE(ssa_ops[i].op1_use, ssa_ops[i].op1_def);
2486                        }
2487                        if (ssa_ops[i].result_def >= 0) {
2488                                tmp = 0;
2489                                if (t1 & MAY_BE_STRING) {
2490                                        tmp |= MAY_BE_STRING;
2491                                }
2492                                if (t1 & ((MAY_BE_ANY|MAY_BE_UNDEF) - MAY_BE_STRING)) {
2493                                        tmp |= (OP1_DATA_INFO() & (MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF));
2494
2495                                        if (opline->op2_type == IS_UNUSED) {
2496                                                /* When appending to an array and the LONG_MAX key is already used
2497                                                 * null will be returned. */
2498                                                tmp |= MAY_BE_NULL;
2499                                        }
2500                                        if (t2 & (MAY_BE_ARRAY | MAY_BE_OBJECT)) {
2501                                                /* Arrays and objects cannot be used as keys. */
2502                                                tmp |= MAY_BE_NULL;
2503                                        }
2504                                        if (t1 & (MAY_BE_ANY - (MAY_BE_NULL | MAY_BE_FALSE | MAY_BE_STRING | MAY_BE_ARRAY))) {
2505                                                /* undef, null and false are implicitly converted to array, anything else
2506                                                 * results in a null return value. */
2507                                                tmp |= MAY_BE_NULL;
2508                                        }
2509                                }
2510                                tmp |= MAY_BE_RC1 | MAY_BE_RCN;
2511                                if (t1 & MAY_BE_OBJECT) {
2512                                        tmp |= MAY_BE_REF;
2513                                }
2514                                UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
2515                        }
2516                        if ((opline+1)->op1_type == IS_CV && ssa_ops[i+1].op1_def >= 0) {
2517                                opline++;
2518                                i++;
2519                                tmp = OP1_INFO();
2520                                if (tmp & (MAY_BE_ANY | MAY_BE_REF)) {
2521                                        if (tmp & MAY_BE_RC1) {
2522                                                tmp |= MAY_BE_RCN;
2523                                        }
2524                                }
2525                                UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
2526                        }
2527                        break;
2528                case ZEND_ASSIGN_OBJ:
2529                        if (opline->op1_type == IS_CV) {
2530                                tmp = t1;
2531                                if (t1 & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE)) {
2532                                        tmp &= ~(MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE);
2533                                        tmp |= MAY_BE_OBJECT | MAY_BE_RC1 | MAY_BE_RCN;
2534                                }
2535                                if (tmp & MAY_BE_OBJECT) {
2536                                        tmp |= MAY_BE_RC1 | MAY_BE_RCN;
2537                                }
2538                                UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
2539                                COPY_SSA_OBJ_TYPE(ssa_ops[i].op1_use, ssa_ops[i].op1_def);
2540                        }
2541                        if (ssa_ops[i].result_def >= 0) {
2542                                // TODO: ???
2543                                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;
2544                                UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
2545                        }
2546                        if ((opline+1)->op1_type == IS_CV) {
2547                                opline++;
2548                                i++;
2549                                tmp = OP1_INFO();
2550                                if (tmp & (MAY_BE_ANY | MAY_BE_REF)) {
2551                                        if (tmp & MAY_BE_RC1) {
2552                                                tmp |= MAY_BE_RCN;
2553                                        }
2554                                }
2555                                UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
2556                        }
2557                        break;
2558                case ZEND_ASSIGN:
2559                        if (opline->op2_type == IS_CV && ssa_ops[i].op2_def >= 0) {
2560                                tmp = t2;
2561                                if (tmp & (MAY_BE_ANY | MAY_BE_REF)) {
2562                                        if (tmp & MAY_BE_RC1) {
2563                                                tmp |= MAY_BE_RCN;
2564                                        }
2565                                }
2566                                UPDATE_SSA_TYPE(tmp, ssa_ops[i].op2_def);
2567                        }
2568                        tmp = t2 & ~(MAY_BE_UNDEF|MAY_BE_REF|MAY_BE_RC1|MAY_BE_RCN);
2569                        if (t2 & MAY_BE_UNDEF) {
2570                                tmp |= MAY_BE_NULL;
2571                        }
2572                        if (t1 & MAY_BE_REF) {
2573                                tmp |= MAY_BE_REF;
2574                        }
2575                        if (t2 & MAY_BE_REF) {
2576                                tmp |= MAY_BE_RC1 | MAY_BE_RCN;
2577                        } else if (opline->op2_type & (IS_TMP_VAR|IS_VAR)) {
2578                                tmp |= t2 & (MAY_BE_RC1|MAY_BE_RCN);
2579                        } else if (t2 & (MAY_BE_RC1|MAY_BE_RCN)) {
2580                                tmp |= MAY_BE_RCN;
2581                        }
2582                        if (RETURN_VALUE_USED(opline) && (tmp & MAY_BE_RC1)) {
2583                                tmp |= MAY_BE_RCN;
2584                        }
2585                        if (ssa_ops[i].op1_def >= 0) {
2586                                if (ssa_var_info[ssa_ops[i].op1_def].use_as_double) {
2587                                        tmp &= ~MAY_BE_LONG;
2588                                        tmp |= MAY_BE_DOUBLE;
2589                                }
2590                                UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
2591                                COPY_SSA_OBJ_TYPE(ssa_ops[i].op2_use, ssa_ops[i].op1_def);
2592                        }
2593                        if (ssa_ops[i].result_def >= 0) {
2594                                UPDATE_SSA_TYPE(tmp & ~MAY_BE_REF, ssa_ops[i].result_def);
2595                                COPY_SSA_OBJ_TYPE(ssa_ops[i].op2_use, ssa_ops[i].result_def);
2596                        }
2597                        break;
2598                case ZEND_ASSIGN_REF:
2599// TODO: ???
2600                        if (opline->op2_type == IS_CV) {
2601                                tmp = (MAY_BE_REF | t2) & ~(MAY_BE_UNDEF|MAY_BE_RC1|MAY_BE_RCN);
2602                                if (t2 & MAY_BE_UNDEF) {
2603                                        tmp |= MAY_BE_NULL;
2604                                }
2605                                UPDATE_SSA_TYPE(tmp, ssa_ops[i].op2_def);
2606                        }
2607                        if (opline->op2_type == IS_VAR && opline->extended_value == ZEND_RETURNS_FUNCTION) {
2608                                tmp = (MAY_BE_REF | MAY_BE_RCN | MAY_BE_RC1 | t2) & ~MAY_BE_UNDEF;
2609                        } else {
2610                                tmp = (MAY_BE_REF | t2) & ~(MAY_BE_UNDEF|MAY_BE_ERROR|MAY_BE_RC1|MAY_BE_RCN);
2611                        }
2612                        if (t2 & MAY_BE_UNDEF) {
2613                                tmp |= MAY_BE_NULL;
2614                        }
2615                        UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
2616                        if (ssa_ops[i].result_def >= 0) {
2617                                UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
2618                        }
2619                        break;
2620                case ZEND_BIND_GLOBAL:
2621                        tmp = MAY_BE_REF | MAY_BE_ANY
2622                                | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
2623                        UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
2624                        break;
2625                case ZEND_BIND_STATIC:
2626                        tmp = MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF
2627                                | (opline->extended_value ? MAY_BE_REF : (MAY_BE_RC1 | MAY_BE_RCN));
2628                        UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
2629                        break;
2630                case ZEND_SEND_VAR:
2631                        if (ssa_ops[i].op1_def >= 0) {
2632                                tmp = t1;
2633                                if ((t1 & (MAY_BE_RC1|MAY_BE_REF)) && (opline->op1_type == IS_CV)) {
2634                                        tmp |= MAY_BE_RCN;
2635                                }
2636                                UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
2637                                COPY_SSA_OBJ_TYPE(ssa_ops[i].op1_use, ssa_ops[i].op1_def);
2638                        }
2639                        break;
2640                case ZEND_BIND_LEXICAL:
2641                        if (ssa_ops[i].op2_def >= 0) {
2642                                if (opline->extended_value) {
2643                                        tmp = t2 | MAY_BE_REF;
2644                                } else {
2645                                        tmp = t2 & ~(MAY_BE_RC1|MAY_BE_RCN);
2646                                        if (t2 & (MAY_BE_RC1|MAY_BE_RCN)) {
2647                                                tmp |= MAY_BE_RCN;
2648                                        }
2649                                }
2650                                UPDATE_SSA_TYPE(tmp, ssa_ops[i].op2_def);
2651                                COPY_SSA_OBJ_TYPE(ssa_ops[i].op2_use, ssa_ops[i].op2_def);
2652                        }
2653                        break;
2654                case ZEND_YIELD:
2655                        if (ssa_ops[i].op1_def >= 0) {
2656                                if (op_array->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
2657                                        tmp = t1 | MAY_BE_REF;
2658                                } else {
2659                                        tmp = t1 & ~(MAY_BE_RC1|MAY_BE_RCN);
2660                                        if (t1 & (MAY_BE_RC1|MAY_BE_RCN)) {
2661                                                tmp |= MAY_BE_RCN;
2662                                        }
2663                                }
2664                                UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
2665                                COPY_SSA_OBJ_TYPE(ssa_ops[i].op1_use, ssa_ops[i].op1_def);
2666                        }
2667                        if (ssa_ops[i].result_def >= 0) {
2668                                tmp = MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF
2669                                        | MAY_BE_RC1 | MAY_BE_RCN;
2670                                UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
2671                        }
2672                        break;
2673                case ZEND_SEND_VAR_EX:
2674                        if (ssa_ops[i].op1_def >= 0) {
2675                                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;
2676                                UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
2677                        }
2678                        break;
2679                case ZEND_SEND_REF:
2680                        if (ssa_ops[i].op1_def >= 0) {
2681                                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;
2682                                UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
2683                        }
2684                        break;
2685                case ZEND_SEND_UNPACK:
2686                        if (ssa_ops[i].op1_def >= 0) {
2687                                tmp = t1;
2688                                if (t1 & MAY_BE_ARRAY) {
2689                                        tmp |= MAY_BE_RC1 | MAY_BE_RCN;
2690                                        /* SEND_UNPACK may acquire references into the array */
2691                                        tmp |= MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
2692                                }
2693                                if (t1 & MAY_BE_OBJECT) {
2694                                        tmp |= MAY_BE_RC1 | MAY_BE_RCN;
2695                                }
2696                                UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
2697                        }
2698                        break;
2699                case ZEND_FAST_CONCAT:
2700                case ZEND_ROPE_INIT:
2701                case ZEND_ROPE_ADD:
2702                case ZEND_ROPE_END:
2703                        UPDATE_SSA_TYPE(MAY_BE_STRING|MAY_BE_RC1|MAY_BE_RCN, ssa_ops[i].result_def);
2704                        break;
2705                case ZEND_RECV:
2706                case ZEND_RECV_INIT:
2707                {
2708                        /* Typehinting */
2709                        zend_func_info *func_info;
2710                        zend_arg_info *arg_info = NULL;
2711                        if (op_array->arg_info && opline->op1.num <= op_array->num_args) {
2712                                arg_info = &op_array->arg_info[opline->op1.num-1];
2713                        }
2714
2715                        ce = NULL;
2716                        if (arg_info) {
2717                                tmp = zend_fetch_arg_info(script, arg_info, &ce);
2718                                if (opline->opcode == ZEND_RECV_INIT &&
2719                                           Z_CONSTANT_P(CRT_CONSTANT_EX(op_array, opline->op2, ssa->rt_constants))) {
2720                                        /* The constant may resolve to NULL */
2721                                        tmp |= MAY_BE_NULL;
2722                                }
2723                                if (arg_info->pass_by_reference) {
2724                                        tmp |= MAY_BE_REF;
2725                                } else if (tmp & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)) {
2726                                        tmp |= MAY_BE_RC1|MAY_BE_RCN;
2727                                }
2728                        } else {
2729                                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;
2730                        }
2731                        func_info = ZEND_FUNC_INFO(op_array);
2732                        if (func_info && (int)opline->op1.num-1 < func_info->num_args) {
2733                                tmp = (tmp & (MAY_BE_RC1|MAY_BE_RCN|MAY_BE_REF)) |
2734                                        (tmp & func_info->arg_info[opline->op1.num-1].info.type);
2735                        }
2736#if 0
2737                        /* We won't recieve unused arguments */
2738                        if (ssa_vars[ssa_ops[i].result_def].use_chain < 0 &&
2739                            ssa_vars[ssa_ops[i].result_def].phi_use_chain == NULL &&
2740                            op_array->arg_info &&
2741                            opline->op1.num <= op_array->num_args &&
2742                            op_array->arg_info[opline->op1.num-1].class_name == NULL &&
2743                            !op_array->arg_info[opline->op1.num-1].type_hint) {
2744                                tmp = MAY_BE_UNDEF|MAY_BE_RCN;
2745                        }
2746#endif
2747                        UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
2748                        if (func_info &&
2749                            (int)opline->op1.num-1 < func_info->num_args &&
2750                            func_info->arg_info[opline->op1.num-1].info.ce) {
2751                                UPDATE_SSA_OBJ_TYPE(
2752                                        func_info->arg_info[opline->op1.num-1].info.ce,
2753                                        func_info->arg_info[opline->op1.num-1].info.is_instanceof,
2754                                        ssa_ops[i].result_def);
2755                        } else if (ce) {
2756                                UPDATE_SSA_OBJ_TYPE(ce, 1, ssa_ops[i].result_def);
2757                        } else {
2758                                UPDATE_SSA_OBJ_TYPE(NULL, 0, ssa_ops[i].result_def);
2759                        }
2760                        break;
2761                }
2762                case ZEND_DECLARE_CLASS:
2763                case ZEND_DECLARE_INHERITED_CLASS:
2764                case ZEND_DECLARE_ANON_CLASS:
2765                case ZEND_DECLARE_ANON_INHERITED_CLASS:
2766                        UPDATE_SSA_TYPE(MAY_BE_CLASS, ssa_ops[i].result_def);
2767                        if (script && (ce = zend_hash_find_ptr(&script->class_table, Z_STR_P(CRT_CONSTANT_EX(op_array, opline->op1, ssa->rt_constants)))) != NULL) {
2768                                UPDATE_SSA_OBJ_TYPE(ce, 0, ssa_ops[i].result_def);
2769                        }
2770                        break;
2771                case ZEND_FETCH_CLASS:
2772                        UPDATE_SSA_TYPE(MAY_BE_CLASS, ssa_ops[i].result_def);
2773                        if (opline->op2_type == IS_UNUSED) {
2774                                switch (opline->extended_value & ZEND_FETCH_CLASS_MASK) {
2775                                        case ZEND_FETCH_CLASS_SELF:
2776                                                if (op_array->scope) {
2777                                                        UPDATE_SSA_OBJ_TYPE(op_array->scope, 0, ssa_ops[i].result_def);
2778                                                } else {
2779                                                        UPDATE_SSA_OBJ_TYPE(NULL, 0, ssa_ops[i].result_def);
2780                                                }
2781                                                break;
2782                                        case ZEND_FETCH_CLASS_PARENT:
2783                                                if (op_array->scope && op_array->scope->parent) {
2784                                                        UPDATE_SSA_OBJ_TYPE(op_array->scope->parent, 0, ssa_ops[i].result_def);
2785                                                } else {
2786                                                        UPDATE_SSA_OBJ_TYPE(NULL, 0, ssa_ops[i].result_def);
2787                                                }
2788                                                break;
2789                                        case ZEND_FETCH_CLASS_STATIC:
2790                                        default:
2791                                                UPDATE_SSA_OBJ_TYPE(NULL, 0, ssa_ops[i].result_def);
2792                                                break;
2793                                }
2794                        } else if (opline->op2_type == IS_CONST) {
2795                                zval *zv = CRT_CONSTANT_EX(op_array, opline->op2, ssa->rt_constants);
2796                                if (Z_TYPE_P(zv) == IS_STRING) {
2797                                        ce = get_class_entry(script, Z_STR_P(zv+1));
2798                                        UPDATE_SSA_OBJ_TYPE(ce, 0, ssa_ops[i].result_def);
2799                                } else {
2800                                        UPDATE_SSA_OBJ_TYPE(NULL, 0, ssa_ops[i].result_def);
2801                                }
2802                        } else {
2803                                COPY_SSA_OBJ_TYPE(ssa_ops[i].op2_use, ssa_ops[i].result_def);
2804                        }
2805                        break;
2806                case ZEND_NEW:
2807                        tmp = MAY_BE_RC1|MAY_BE_RCN|MAY_BE_OBJECT;
2808                        if (opline->op1_type == IS_CONST &&
2809                            (ce = get_class_entry(script, Z_STR_P(CRT_CONSTANT_EX(op_array, opline->op1, ssa->rt_constants)+1))) != NULL) {
2810                                UPDATE_SSA_OBJ_TYPE(ce, 0, ssa_ops[i].result_def);
2811                        } else if ((t1 & MAY_BE_CLASS) && ssa_ops[i].op1_use >= 0 && ssa_var_info[ssa_ops[i].op1_use].ce) {
2812                                UPDATE_SSA_OBJ_TYPE(ssa_var_info[ssa_ops[i].op1_use].ce, ssa_var_info[ssa_ops[i].op1_use].is_instanceof, ssa_ops[i].result_def);
2813                        } else {
2814                                UPDATE_SSA_OBJ_TYPE(NULL, 0, ssa_ops[i].result_def);
2815                        }
2816                        UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
2817                        break;
2818                case ZEND_CLONE:
2819                        UPDATE_SSA_TYPE(MAY_BE_RC1|MAY_BE_RCN|MAY_BE_OBJECT, ssa_ops[i].result_def);
2820                        COPY_SSA_OBJ_TYPE(ssa_ops[i].op1_use, ssa_ops[i].result_def);
2821                        break;
2822                case ZEND_INIT_ARRAY:
2823                case ZEND_ADD_ARRAY_ELEMENT:
2824                        if (opline->op1_type == IS_CV && ssa_ops[i].op1_def >= 0) {
2825                                if (opline->extended_value & ZEND_ARRAY_ELEMENT_REF) {
2826                                        tmp = (MAY_BE_REF | t1) & ~(MAY_BE_UNDEF|MAY_BE_RC1|MAY_BE_RCN);
2827                                        if (t1 & MAY_BE_UNDEF) {
2828                                                tmp |= MAY_BE_NULL;
2829                                        }
2830                                } else if ((t1 & (MAY_BE_REF|MAY_BE_RC1|MAY_BE_RCN)) == MAY_BE_REF) {
2831                                        tmp = (MAY_BE_REF | t1) & ~(MAY_BE_UNDEF|MAY_BE_RC1|MAY_BE_RCN);
2832                                        if (t1 & MAY_BE_UNDEF) {
2833                                                tmp |= MAY_BE_NULL;
2834                                        }
2835                                } else if (t1 & MAY_BE_REF) {
2836                                        tmp = (MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_REF | t1);
2837                                } else {
2838                                        tmp = t1;
2839                                        if (t1 & MAY_BE_RC1) {
2840                                                tmp |= MAY_BE_RCN;
2841                                        }
2842                                }
2843                                UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
2844                        }
2845                        if (ssa_ops[i].result_def >= 0) {
2846                                tmp = MAY_BE_RC1|MAY_BE_ARRAY;
2847                                if (opline->op1_type != IS_UNUSED) {
2848                                        tmp |= (t1 & MAY_BE_ANY) << MAY_BE_ARRAY_SHIFT;
2849                                        if (t1 & MAY_BE_UNDEF) {
2850                                                tmp |= MAY_BE_ARRAY_OF_NULL;
2851                                        }
2852                                        if (opline->extended_value & ZEND_ARRAY_ELEMENT_REF) {
2853                                                tmp |= MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF;
2854                                        }
2855                                }
2856                                if (ssa_ops[i].result_use >= 0) {
2857                                        tmp |= ssa_var_info[ssa_ops[i].result_use].type;
2858                                }
2859                                if (opline->op2_type == IS_UNUSED) {
2860                                        tmp |= MAY_BE_ARRAY_KEY_LONG;
2861                                } else {
2862                                        if (t2 & (MAY_BE_LONG|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_DOUBLE)) {
2863                                                tmp |= MAY_BE_ARRAY_KEY_LONG;
2864                                        }
2865                                        if (t2 & (MAY_BE_STRING)) {
2866                                                tmp |= MAY_BE_ARRAY_KEY_STRING;
2867                                                if (opline->op2_type != IS_CONST) {
2868                                                        // FIXME: numeric string
2869                                                        tmp |= MAY_BE_ARRAY_KEY_LONG;
2870                                                }
2871                                        }
2872                                        if (t2 & (MAY_BE_UNDEF | MAY_BE_NULL)) {
2873                                                tmp |= MAY_BE_ARRAY_KEY_STRING;
2874                                        }
2875                                }
2876                                UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
2877                        }
2878                        break;
2879                case ZEND_UNSET_VAR:
2880                        ZEND_ASSERT(opline->extended_value & ZEND_QUICK_SET);
2881                        tmp = MAY_BE_UNDEF;
2882                        if (!op_array->function_name) {
2883                                /* In global scope, we know nothing */
2884                                tmp |= MAY_BE_REF;
2885                        }
2886                        UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
2887                        break;
2888                case ZEND_UNSET_DIM:
2889                case ZEND_UNSET_OBJ:
2890                        if (ssa_ops[i].op1_def >= 0) {
2891                                UPDATE_SSA_TYPE(t1, ssa_ops[i].op1_def);
2892                                COPY_SSA_OBJ_TYPE(ssa_ops[i].op1_use, ssa_ops[i].op1_def);
2893                        }
2894                        break;
2895                case ZEND_FE_RESET_R:
2896                case ZEND_FE_RESET_RW:
2897                        if (ssa_ops[i].op1_def >= 0) {
2898                                tmp = t1;
2899                                if (opline->opcode == ZEND_FE_RESET_RW) {
2900                                        tmp |= MAY_BE_REF;
2901                                } else {
2902                                        if ((t1 & MAY_BE_RC1) && opline->op1_type != IS_TMP_VAR) {
2903                                                tmp |= MAY_BE_RCN;
2904                                        }
2905                                }
2906                                UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
2907                                COPY_SSA_OBJ_TYPE(ssa_ops[i].op1_use, ssa_ops[i].op1_def);
2908                        }
2909                        if (opline->opcode == ZEND_FE_RESET_RW) {
2910//???
2911                                tmp = MAY_BE_REF | (t1 & (MAY_BE_ARRAY | MAY_BE_OBJECT));
2912                        } else {
2913                                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));
2914                        }
2915                        UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
2916                        COPY_SSA_OBJ_TYPE(ssa_ops[i].op1_use, ssa_ops[i].result_def);
2917                        break;
2918                case ZEND_FE_FETCH_R:
2919                case ZEND_FE_FETCH_RW:
2920                        tmp = (t2 & MAY_BE_REF);
2921                        if (t1 & MAY_BE_OBJECT) {
2922                                if (opline->opcode == ZEND_FE_FETCH_RW) {
2923                                        tmp |= MAY_BE_REF | MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
2924                                } else {
2925                                        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;
2926                                }
2927                        }
2928                        if (t1 & MAY_BE_ARRAY) {
2929                                if (opline->opcode == ZEND_FE_FETCH_RW) {
2930                                        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;
2931                                } else {
2932                                        tmp |= ((t1 & MAY_BE_ARRAY_OF_ANY) >> MAY_BE_ARRAY_SHIFT);
2933                                        if (tmp & MAY_BE_ARRAY) {
2934                                                tmp |= MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
2935                                        }
2936                                        if (t1 & MAY_BE_ARRAY_OF_REF) {
2937                                                tmp |= MAY_BE_RC1 | MAY_BE_RCN;
2938                                        } else if (tmp & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)) {
2939                                                tmp |= MAY_BE_RC1 | MAY_BE_RCN;
2940                                        }
2941                                }
2942                        }
2943                        UPDATE_SSA_TYPE(tmp, ssa_ops[i].op2_def);
2944                        if (ssa_ops[i].result_def >= 0) {
2945                                tmp = 0;
2946                                if (t1 & MAY_BE_OBJECT) {
2947                                        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;
2948                                }
2949                                if (t1 & MAY_BE_ARRAY) {
2950                                        if (t1 & MAY_BE_ARRAY_KEY_LONG) {
2951                                                tmp |= MAY_BE_LONG;
2952                                        }
2953                                        if (t1 & MAY_BE_ARRAY_KEY_STRING) {
2954                                                tmp |= MAY_BE_STRING | MAY_BE_RCN;
2955                                        }
2956                                }
2957                                UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
2958                        }
2959                        break;
2960                case ZEND_FETCH_DIM_R:
2961                case ZEND_FETCH_DIM_IS:
2962                case ZEND_FETCH_DIM_RW:
2963                case ZEND_FETCH_DIM_W:
2964                case ZEND_FETCH_DIM_UNSET:
2965                case ZEND_FETCH_DIM_FUNC_ARG:
2966                case ZEND_FETCH_LIST:
2967                        if (ssa_ops[i].op1_def >= 0) {
2968                                tmp = t1 & ~(MAY_BE_RC1|MAY_BE_RCN);
2969                                if (opline->opcode == ZEND_FETCH_DIM_W ||
2970                                    opline->opcode == ZEND_FETCH_DIM_RW ||
2971                                    opline->opcode == ZEND_FETCH_DIM_FUNC_ARG) {
2972                                        if (t1 & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE)) {
2973                                                if (opline->opcode != ZEND_FETCH_DIM_FUNC_ARG) {
2974                                                        tmp &= ~(MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE);
2975                                                }
2976                                                tmp |= MAY_BE_ARRAY | MAY_BE_RC1;
2977                                        }
2978                                        if (t1 & (MAY_BE_STRING|MAY_BE_ARRAY)) {
2979                                                tmp |= MAY_BE_RC1;
2980                                        }
2981                                        if (t1 & (MAY_BE_OBJECT|MAY_BE_RESOURCE)) {
2982                                                tmp |= t1 & (MAY_BE_RC1|MAY_BE_RCN);
2983                                        }
2984                                        if (opline->op2_type == IS_UNUSED) {
2985                                                tmp |= MAY_BE_ARRAY_KEY_LONG;
2986                                        } else {
2987                                                if (t2 & (MAY_BE_LONG|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_RESOURCE|MAY_BE_DOUBLE)) {
2988                                                        tmp |= MAY_BE_ARRAY_KEY_LONG;
2989                                                }
2990                                                if (t2 & MAY_BE_STRING) {
2991                                                        tmp |= MAY_BE_ARRAY_KEY_STRING;
2992                                                        if (opline->op2_type != IS_CONST) {
2993                                                                // FIXME: numeric string
2994                                                                tmp |= MAY_BE_ARRAY_KEY_LONG;
2995                                                        }
2996                                                }
2997                                                if (t2 & (MAY_BE_UNDEF | MAY_BE_NULL)) {
2998                                                        tmp |= MAY_BE_ARRAY_KEY_STRING;
2999                                                }
3000                                        }
3001                                }
3002                                j = ssa_vars[ssa_ops[i].result_def].use_chain;
3003                                while (j >= 0) {
3004                                        switch (op_array->opcodes[j].opcode) {
3005                                                case ZEND_FETCH_DIM_W:
3006                                                case ZEND_FETCH_DIM_RW:
3007                                                case ZEND_FETCH_DIM_FUNC_ARG:
3008                                                case ZEND_ASSIGN_ADD:
3009                                                case ZEND_ASSIGN_SUB:
3010                                                case ZEND_ASSIGN_MUL:
3011                                                case ZEND_ASSIGN_DIV:
3012                                                case ZEND_ASSIGN_MOD:
3013                                                case ZEND_ASSIGN_SL:
3014                                                case ZEND_ASSIGN_SR:
3015                                                case ZEND_ASSIGN_CONCAT:
3016                                                case ZEND_ASSIGN_BW_OR:
3017                                                case ZEND_ASSIGN_BW_AND:
3018                                                case ZEND_ASSIGN_BW_XOR:
3019                                                case ZEND_ASSIGN_POW:
3020                                                case ZEND_ASSIGN_DIM:
3021                                                        tmp |= MAY_BE_ARRAY | MAY_BE_ARRAY_OF_ARRAY;
3022                                                        break;
3023                                                case ZEND_FETCH_OBJ_W:
3024                                                case ZEND_FETCH_OBJ_RW:
3025                                                case ZEND_FETCH_OBJ_FUNC_ARG:
3026                                                case ZEND_ASSIGN_OBJ:
3027                                                case ZEND_PRE_INC_OBJ:
3028                                                case ZEND_PRE_DEC_OBJ:
3029                                                case ZEND_POST_INC_OBJ:
3030                                                case ZEND_POST_DEC_OBJ:
3031                                                        tmp |= MAY_BE_ARRAY_OF_OBJECT;
3032                                                        break;
3033                                                case ZEND_SEND_VAR_EX:
3034                                                case ZEND_SEND_VAR_NO_REF:
3035                                                case ZEND_SEND_VAR_NO_REF_EX:
3036                                                case ZEND_SEND_REF:
3037                                                case ZEND_ASSIGN_REF:
3038                                                case ZEND_YIELD:
3039                                                case ZEND_INIT_ARRAY:
3040                                                case ZEND_ADD_ARRAY_ELEMENT:
3041                                                case ZEND_RETURN_BY_REF:
3042                                                case ZEND_VERIFY_RETURN_TYPE:
3043                                                case ZEND_MAKE_REF:
3044                                                        tmp |= MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
3045                                                        break;
3046                                                case ZEND_PRE_INC:
3047                                                case ZEND_PRE_DEC:
3048                                                case ZEND_POST_INC:
3049                                                case ZEND_POST_DEC:
3050                                                        if (tmp & MAY_BE_ARRAY_OF_LONG) {
3051                                                                /* may overflow */
3052                                                                tmp |= MAY_BE_ARRAY_OF_DOUBLE;
3053                                                        } else if (!(tmp & (MAY_BE_ARRAY_OF_LONG|MAY_BE_ARRAY_OF_DOUBLE))) {
3054                                                                tmp |= MAY_BE_ARRAY_OF_LONG | MAY_BE_ARRAY_OF_DOUBLE;
3055                                                        }
3056                                                        break;
3057                                                case ZEND_UNSET_DIM:
3058                                                case ZEND_UNSET_OBJ:
3059                                                case ZEND_FETCH_DIM_UNSET:
3060                                                case ZEND_FETCH_OBJ_UNSET:
3061                                                        break;
3062                                                default :
3063                                                        break;
3064                                        }
3065                                        j = zend_ssa_next_use(ssa_ops, ssa_ops[i].result_def, j);
3066                                }
3067                                UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
3068                                COPY_SSA_OBJ_TYPE(ssa_ops[i].op1_use, ssa_ops[i].op1_def);
3069                        }
3070                        /* FETCH_LIST on a string behaves like FETCH_R on null */
3071                        tmp = zend_array_element_type(
3072                                opline->opcode != ZEND_FETCH_LIST ? t1 : ((t1 & ~MAY_BE_STRING) | MAY_BE_NULL),
3073                                opline->opcode != ZEND_FETCH_DIM_R && opline->opcode != ZEND_FETCH_DIM_IS
3074                                        && opline->opcode != ZEND_FETCH_LIST,
3075                                opline->op2_type == IS_UNUSED);
3076                        if (opline->opcode == ZEND_FETCH_DIM_W ||
3077                            opline->opcode == ZEND_FETCH_DIM_RW ||
3078                            opline->opcode == ZEND_FETCH_DIM_FUNC_ARG) {
3079                                if (t1 & (MAY_BE_ERROR|MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE|MAY_BE_RESOURCE|MAY_BE_OBJECT)) {
3080                                        tmp |= MAY_BE_ERROR;
3081                                } else if (opline->op2_type == IS_UNUSED) {
3082                                        tmp |= MAY_BE_ERROR;
3083                                } else if (t2 & (MAY_BE_ARRAY|MAY_BE_OBJECT)) {
3084                                        tmp |= MAY_BE_ERROR;
3085                                }
3086                        } else if (opline->opcode == ZEND_FETCH_DIM_IS && (t1 & MAY_BE_STRING)) {
3087                                tmp |= MAY_BE_NULL;
3088                        }
3089                        UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
3090                        break;
3091                case ZEND_FETCH_THIS:
3092                        UPDATE_SSA_OBJ_TYPE(op_array->scope, 1, ssa_ops[i].result_def);
3093                        UPDATE_SSA_TYPE(MAY_BE_RC1|MAY_BE_RCN|MAY_BE_OBJECT, ssa_ops[i].result_def);
3094                        break;
3095                case ZEND_FETCH_OBJ_R:
3096                case ZEND_FETCH_OBJ_IS:
3097                case ZEND_FETCH_OBJ_RW:
3098                case ZEND_FETCH_OBJ_W:
3099                case ZEND_FETCH_OBJ_UNSET:
3100                case ZEND_FETCH_OBJ_FUNC_ARG:
3101                        if (ssa_ops[i].op1_def >= 0) {
3102                                tmp = t1;
3103                                if (opline->opcode == ZEND_FETCH_OBJ_W ||
3104                                    opline->opcode == ZEND_FETCH_OBJ_RW ||
3105                                    opline->opcode == ZEND_FETCH_OBJ_FUNC_ARG) {
3106                                        if (opline->opcode != ZEND_FETCH_DIM_FUNC_ARG) {
3107                                                if (t1 & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_NULL)) {
3108                                                        tmp &= ~(MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE);
3109                                                        tmp |= MAY_BE_OBJECT | MAY_BE_RC1 | MAY_BE_RCN;
3110                                                }
3111                                        }
3112                                }
3113                                UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
3114                                COPY_SSA_OBJ_TYPE(ssa_ops[i].op1_use, ssa_ops[i].op1_def);
3115                        }
3116                        if (ssa_ops[i].result_def >= 0) {
3117                                tmp = MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
3118                                if (opline->opcode != ZEND_FETCH_OBJ_R && opline->opcode != ZEND_FETCH_OBJ_IS) {
3119                                        tmp |= MAY_BE_ERROR;
3120                                }
3121                                if (opline->result_type == IS_TMP_VAR) {
3122                                        tmp |= MAY_BE_RC1 | MAY_BE_RCN;
3123                                } else {
3124                                        tmp |= MAY_BE_REF | MAY_BE_RC1 | MAY_BE_RCN;
3125                                }
3126                                UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
3127                        }
3128                        break;
3129                case ZEND_DO_FCALL:
3130                case ZEND_DO_ICALL:
3131                case ZEND_DO_UCALL:
3132                case ZEND_DO_FCALL_BY_NAME:
3133                        if (ssa_ops[i].result_def >= 0) {
3134                                zend_func_info *func_info = ZEND_FUNC_INFO(op_array);
3135                                zend_call_info *call_info;
3136
3137                                if (!func_info || !func_info->call_map) {
3138                                        goto unknown_opcode;
3139                                }
3140                                call_info = func_info->call_map[opline - op_array->opcodes];
3141                                if (!call_info) {
3142                                        goto unknown_opcode;
3143                                }
3144                                tmp = zend_get_func_info(call_info, ssa) & ~FUNC_MAY_WARN;
3145                                UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
3146                                if (call_info->callee_func->type == ZEND_USER_FUNCTION) {
3147                                        func_info = ZEND_FUNC_INFO(&call_info->callee_func->op_array);
3148                                        if (func_info) {
3149                                                UPDATE_SSA_OBJ_TYPE(
3150                                                        func_info->return_info.ce,
3151                                                        func_info->return_info.is_instanceof,
3152                                                        ssa_ops[i].result_def);
3153                                        }
3154                                }
3155                        }
3156                        break;
3157                case ZEND_FETCH_CONSTANT:
3158                case ZEND_FETCH_CLASS_CONSTANT:
3159                        UPDATE_SSA_TYPE(MAY_BE_RC1|MAY_BE_RCN|MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE|MAY_BE_STRING|MAY_BE_RESOURCE|MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY, ssa_ops[i].result_def);
3160                        break;
3161                case ZEND_STRLEN:
3162                        tmp = MAY_BE_LONG;
3163                        if (t1 & (MAY_BE_ANY - (MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE|MAY_BE_STRING))) {
3164                                tmp |= MAY_BE_NULL;
3165                        }
3166                        UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
3167                        break;
3168                case ZEND_TYPE_CHECK:
3169                case ZEND_DEFINED:
3170                        UPDATE_SSA_TYPE(MAY_BE_FALSE|MAY_BE_TRUE, ssa_ops[i].result_def);
3171                        break;
3172                case ZEND_VERIFY_RETURN_TYPE:
3173                        if (t1 & MAY_BE_REF) {
3174                                tmp = t1;
3175                                ce = NULL;
3176                        } else {
3177                                zend_arg_info *ret_info = op_array->arg_info - 1;
3178
3179                                tmp = zend_fetch_arg_info(script, ret_info, &ce);
3180                                if (tmp & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)) {
3181                                        tmp |= MAY_BE_RC1 | MAY_BE_RCN;
3182                                }
3183                        }
3184                        if (opline->op1_type & (IS_TMP_VAR|IS_VAR|IS_CV)) {
3185                                UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
3186                                if (ce) {
3187                                        UPDATE_SSA_OBJ_TYPE(ce, 1, ssa_ops[i].op1_def);
3188                                } else {
3189                                        UPDATE_SSA_OBJ_TYPE(NULL, 0, ssa_ops[i].op1_def);
3190                                }
3191                        } else {
3192                                UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
3193                                if (ce) {
3194                                        UPDATE_SSA_OBJ_TYPE(ce, 1, ssa_ops[i].result_def);
3195                                } else {
3196                                        UPDATE_SSA_OBJ_TYPE(NULL, 0, ssa_ops[i].result_def);
3197                                }
3198                        }
3199                        break;
3200                case ZEND_CATCH:
3201                case ZEND_INCLUDE_OR_EVAL:
3202                        /* Forbidden opcodes */
3203                        ZEND_ASSERT(0);
3204                        break;
3205                default:
3206unknown_opcode:
3207                        if (ssa_ops[i].op1_def >= 0) {
3208                                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;
3209                                UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
3210                        }
3211                        if (ssa_ops[i].result_def >= 0) {
3212                                tmp = MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
3213                                if (opline->result_type == IS_TMP_VAR) {
3214                                        tmp |= MAY_BE_RC1 | MAY_BE_RCN;
3215                                } else {
3216                                        tmp |= MAY_BE_REF | MAY_BE_RC1 | MAY_BE_RCN;
3217                                }
3218                                UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
3219                        }
3220                        break;
3221        }
3222}
3223
3224static uint32_t get_class_entry_rank(zend_class_entry *ce) {
3225        uint32_t rank = 0;
3226        while (ce->parent) {
3227                rank++;
3228                ce = ce->parent;
3229        }
3230        return rank;
3231}
3232
3233/* Compute least common ancestor on class inheritance tree only */
3234static zend_class_entry *join_class_entries(
3235                zend_class_entry *ce1, zend_class_entry *ce2, int *is_instanceof) {
3236        uint32_t rank1, rank2;
3237        if (ce1 == ce2) {
3238                return ce1;
3239        }
3240        if (!ce1 || !ce2) {
3241                return NULL;
3242        }
3243
3244        rank1 = get_class_entry_rank(ce1);
3245        rank2 = get_class_entry_rank(ce2);
3246
3247        while (rank1 != rank2) {
3248                if (rank1 > rank2) {
3249                        ce1 = ce1->parent;
3250                        rank1--;
3251                } else {
3252                        ce2 = ce2->parent;
3253                        rank2--;
3254                }
3255        }
3256
3257        while (ce1 != ce2) {
3258                ce1 = ce1->parent;
3259                ce2 = ce2->parent;
3260        }
3261
3262        if (ce1) {
3263                *is_instanceof = 1;
3264        }
3265        return ce1;
3266}
3267
3268int zend_infer_types_ex(const zend_op_array *op_array, const zend_script *script, zend_ssa *ssa, zend_bitset worklist)
3269{
3270        zend_basic_block *blocks = ssa->cfg.blocks;
3271        zend_ssa_var *ssa_vars = ssa->vars;
3272        zend_ssa_var_info *ssa_var_info = ssa->var_info;
3273        int ssa_vars_count = ssa->vars_count;
3274        int i, j;
3275        uint32_t tmp;
3276
3277        WHILE_WORKLIST(worklist, zend_bitset_len(ssa_vars_count), j) {
3278                if (ssa_vars[j].definition_phi) {
3279                        zend_ssa_phi *p = ssa_vars[j].definition_phi;
3280                        if (p->pi >= 0) {
3281                                zend_class_entry *ce = ssa_var_info[p->sources[0]].ce;
3282                                int is_instanceof = ssa_var_info[p->sources[0]].is_instanceof;
3283                                tmp = get_ssa_var_info(ssa, p->sources[0]);
3284
3285                                if (!p->has_range_constraint) {
3286                                        zend_ssa_type_constraint *constraint = &p->constraint.type;
3287                                        tmp &= constraint->type_mask;
3288                                        if ((tmp & MAY_BE_OBJECT) && constraint->ce && ce != constraint->ce) {
3289                                                if (!ce) {
3290                                                        ce = constraint->ce;
3291                                                        is_instanceof = 1;
3292                                                } else if (is_instanceof && instanceof_function(constraint->ce, ce)) {
3293                                                        ce = constraint->ce;
3294                                                } else {
3295                                                        /* Ignore the constraint (either ce instanceof constraint->ce or
3296                                                         * they are unrelated, as far as we can statically determine) */
3297                                                }
3298                                        }
3299                                }
3300
3301                                UPDATE_SSA_TYPE(tmp, j);
3302                                UPDATE_SSA_OBJ_TYPE(ce, is_instanceof, j);
3303                        } else {
3304                                int first = 1;
3305                                int is_instanceof = 0;
3306                                zend_class_entry *ce = NULL;
3307
3308                                tmp = 0;
3309                                for (i = 0; i < blocks[p->block].predecessors_count; i++) {
3310                                        tmp |= get_ssa_var_info(ssa, p->sources[i]);
3311                                }
3312                                UPDATE_SSA_TYPE(tmp, j);
3313                                for (i = 0; i < blocks[p->block].predecessors_count; i++) {
3314                                        if (p->sources[i] >= 0) {
3315                                                zend_ssa_var_info *info = &ssa_var_info[p->sources[i]];
3316                                                if (info->type & MAY_BE_OBJECT) {
3317                                                        if (first) {
3318                                                                ce = info->ce;
3319                                                                is_instanceof = info->is_instanceof;
3320                                                                first = 0;
3321                                                        } else {
3322                                                                is_instanceof |= info->is_instanceof;
3323                                                                ce = join_class_entries(ce, info->ce, &is_instanceof);
3324                                                        }
3325                                                }
3326                                        }
3327                                }
3328                                UPDATE_SSA_OBJ_TYPE(ce, ce ? is_instanceof : 0, j);
3329                        }
3330                } else if (ssa_vars[j].definition >= 0) {
3331                        i = ssa_vars[j].definition;
3332                        zend_update_type_info(op_array, ssa, script, worklist, i);
3333                }
3334        } WHILE_WORKLIST_END();
3335        return SUCCESS;
3336}
3337
3338static zend_bool is_narrowable_instr(zend_op *opline)  {
3339        return opline->opcode == ZEND_ADD || opline->opcode == ZEND_SUB
3340                || opline->opcode == ZEND_MUL || opline->opcode == ZEND_DIV;
3341}
3342
3343static zend_bool is_effective_op1_double_cast(zend_op *opline, zval *op2) {
3344        return (opline->opcode == ZEND_ADD && Z_LVAL_P(op2) == 0)
3345                || (opline->opcode == ZEND_SUB && Z_LVAL_P(op2) == 0)
3346                || (opline->opcode == ZEND_MUL && Z_LVAL_P(op2) == 1)
3347                || (opline->opcode == ZEND_DIV && Z_LVAL_P(op2) == 1);
3348}
3349static zend_bool is_effective_op2_double_cast(zend_op *opline, zval *op1) {
3350        /* In PHP it holds that (double)(0-$int) is bitwise identical to 0.0-(double)$int,
3351         * so allowing SUB here is fine. */
3352        return (opline->opcode == ZEND_ADD && Z_LVAL_P(op1) == 0)
3353                || (opline->opcode == ZEND_SUB && Z_LVAL_P(op1) == 0)
3354                || (opline->opcode == ZEND_MUL && Z_LVAL_P(op1) == 1);
3355}
3356
3357/* This function recursively checks whether it's possible to convert an integer variable
3358 * initialization to a double initialization. The basic idea is that if the value is used
3359 * only in add/sub/mul/div ("narrowable" instructions) with a double result value, then it
3360 * will be cast to double at that point anyway, so we may as well do it earlier already.
3361 *
3362 * The tricky case are chains of operations, where it's not necessarily a given that converting
3363 * an integer to double before the chain of operations is the same as converting it after the
3364 * chain. What this function does is detect two cases where it is safe:
3365 *  * If the operations only involve constants, then we can simply verify that performing the
3366 *    calculation on integers and doubles yields the same value.
3367 *  * Even if one operand is not known, we may be able to determine that the operations with the
3368 *    integer replaced by a double only acts as an effective double cast on the unknown operand.
3369 *    E.g. 0+$i and 0.0+$i only differ by that cast. If then the consuming instruction of this
3370 *    result will perform a double cast anyway, the conversion is safe.
3371 *
3372 * The checks happens recursively, while keeping track of which variables are already visisted to
3373 * avoid infinite loops. An iterative, worklist driven approach would be possible, but the state
3374 * management more cumbersome to implement, so we don't bother for now.
3375 */
3376static zend_bool can_convert_to_double(
3377                const zend_op_array *op_array, zend_ssa *ssa, int var_num,
3378                zval *value, zend_bitset visited) {
3379        zend_ssa_var *var = &ssa->vars[var_num];
3380        zend_ssa_phi *phi;
3381        int use;
3382        uint32_t type;
3383
3384        if (zend_bitset_in(visited, var_num)) {
3385                return 1;
3386        }
3387        zend_bitset_incl(visited, var_num);
3388
3389        for (use = var->use_chain; use >= 0; use = zend_ssa_next_use(ssa->ops, var_num, use)) {
3390                zend_op *opline = &op_array->opcodes[use];
3391                zend_ssa_op *ssa_op = &ssa->ops[use];
3392
3393                if (is_no_val_use(opline, ssa_op, var_num)) {
3394                        continue;
3395                }
3396
3397                if (!is_narrowable_instr(opline)) {
3398                        return 0;
3399                }
3400
3401                /* Instruction always returns double, the conversion is certainly fine */
3402                type = ssa->var_info[ssa_op->result_def].type;
3403                if ((type & MAY_BE_ANY) == MAY_BE_DOUBLE) {
3404                        continue;
3405                }
3406
3407                /* UNDEF signals that the previous result is an effective double cast, this is only allowed
3408                 * if this instruction would have done the cast anyway (previous check). */
3409                if (Z_ISUNDEF_P(value)) {
3410                        return 0;
3411                }
3412
3413                /* Check that narrowing can actually be useful */
3414                if ((type & MAY_BE_ANY) & ~(MAY_BE_LONG|MAY_BE_DOUBLE)) {
3415                        return 0;
3416                }
3417
3418                {
3419                        /* For calculation on original values */
3420                        zval orig_op1, orig_op2, orig_result;
3421                        /* For calculation with var_num cast to double */
3422                        zval dval_op1, dval_op2, dval_result;
3423
3424                        ZVAL_UNDEF(&orig_op1);
3425                        ZVAL_UNDEF(&dval_op1);
3426                        if (ssa_op->op1_use == var_num) {
3427                                ZVAL_COPY_VALUE(&orig_op1, value);
3428                                ZVAL_DOUBLE(&dval_op1, (double) Z_LVAL_P(value));
3429                        } else if (opline->op1_type == IS_CONST) {
3430                                zval *zv = CRT_CONSTANT_EX(op_array, opline->op1, ssa->rt_constants);
3431                                if (Z_TYPE_P(zv) == IS_LONG || Z_TYPE_P(zv) == IS_DOUBLE) {
3432                                        ZVAL_COPY_VALUE(&orig_op1, zv);
3433                                        ZVAL_COPY_VALUE(&dval_op1, zv);
3434                                }
3435                        }
3436
3437                        ZVAL_UNDEF(&orig_op2);
3438                        ZVAL_UNDEF(&dval_op2);
3439                        if (ssa_op->op2_use == var_num) {
3440                                ZVAL_COPY_VALUE(&orig_op2, value);
3441                                ZVAL_DOUBLE(&dval_op2, (double) Z_LVAL_P(value));
3442                        } else if (opline->op2_type == IS_CONST) {
3443                                zval *zv = CRT_CONSTANT_EX(op_array, opline->op2, ssa->rt_constants);
3444                                if (Z_TYPE_P(zv) == IS_LONG || Z_TYPE_P(zv) == IS_DOUBLE) {
3445                                        ZVAL_COPY_VALUE(&orig_op2, zv);
3446                                        ZVAL_COPY_VALUE(&dval_op2, zv);
3447                                }
3448                        }
3449
3450                        ZEND_ASSERT(!Z_ISUNDEF(orig_op1) || !Z_ISUNDEF(orig_op2));
3451                        if (Z_ISUNDEF(orig_op1)) {
3452                                if (opline->opcode == ZEND_MUL && Z_LVAL(orig_op2) == 0) {
3453                                        ZVAL_LONG(&orig_result, 0);
3454                                } else if (is_effective_op1_double_cast(opline, &orig_op2)) {
3455                                        ZVAL_UNDEF(&orig_result);
3456                                } else {
3457                                        return 0;
3458                                }
3459                        } else if (Z_ISUNDEF(orig_op2)) {
3460                                if (opline->opcode == ZEND_MUL && Z_LVAL(orig_op1) == 0) {
3461                                        ZVAL_LONG(&orig_result, 0);
3462                                } else if (is_effective_op2_double_cast(opline, &orig_op1)) {
3463                                        ZVAL_UNDEF(&orig_result);
3464                                } else {
3465                                        return 0;
3466                                }
3467                        } else {
3468                                /* Avoid division by zero */
3469                                if (opline->opcode == ZEND_DIV && zval_get_double(&orig_op2) == 0.0) {
3470                                        return 0;
3471                                }
3472
3473                                get_binary_op(opline->opcode)(&orig_result, &orig_op1, &orig_op2);
3474                                get_binary_op(opline->opcode)(&dval_result, &dval_op1, &dval_op2);
3475                                ZEND_ASSERT(Z_TYPE(dval_result) == IS_DOUBLE);
3476                                if (zval_get_double(&orig_result) != Z_DVAL(dval_result)) {
3477                                        return 0;
3478                                }
3479                        }
3480
3481                        if (!can_convert_to_double(op_array, ssa, ssa_op->result_def, &orig_result, visited)) {
3482                                return 0;
3483                        }
3484                }
3485        }
3486
3487        for (phi = var->phi_use_chain; phi; phi = zend_ssa_next_use_phi(ssa, var_num, phi)) {
3488                /* Check that narrowing can actually be useful */
3489                type = ssa->var_info[phi->ssa_var].type;
3490                if ((type & MAY_BE_ANY) & ~(MAY_BE_LONG|MAY_BE_DOUBLE)) {
3491                        return 0;
3492                }
3493
3494                if (!can_convert_to_double(op_array, ssa, phi->ssa_var, value, visited)) {
3495                        return 0;
3496                }
3497        }
3498
3499        return 1;
3500}
3501
3502static int zend_type_narrowing(const zend_op_array *op_array, const zend_script *script, zend_ssa *ssa)
3503{
3504        uint32_t bitset_len = zend_bitset_len(ssa->vars_count);
3505        zend_bitset visited, worklist;
3506        int i, v;
3507        zend_op *opline;
3508        zend_bool narrowed = 0;
3509        ALLOCA_FLAG(use_heap)
3510
3511        visited = ZEND_BITSET_ALLOCA(2 * bitset_len, use_heap);
3512        worklist = visited + bitset_len;
3513
3514        zend_bitset_clear(worklist, bitset_len);
3515
3516        for (v = op_array->last_var; v < ssa->vars_count; v++) {
3517                if ((ssa->var_info[v].type & (MAY_BE_REF | MAY_BE_ANY | MAY_BE_UNDEF)) != MAY_BE_LONG) continue;
3518                if (ssa->vars[v].definition < 0) continue;
3519                if (ssa->vars[v].no_val) continue;
3520                opline = op_array->opcodes + ssa->vars[v].definition;
3521                /* Go through assignments of literal integers and check if they can be converted to
3522                 * doubles instead, in the hope that we'll narrow long|double to double. */
3523                if (opline->opcode == ZEND_ASSIGN && opline->result_type == IS_UNUSED &&
3524                                opline->op1_type == IS_CV && opline->op2_type == IS_CONST) {
3525                        zval *value = CRT_CONSTANT_EX(op_array, opline->op2, ssa->rt_constants);
3526
3527                        zend_bitset_clear(visited, bitset_len);
3528                        if (can_convert_to_double(op_array, ssa, v, value, visited)) {
3529                                narrowed = 1;
3530                                ssa->var_info[v].use_as_double = 1;
3531                                /* The "visited" vars are exactly those which may change their type due to
3532                                 * narrowing. Reset their types and add them to the type inference worklist */
3533                                ZEND_BITSET_FOREACH(visited, bitset_len, i) {
3534                                        ssa->var_info[i].type &= ~MAY_BE_ANY;
3535                                } ZEND_BITSET_FOREACH_END();
3536                                zend_bitset_union(worklist, visited, bitset_len);
3537                        }
3538                }
3539        }
3540
3541        if (!narrowed) {
3542                free_alloca(visited, use_heap);
3543                return SUCCESS;
3544        }
3545
3546        if (zend_infer_types_ex(op_array, script, ssa, worklist) != SUCCESS) {
3547                free_alloca(visited, use_heap);
3548                return FAILURE;
3549        }
3550
3551        free_alloca(visited, use_heap);
3552        return SUCCESS;
3553}
3554
3555static int is_recursive_tail_call(const zend_op_array *op_array,
3556                                  zend_op             *opline)
3557{
3558        zend_func_info *info = ZEND_FUNC_INFO(op_array);
3559
3560        if (info->ssa.ops && info->ssa.vars && info->call_map &&
3561            info->ssa.ops[opline - op_array->opcodes].op1_use >= 0 &&
3562            info->ssa.vars[info->ssa.ops[opline - op_array->opcodes].op1_use].definition >= 0) {
3563
3564                zend_op *op = op_array->opcodes + info->ssa.vars[info->ssa.ops[opline - op_array->opcodes].op1_use].definition;
3565
3566                if (op->opcode == ZEND_DO_UCALL) {
3567                        zend_call_info *call_info = info->call_map[op - op_array->opcodes];
3568                        if (call_info && op_array == &call_info->callee_func->op_array) {
3569                                return 1;
3570                        }
3571                }
3572        }
3573        return 0;
3574}
3575
3576void zend_init_func_return_info(const zend_op_array   *op_array,
3577                                const zend_script     *script,
3578                                zend_ssa_var_info     *ret)
3579{
3580        if (op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
3581                zend_arg_info *ret_info = op_array->arg_info - 1;
3582                zend_ssa_range tmp_range = {0, 0, 0, 0};
3583
3584                ret->type = zend_fetch_arg_info(script, ret_info, &ret->ce);
3585                if (op_array->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
3586                        ret->type |= MAY_BE_REF;
3587                }
3588                ret->is_instanceof = (ret->ce) ? 1 : 0;
3589                ret->range = tmp_range;
3590                ret->has_range = 0;
3591        }
3592}
3593
3594void zend_func_return_info(const zend_op_array   *op_array,
3595                           const zend_script     *script,
3596                           int                    recursive,
3597                           int                    widening,
3598                           zend_ssa_var_info     *ret)
3599{
3600        zend_func_info *info = ZEND_FUNC_INFO(op_array);
3601        zend_ssa *ssa = &info->ssa;
3602        int blocks_count = info->ssa.cfg.blocks_count;
3603        zend_basic_block *blocks = info->ssa.cfg.blocks;
3604        int j;
3605        uint32_t t1;
3606        uint32_t tmp = 0;
3607        zend_class_entry *tmp_ce = NULL;
3608        int tmp_is_instanceof = -1;
3609        zend_class_entry *arg_ce;
3610        int arg_is_instanceof;
3611        zend_ssa_range tmp_range = {0, 0, 0, 0};
3612        int tmp_has_range = -1;
3613
3614        if (op_array->fn_flags & ZEND_ACC_GENERATOR) {
3615                ret->type = MAY_BE_OBJECT | MAY_BE_RC1 | MAY_BE_RCN;
3616                ret->ce = zend_ce_generator;
3617                ret->is_instanceof = 0;
3618                ret->range = tmp_range;
3619                ret->has_range = 0;
3620                return;
3621        }
3622
3623        for (j = 0; j < blocks_count; j++) {
3624                if ((blocks[j].flags & ZEND_BB_REACHABLE) && blocks[j].len != 0) {
3625                        zend_op *opline = op_array->opcodes + blocks[j].start + blocks[j].len - 1;
3626
3627                        if (opline->opcode == ZEND_RETURN || opline->opcode == ZEND_RETURN_BY_REF) {
3628                                if (!recursive &&
3629                                    info->ssa.ops &&
3630                                    info->ssa.var_info &&
3631                                    info->ssa.ops[opline - op_array->opcodes].op1_use >= 0 &&
3632                                    info->ssa.var_info[info->ssa.ops[opline - op_array->opcodes].op1_use].recursive) {
3633                                        continue;
3634                                }
3635                                if (is_recursive_tail_call(op_array, opline)) {
3636                                        continue;
3637                                }
3638                                t1 = OP1_INFO();
3639                                if (t1 & MAY_BE_UNDEF) {
3640                                        t1 |= MAY_BE_NULL;
3641                                }
3642                                if (opline->opcode == ZEND_RETURN) {
3643                                        if (t1 & MAY_BE_RC1) {
3644                                                t1 |= MAY_BE_RCN;
3645                                        }
3646                                        t1 &= ~(MAY_BE_UNDEF | MAY_BE_REF);
3647                                } else {
3648                                        t1 |= MAY_BE_REF;
3649                                        t1 &= ~(MAY_BE_UNDEF | MAY_BE_RC1 | MAY_BE_RCN);
3650                                }
3651                                tmp |= t1;
3652
3653                                if (info->ssa.ops &&
3654                                    info->ssa.var_info &&
3655                                    info->ssa.ops[opline - op_array->opcodes].op1_use >= 0 &&
3656                                    info->ssa.var_info[info->ssa.ops[opline - op_array->opcodes].op1_use].ce) {
3657                                        arg_ce = info->ssa.var_info[info->ssa.ops[opline - op_array->opcodes].op1_use].ce;
3658                                        arg_is_instanceof = info->ssa.var_info[info->ssa.ops[opline - op_array->opcodes].op1_use].is_instanceof;
3659                                } else {
3660                                        arg_ce = NULL;
3661                                        arg_is_instanceof = 0;
3662                                }
3663
3664                                if (tmp_is_instanceof < 0) {
3665                                        tmp_ce = arg_ce;
3666                                        tmp_is_instanceof = arg_is_instanceof;
3667                                } else if (arg_ce && arg_ce == tmp_ce) {
3668                                        if (tmp_is_instanceof != arg_is_instanceof) {
3669                                                tmp_is_instanceof = 1;
3670                                        }
3671                                } else {
3672                                        tmp_ce = NULL;
3673                                        tmp_is_instanceof = 0;
3674                                }
3675
3676                                if (opline->op1_type == IS_CONST) {
3677                                        zval *zv = CRT_CONSTANT_EX(op_array, opline->op1, info->ssa.rt_constants);
3678
3679                                        if (Z_TYPE_P(zv) == IS_NULL) {
3680                                                if (tmp_has_range < 0) {
3681                                                        tmp_has_range = 1;
3682                                                        tmp_range.underflow = 0;
3683                                                        tmp_range.min = 0;
3684                                                        tmp_range.max = 0;
3685                                                        tmp_range.overflow = 0;
3686                                                } else if (tmp_has_range) {
3687                                                        if (!tmp_range.underflow) {
3688                                                                tmp_range.min = MIN(tmp_range.min, 0);
3689                                                        }
3690                                                        if (!tmp_range.overflow) {
3691                                                                tmp_range.max = MAX(tmp_range.max, 0);
3692                                                        }
3693                                                }
3694                                        } else if (Z_TYPE_P(zv) == IS_FALSE) {
3695                                                if (tmp_has_range < 0) {
3696                                                        tmp_has_range = 1;
3697                                                        tmp_range.underflow = 0;
3698                                                        tmp_range.min = 0;
3699                                                        tmp_range.max = 0;
3700                                                        tmp_range.overflow = 0;
3701                                                } else if (tmp_has_range) {
3702                                                        if (!tmp_range.underflow) {
3703                                                                tmp_range.min = MIN(tmp_range.min, 0);
3704                                                        }
3705                                                        if (!tmp_range.overflow) {
3706                                                                tmp_range.max = MAX(tmp_range.max, 0);
3707                                                        }
3708                                                }
3709                                        } else if (Z_TYPE_P(zv) == IS_TRUE) {
3710                                                if (tmp_has_range < 0) {
3711                                                        tmp_has_range = 1;
3712                                                        tmp_range.underflow = 0;
3713                                                        tmp_range.min = 1;
3714                                                        tmp_range.max = 1;
3715                                                        tmp_range.overflow = 0;
3716                                                } else if (tmp_has_range) {
3717                                                        if (!tmp_range.underflow) {
3718                                                                tmp_range.min = MIN(tmp_range.min, 1);
3719                                                        }
3720                                                        if (!tmp_range.overflow) {
3721                                                                tmp_range.max = MAX(tmp_range.max, 1);
3722                                                        }
3723                                                }
3724                                        } else if (Z_TYPE_P(zv) == IS_LONG) {
3725                                                if (tmp_has_range < 0) {
3726                                                        tmp_has_range = 1;
3727                                                        tmp_range.underflow = 0;
3728                                                        tmp_range.min = Z_LVAL_P(zv);
3729                                                        tmp_range.max = Z_LVAL_P(zv);
3730                                                        tmp_range.overflow = 0;
3731                                                } else if (tmp_has_range) {
3732                                                        if (!tmp_range.underflow) {
3733                                                                tmp_range.min = MIN(tmp_range.min, Z_LVAL_P(zv));
3734                                                        }
3735                                                        if (!tmp_range.overflow) {
3736                                                                tmp_range.max = MAX(tmp_range.max, Z_LVAL_P(zv));
3737                                                        }
3738                                                }
3739                                        } else {
3740                                                tmp_has_range = 0;
3741                                        }
3742                                } else if (info->ssa.ops &&
3743                                           info->ssa.var_info &&
3744                                           info->ssa.ops[opline - op_array->opcodes].op1_use >= 0) {
3745                                        if (info->ssa.var_info[info->ssa.ops[opline - op_array->opcodes].op1_use].has_range) {
3746                                                if (tmp_has_range < 0) {
3747                                                        tmp_has_range = 1;
3748                                                        tmp_range = info->ssa.var_info[info->ssa.ops[opline - op_array->opcodes].op1_use].range;
3749                                                } else if (tmp_has_range) {
3750                                                        /* union */
3751                                                        if (info->ssa.var_info[info->ssa.ops[opline - op_array->opcodes].op1_use].range.underflow) {
3752                                                                tmp_range.underflow = 1;
3753                                                                tmp_range.min = ZEND_LONG_MIN;
3754                                                        } else {
3755                                                                tmp_range.min = MIN(tmp_range.min, info->ssa.var_info[info->ssa.ops[opline - op_array->opcodes].op1_use].range.min);
3756                                                        }
3757                                                        if (info->ssa.var_info[info->ssa.ops[opline - op_array->opcodes].op1_use].range.overflow) {
3758                                                                tmp_range.overflow = 1;
3759                                                                tmp_range.max = ZEND_LONG_MAX;
3760                                                        } else {
3761                                                                tmp_range.max = MAX(tmp_range.max, info->ssa.var_info[info->ssa.ops[opline - op_array->opcodes].op1_use].range.max);
3762                                                        }
3763                                                }
3764                                        } else if (!widening) {
3765                                                tmp_has_range = 1;
3766                                                tmp_range.underflow = 1;
3767                                                tmp_range.min = ZEND_LONG_MIN;
3768                                                tmp_range.max = ZEND_LONG_MAX;
3769                                                tmp_range.overflow = 1;
3770                                        }
3771                                } else {
3772                                        tmp_has_range = 0;
3773                                }
3774                        }
3775                }
3776        }
3777
3778        if (!(op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE)) {
3779                if (tmp_is_instanceof < 0) {
3780                        tmp_is_instanceof = 0;
3781                        tmp_ce = NULL;
3782                }
3783                if (tmp_has_range < 0) {
3784                        tmp_has_range = 0;
3785                }
3786                ret->type = tmp;
3787                ret->ce = tmp_ce;
3788                ret->is_instanceof = tmp_is_instanceof;
3789        }
3790        ret->range = tmp_range;
3791        ret->has_range = tmp_has_range;
3792}
3793
3794static int zend_infer_types(const zend_op_array *op_array, const zend_script *script, zend_ssa *ssa)
3795{
3796        zend_ssa_var_info *ssa_var_info = ssa->var_info;
3797        int ssa_vars_count = ssa->vars_count;
3798        int j;
3799        zend_bitset worklist;
3800        ALLOCA_FLAG(use_heap);
3801
3802        worklist = do_alloca(sizeof(zend_ulong) * zend_bitset_len(ssa_vars_count), use_heap);
3803        memset(worklist, 0, sizeof(zend_ulong) * zend_bitset_len(ssa_vars_count));
3804
3805        /* Type Inference */
3806        for (j = op_array->last_var; j < ssa_vars_count; j++) {
3807                zend_bitset_incl(worklist, j);
3808                ssa_var_info[j].type = 0;
3809        }
3810
3811        if (zend_infer_types_ex(op_array, script, ssa, worklist) != SUCCESS) {
3812                free_alloca(worklist,  use_heap);
3813                return FAILURE;
3814        }
3815
3816        /* Narrowing integer initialization to doubles */
3817        zend_type_narrowing(op_array, script, ssa);
3818
3819        for (j = 0; j < op_array->last_var; j++) {
3820                /* $php_errormsg and $http_response_header may be updated indirectly */
3821                if (zend_string_equals_literal(op_array->vars[j], "php_errormsg")) {
3822                        int i;
3823                        for (i = 0; i < ssa_vars_count; i++) {
3824                                if (ssa->vars[i].var == j) {
3825                                        ssa_var_info[i].type |= MAY_BE_STRING | MAY_BE_RC1 | MAY_BE_RCN;
3826                                }
3827                        }
3828                } else if (zend_string_equals_literal(op_array->vars[j], "http_response_header")) {
3829                        int i;
3830                        for (i = 0; i < ssa_vars_count; i++) {
3831                                if (ssa->vars[i].var == j) {
3832                                        ssa_var_info[i].type |= MAY_BE_ARRAY | MAY_BE_ARRAY_KEY_LONG | MAY_BE_ARRAY_OF_STRING | MAY_BE_RC1 | MAY_BE_RCN;
3833                                }
3834                        }
3835                }
3836        }
3837
3838        if (ZEND_FUNC_INFO(op_array)) {
3839                zend_func_return_info(op_array, script, 1, 0, &ZEND_FUNC_INFO(op_array)->return_info);
3840        }
3841
3842        free_alloca(worklist,  use_heap);
3843        return SUCCESS;
3844}
3845
3846int zend_ssa_inference(zend_arena **arena, const zend_op_array *op_array, const zend_script *script, zend_ssa *ssa) /* {{{ */
3847{
3848        zend_ssa_var_info *ssa_var_info;
3849        int i;
3850
3851        if (!ssa->var_info) {
3852                ssa->var_info = zend_arena_calloc(arena, ssa->vars_count, sizeof(zend_ssa_var_info));
3853        }
3854        ssa_var_info = ssa->var_info;
3855
3856        if (!op_array->function_name) {
3857                for (i = 0; i < op_array->last_var; i++) {
3858                        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;
3859                        ssa_var_info[i].has_range = 0;
3860                }
3861        } else {
3862                for (i = 0; i < op_array->last_var; i++) {
3863                        ssa_var_info[i].type = MAY_BE_UNDEF;
3864                        ssa_var_info[i].has_range = 0;
3865                }
3866        }
3867        for (i = op_array->last_var; i < ssa->vars_count; i++) {
3868                ssa_var_info[i].type = 0;
3869                ssa_var_info[i].has_range = 0;
3870        }
3871
3872        if (zend_infer_ranges(op_array, ssa) != SUCCESS) {
3873                return FAILURE;
3874        }
3875
3876        if (zend_infer_types(op_array, script, ssa) != SUCCESS) {
3877                return FAILURE;
3878        }
3879
3880        return SUCCESS;
3881}
3882/* }}} */
3883
3884void zend_inference_check_recursive_dependencies(zend_op_array *op_array)
3885{
3886        zend_func_info *info = ZEND_FUNC_INFO(op_array);
3887        zend_call_info *call_info;
3888        zend_bitset worklist;
3889        int worklist_len, i;
3890        ALLOCA_FLAG(use_heap);
3891
3892        if (!info->ssa.var_info || !(info->flags & ZEND_FUNC_RECURSIVE)) {
3893                return;
3894        }
3895        worklist_len = zend_bitset_len(info->ssa.vars_count);
3896        worklist = do_alloca(sizeof(zend_ulong) * worklist_len, use_heap);
3897        memset(worklist, 0, sizeof(zend_ulong) * worklist_len);
3898        call_info = info->callee_info;
3899        while (call_info) {
3900                if (call_info->recursive &&
3901                    info->ssa.ops[call_info->caller_call_opline - op_array->opcodes].result_def >= 0) {
3902                        zend_bitset_incl(worklist, info->ssa.ops[call_info->caller_call_opline - op_array->opcodes].result_def);
3903                }
3904                call_info = call_info->next_callee;
3905        }
3906        WHILE_WORKLIST(worklist, worklist_len, i) {
3907                if (!info->ssa.var_info[i].recursive) {
3908                        info->ssa.var_info[i].recursive = 1;
3909                        add_usages(op_array, &info->ssa, worklist, i);
3910                }
3911        } WHILE_WORKLIST_END();
3912        free_alloca(worklist, use_heap);
3913}
3914
3915/*
3916 * Local variables:
3917 * tab-width: 4
3918 * c-basic-offset: 4
3919 * indent-tabs-mode: t
3920 * End:
3921 */
Note: See TracBrowser for help on using the repository browser.