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