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