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