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