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