xref: /PHP-7.2/Zend/zend_opcode.c (revision 902d39a3)
1 /*
2    +----------------------------------------------------------------------+
3    | Zend Engine                                                          |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 1998-2018 Zend Technologies Ltd. (http://www.zend.com) |
6    +----------------------------------------------------------------------+
7    | This source file is subject to version 2.00 of the Zend 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.zend.com/license/2_00.txt.                                |
11    | If you did not receive a copy of the Zend license and are unable to  |
12    | obtain it through the world-wide-web, please send a note to          |
13    | license@zend.com so we can mail you a copy immediately.              |
14    +----------------------------------------------------------------------+
15    | Authors: Andi Gutmans <andi@zend.com>                                |
16    |          Zeev Suraski <zeev@zend.com>                                |
17    |          Dmitry Stogov <dmitry@zend.com>                             |
18    +----------------------------------------------------------------------+
19 */
20 
21 /* $Id$ */
22 
23 #include <stdio.h>
24 
25 #include "zend.h"
26 #include "zend_alloc.h"
27 #include "zend_compile.h"
28 #include "zend_extensions.h"
29 #include "zend_API.h"
30 
31 #include "zend_vm.h"
32 
zend_extension_op_array_ctor_handler(zend_extension * extension,zend_op_array * op_array)33 static void zend_extension_op_array_ctor_handler(zend_extension *extension, zend_op_array *op_array)
34 {
35 	if (extension->op_array_ctor) {
36 		extension->op_array_ctor(op_array);
37 	}
38 }
39 
zend_extension_op_array_dtor_handler(zend_extension * extension,zend_op_array * op_array)40 static void zend_extension_op_array_dtor_handler(zend_extension *extension, zend_op_array *op_array)
41 {
42 	if (extension->op_array_dtor) {
43 		extension->op_array_dtor(op_array);
44 	}
45 }
46 
op_array_alloc_ops(zend_op_array * op_array,uint32_t size)47 static void op_array_alloc_ops(zend_op_array *op_array, uint32_t size)
48 {
49 	op_array->opcodes = erealloc(op_array->opcodes, size * sizeof(zend_op));
50 }
51 
init_op_array(zend_op_array * op_array,zend_uchar type,int initial_ops_size)52 void init_op_array(zend_op_array *op_array, zend_uchar type, int initial_ops_size)
53 {
54 	op_array->type = type;
55 	op_array->arg_flags[0] = 0;
56 	op_array->arg_flags[1] = 0;
57 	op_array->arg_flags[2] = 0;
58 
59 	op_array->refcount = (uint32_t *) emalloc(sizeof(uint32_t));
60 	*op_array->refcount = 1;
61 	op_array->last = 0;
62 	op_array->opcodes = NULL;
63 	op_array_alloc_ops(op_array, initial_ops_size);
64 
65 	op_array->last_var = 0;
66 	op_array->vars = NULL;
67 
68 	op_array->T = 0;
69 
70 	op_array->function_name = NULL;
71 	op_array->filename = zend_get_compiled_filename();
72 	op_array->doc_comment = NULL;
73 
74 	op_array->arg_info = NULL;
75 	op_array->num_args = 0;
76 	op_array->required_num_args = 0;
77 
78 	op_array->scope = NULL;
79 	op_array->prototype = NULL;
80 
81 	op_array->live_range = NULL;
82 	op_array->try_catch_array = NULL;
83 	op_array->last_live_range = 0;
84 
85 	op_array->static_variables = NULL;
86 	op_array->last_try_catch = 0;
87 
88 	op_array->fn_flags = 0;
89 
90 	op_array->early_binding = -1;
91 
92 	op_array->last_literal = 0;
93 	op_array->literals = NULL;
94 
95 	op_array->run_time_cache = NULL;
96 	op_array->cache_size = 0;
97 
98 	memset(op_array->reserved, 0, ZEND_MAX_RESERVED_RESOURCES * sizeof(void*));
99 
100 	if (zend_extension_flags & ZEND_EXTENSIONS_HAVE_OP_ARRAY_CTOR) {
101 		zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_op_array_ctor_handler, op_array);
102 	}
103 }
104 
destroy_zend_function(zend_function * function)105 ZEND_API void destroy_zend_function(zend_function *function)
106 {
107 	if (function->type == ZEND_USER_FUNCTION) {
108 		destroy_op_array(&function->op_array);
109 	} else {
110 		ZEND_ASSERT(function->type == ZEND_INTERNAL_FUNCTION);
111 		ZEND_ASSERT(function->common.function_name);
112 		zend_string_release(function->common.function_name);
113 
114 		if (function->common.arg_info &&
115 		    (function->common.fn_flags & (ZEND_ACC_HAS_RETURN_TYPE|ZEND_ACC_HAS_TYPE_HINTS))) {
116 			uint32_t i;
117 			uint32_t num_args = function->common.num_args + 1;
118 			zend_arg_info *arg_info = function->common.arg_info - 1;
119 
120 			if (function->common.fn_flags & ZEND_ACC_VARIADIC) {
121 				num_args++;
122 			}
123 			for (i = 0 ; i < num_args; i++) {
124 				if (ZEND_TYPE_IS_CLASS(arg_info[i].type)) {
125 					zend_string_release(ZEND_TYPE_NAME(arg_info[i].type));
126 				}
127 			}
128 			free(arg_info);
129 		}
130 	}
131 }
132 
zend_function_dtor(zval * zv)133 ZEND_API void zend_function_dtor(zval *zv)
134 {
135 	zend_function *function = Z_PTR_P(zv);
136 
137 	if (function->type == ZEND_USER_FUNCTION) {
138 		ZEND_ASSERT(function->common.function_name);
139 		destroy_op_array(&function->op_array);
140 		/* op_arrays are allocated on arena, so we don't have to free them */
141 	} else {
142 		ZEND_ASSERT(function->type == ZEND_INTERNAL_FUNCTION);
143 		ZEND_ASSERT(function->common.function_name);
144 		zend_string_release(function->common.function_name);
145 #ifndef ZTS
146 		if ((function->common.fn_flags & (ZEND_ACC_HAS_RETURN_TYPE|ZEND_ACC_HAS_TYPE_HINTS)) &&
147 		    !function->common.scope && function->common.arg_info) {
148 
149 			uint32_t i;
150 			uint32_t num_args = function->common.num_args + 1;
151 			zend_arg_info *arg_info = function->common.arg_info - 1;
152 
153 			if (function->common.fn_flags & ZEND_ACC_VARIADIC) {
154 				num_args++;
155 			}
156 			for (i = 0 ; i < num_args; i++) {
157 				if (ZEND_TYPE_IS_CLASS(arg_info[i].type)) {
158 					zend_string_release(ZEND_TYPE_NAME(arg_info[i].type));
159 				}
160 			}
161 			free(arg_info);
162 		}
163 #endif
164 		if (!(function->common.fn_flags & ZEND_ACC_ARENA_ALLOCATED)) {
165 			pefree(function, 1);
166 		}
167 	}
168 }
169 
zend_cleanup_internal_class_data(zend_class_entry * ce)170 ZEND_API void zend_cleanup_internal_class_data(zend_class_entry *ce)
171 {
172 	if (CE_STATIC_MEMBERS(ce)) {
173 		zval *static_members = CE_STATIC_MEMBERS(ce);
174 		zval *p = static_members;
175 		zval *end = p + ce->default_static_members_count;
176 
177 #ifdef ZTS
178 		CG(static_members_table)[(zend_intptr_t)(ce->static_members_table)] = NULL;
179 #else
180 		ce->static_members_table = NULL;
181 #endif
182 		ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
183 		while (p != end) {
184 			i_zval_ptr_dtor(p ZEND_FILE_LINE_CC);
185 			p++;
186 		}
187 		efree(static_members);
188 	}
189 }
190 
_destroy_zend_class_traits_info(zend_class_entry * ce)191 void _destroy_zend_class_traits_info(zend_class_entry *ce)
192 {
193 	if (ce->num_traits > 0 && ce->traits) {
194 		efree(ce->traits);
195 	}
196 
197 	if (ce->trait_aliases) {
198 		size_t i = 0;
199 		while (ce->trait_aliases[i]) {
200 			if (ce->trait_aliases[i]->trait_method) {
201 				if (ce->trait_aliases[i]->trait_method->method_name) {
202 	 				zend_string_release(ce->trait_aliases[i]->trait_method->method_name);
203 				}
204 				if (ce->trait_aliases[i]->trait_method->class_name) {
205 	 				zend_string_release(ce->trait_aliases[i]->trait_method->class_name);
206 				}
207 				efree(ce->trait_aliases[i]->trait_method);
208 			}
209 
210 			if (ce->trait_aliases[i]->alias) {
211 				zend_string_release(ce->trait_aliases[i]->alias);
212 			}
213 
214 			efree(ce->trait_aliases[i]);
215 			i++;
216 		}
217 
218 		efree(ce->trait_aliases);
219 	}
220 
221 	if (ce->trait_precedences) {
222 		size_t i = 0;
223 
224 		while (ce->trait_precedences[i]) {
225 			zend_string_release(ce->trait_precedences[i]->trait_method->method_name);
226 			zend_string_release(ce->trait_precedences[i]->trait_method->class_name);
227 			efree(ce->trait_precedences[i]->trait_method);
228 
229 			if (ce->trait_precedences[i]->exclude_from_classes) {
230 				size_t j = 0;
231 				zend_trait_precedence *cur_precedence = ce->trait_precedences[i];
232 				while (cur_precedence->exclude_from_classes[j].class_name) {
233 					zend_string_release(cur_precedence->exclude_from_classes[j].class_name);
234 					j++;
235 				}
236 				efree(ce->trait_precedences[i]->exclude_from_classes);
237 			}
238 			efree(ce->trait_precedences[i]);
239 			i++;
240 		}
241 		efree(ce->trait_precedences);
242 	}
243 }
244 
destroy_zend_class(zval * zv)245 ZEND_API void destroy_zend_class(zval *zv)
246 {
247 	zend_property_info *prop_info;
248 	zend_class_entry *ce = Z_PTR_P(zv);
249 #ifndef ZTS
250 	zend_function *fn;
251 #endif
252 
253 	if (--ce->refcount > 0) {
254 		return;
255 	}
256 	switch (ce->type) {
257 		case ZEND_USER_CLASS:
258 			if (ce->default_properties_table) {
259 				zval *p = ce->default_properties_table;
260 				zval *end = p + ce->default_properties_count;
261 
262 				while (p != end) {
263 					i_zval_ptr_dtor(p ZEND_FILE_LINE_CC);
264 					p++;
265 				}
266 				efree(ce->default_properties_table);
267 			}
268 			if (ce->default_static_members_table) {
269 				zval *p = ce->default_static_members_table;
270 				zval *end = p + ce->default_static_members_count;
271 
272 				while (p != end) {
273 					i_zval_ptr_dtor(p ZEND_FILE_LINE_CC);
274 					p++;
275 				}
276 				efree(ce->default_static_members_table);
277 			}
278 			ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop_info) {
279 				if (prop_info->ce == ce || (prop_info->flags & ZEND_ACC_SHADOW)) {
280 					zend_string_release(prop_info->name);
281 					if (prop_info->doc_comment) {
282 						zend_string_release(prop_info->doc_comment);
283 					}
284 				}
285 			} ZEND_HASH_FOREACH_END();
286 			zend_hash_destroy(&ce->properties_info);
287 			zend_string_release(ce->name);
288 			zend_hash_destroy(&ce->function_table);
289 			if (zend_hash_num_elements(&ce->constants_table)) {
290 				zend_class_constant *c;
291 
292 				ZEND_HASH_FOREACH_PTR(&ce->constants_table, c) {
293 					if (c->ce == ce) {
294 						zval_ptr_dtor(&c->value);
295 						if (c->doc_comment) {
296 							zend_string_release(c->doc_comment);
297 						}
298 					}
299 				} ZEND_HASH_FOREACH_END();
300 			}
301 			zend_hash_destroy(&ce->constants_table);
302 			if (ce->num_interfaces > 0 && ce->interfaces) {
303 				efree(ce->interfaces);
304 			}
305 			if (ce->info.user.doc_comment) {
306 				zend_string_release(ce->info.user.doc_comment);
307 			}
308 
309 			_destroy_zend_class_traits_info(ce);
310 
311 			break;
312 		case ZEND_INTERNAL_CLASS:
313 			if (ce->default_properties_table) {
314 				zval *p = ce->default_properties_table;
315 				zval *end = p + ce->default_properties_count;
316 
317 				while (p != end) {
318 					zval_internal_ptr_dtor(p);
319 					p++;
320 				}
321 				free(ce->default_properties_table);
322 			}
323 			if (ce->default_static_members_table) {
324 				zval *p = ce->default_static_members_table;
325 				zval *end = p + ce->default_static_members_count;
326 
327 				while (p != end) {
328 					zval_internal_ptr_dtor(p);
329 					p++;
330 				}
331 				free(ce->default_static_members_table);
332 			}
333 			zend_hash_destroy(&ce->properties_info);
334 			zend_string_release(ce->name);
335 #ifndef ZTS
336 			ZEND_HASH_FOREACH_PTR(&ce->function_table, fn) {
337 				if ((fn->common.fn_flags & (ZEND_ACC_HAS_RETURN_TYPE|ZEND_ACC_HAS_TYPE_HINTS)) &&
338 				    fn->common.scope == ce) {
339 					/* reset function scope to allow arg_info removing */
340 					fn->common.scope = NULL;
341 				}
342 			} ZEND_HASH_FOREACH_END();
343 #endif
344 			zend_hash_destroy(&ce->function_table);
345 			if (zend_hash_num_elements(&ce->constants_table)) {
346 				zend_class_constant *c;
347 
348 				ZEND_HASH_FOREACH_PTR(&ce->constants_table, c) {
349 					zval_internal_ptr_dtor(&c->value);
350 					if (c->doc_comment && c->ce == ce) {
351 						zend_string_release(c->doc_comment);
352 					}
353 				} ZEND_HASH_FOREACH_END();
354 				zend_hash_destroy(&ce->constants_table);
355 			}
356 			if (ce->num_interfaces > 0) {
357 				free(ce->interfaces);
358 			}
359 			free(ce);
360 			break;
361 	}
362 }
363 
zend_class_add_ref(zval * zv)364 void zend_class_add_ref(zval *zv)
365 {
366 	zend_class_entry *ce = Z_PTR_P(zv);
367 
368 	ce->refcount++;
369 }
370 
destroy_op_array(zend_op_array * op_array)371 ZEND_API void destroy_op_array(zend_op_array *op_array)
372 {
373 	zval *literal = op_array->literals;
374 	zval *end;
375 	uint32_t i;
376 
377 	if (op_array->static_variables &&
378 	    !(GC_FLAGS(op_array->static_variables) & IS_ARRAY_IMMUTABLE)) {
379 		if (--GC_REFCOUNT(op_array->static_variables) == 0) {
380 			zend_array_destroy(op_array->static_variables);
381 		}
382 	}
383 
384 	if (op_array->run_time_cache && !op_array->function_name) {
385 		efree(op_array->run_time_cache);
386 		op_array->run_time_cache = NULL;
387 	}
388 
389 	if (!op_array->refcount || --(*op_array->refcount) > 0) {
390 		return;
391 	}
392 
393 	efree_size(op_array->refcount, sizeof(*(op_array->refcount)));
394 
395 	if (op_array->vars) {
396 		i = op_array->last_var;
397 		while (i > 0) {
398 			i--;
399 			zend_string_release(op_array->vars[i]);
400 		}
401 		efree(op_array->vars);
402 	}
403 
404 	if (literal) {
405 	 	end = literal + op_array->last_literal;
406 	 	while (literal < end) {
407 			zval_ptr_dtor_nogc(literal);
408 			literal++;
409 		}
410 		efree(op_array->literals);
411 	}
412 	efree(op_array->opcodes);
413 
414 	if (op_array->function_name) {
415 		zend_string_release(op_array->function_name);
416 	}
417 	if (op_array->doc_comment) {
418 		zend_string_release(op_array->doc_comment);
419 	}
420 	if (op_array->live_range) {
421 		efree(op_array->live_range);
422 	}
423 	if (op_array->try_catch_array) {
424 		efree(op_array->try_catch_array);
425 	}
426 	if (zend_extension_flags & ZEND_EXTENSIONS_HAVE_OP_ARRAY_DTOR) {
427 		if (op_array->fn_flags & ZEND_ACC_DONE_PASS_TWO) {
428 			zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_op_array_dtor_handler, op_array);
429 		}
430 	}
431 	if (op_array->arg_info) {
432 		uint32_t num_args = op_array->num_args;
433 		zend_arg_info *arg_info = op_array->arg_info;
434 
435 		if (op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
436 			arg_info--;
437 			num_args++;
438 		}
439 		if (op_array->fn_flags & ZEND_ACC_VARIADIC) {
440 			num_args++;
441 		}
442 		for (i = 0 ; i < num_args; i++) {
443 			if (arg_info[i].name) {
444 				zend_string_release(arg_info[i].name);
445 			}
446 			if (ZEND_TYPE_IS_CLASS(arg_info[i].type)) {
447 				zend_string_release(ZEND_TYPE_NAME(arg_info[i].type));
448 			}
449 		}
450 		efree(arg_info);
451 	}
452 }
453 
init_op(zend_op * op)454 void init_op(zend_op *op)
455 {
456 	memset(op, 0, sizeof(zend_op));
457 	op->lineno = CG(zend_lineno);
458 	SET_UNUSED(op->result);
459 }
460 
get_next_op(zend_op_array * op_array)461 zend_op *get_next_op(zend_op_array *op_array)
462 {
463 	uint32_t next_op_num = op_array->last++;
464 	zend_op *next_op;
465 
466 	if (next_op_num >= CG(context).opcodes_size) {
467 		CG(context).opcodes_size *= 4;
468 		op_array_alloc_ops(op_array, CG(context).opcodes_size);
469 	}
470 
471 	next_op = &(op_array->opcodes[next_op_num]);
472 
473 	init_op(next_op);
474 
475 	return next_op;
476 }
477 
get_next_op_number(zend_op_array * op_array)478 uint32_t get_next_op_number(zend_op_array *op_array)
479 {
480 	return op_array->last;
481 }
482 
get_next_brk_cont_element(void)483 zend_brk_cont_element *get_next_brk_cont_element(void)
484 {
485 	CG(context).last_brk_cont++;
486 	CG(context).brk_cont_array = erealloc(CG(context).brk_cont_array, sizeof(zend_brk_cont_element) * CG(context).last_brk_cont);
487 	return &CG(context).brk_cont_array[CG(context).last_brk_cont-1];
488 }
489 
zend_update_extended_info(zend_op_array * op_array)490 static void zend_update_extended_info(zend_op_array *op_array)
491 {
492 	zend_op *opline = op_array->opcodes, *end=opline+op_array->last;
493 
494 	while (opline<end) {
495 		if (opline->opcode == ZEND_EXT_STMT) {
496 			if (opline+1<end) {
497 				if ((opline+1)->opcode == ZEND_EXT_STMT) {
498 					opline->opcode = ZEND_NOP;
499 					opline++;
500 					continue;
501 				}
502 				if (opline+1<end) {
503 					opline->lineno = (opline+1)->lineno;
504 				}
505 			} else {
506 				opline->opcode = ZEND_NOP;
507 			}
508 		}
509 		opline++;
510 	}
511 }
512 
zend_extension_op_array_handler(zend_extension * extension,zend_op_array * op_array)513 static void zend_extension_op_array_handler(zend_extension *extension, zend_op_array *op_array)
514 {
515 	if (extension->op_array_handler) {
516 		extension->op_array_handler(op_array);
517 	}
518 }
519 
zend_check_finally_breakout(zend_op_array * op_array,uint32_t op_num,uint32_t dst_num)520 static void zend_check_finally_breakout(zend_op_array *op_array, uint32_t op_num, uint32_t dst_num)
521 {
522 	int i;
523 
524 	for (i = 0; i < op_array->last_try_catch; i++) {
525 		if ((op_num < op_array->try_catch_array[i].finally_op ||
526 					op_num >= op_array->try_catch_array[i].finally_end)
527 				&& (dst_num >= op_array->try_catch_array[i].finally_op &&
528 					 dst_num <= op_array->try_catch_array[i].finally_end)) {
529 			CG(in_compilation) = 1;
530 			CG(active_op_array) = op_array;
531 			CG(zend_lineno) = op_array->opcodes[op_num].lineno;
532 			zend_error_noreturn(E_COMPILE_ERROR, "jump into a finally block is disallowed");
533 		} else if ((op_num >= op_array->try_catch_array[i].finally_op
534 					&& op_num <= op_array->try_catch_array[i].finally_end)
535 				&& (dst_num > op_array->try_catch_array[i].finally_end
536 					|| dst_num < op_array->try_catch_array[i].finally_op)) {
537 			CG(in_compilation) = 1;
538 			CG(active_op_array) = op_array;
539 			CG(zend_lineno) = op_array->opcodes[op_num].lineno;
540 			zend_error_noreturn(E_COMPILE_ERROR, "jump out of a finally block is disallowed");
541 		}
542 	}
543 }
544 
zend_get_brk_cont_target(const zend_op_array * op_array,const zend_op * opline)545 static uint32_t zend_get_brk_cont_target(const zend_op_array *op_array, const zend_op *opline) {
546 	int nest_levels = opline->op2.num;
547 	int array_offset = opline->op1.num;
548 	zend_brk_cont_element *jmp_to;
549 	do {
550 		jmp_to = &CG(context).brk_cont_array[array_offset];
551 		if (nest_levels > 1) {
552 			array_offset = jmp_to->parent;
553 		}
554 	} while (--nest_levels > 0);
555 
556 	return opline->opcode == ZEND_BRK ? jmp_to->brk : jmp_to->cont;
557 }
558 
pass_two(zend_op_array * op_array)559 ZEND_API int pass_two(zend_op_array *op_array)
560 {
561 	zend_op *opline, *end;
562 
563 	if (!ZEND_USER_CODE(op_array->type)) {
564 		return 0;
565 	}
566 	if (CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO) {
567 		zend_update_extended_info(op_array);
568 	}
569 	if (CG(compiler_options) & ZEND_COMPILE_HANDLE_OP_ARRAY) {
570 		if (zend_extension_flags & ZEND_EXTENSIONS_HAVE_OP_ARRAY_HANDLER) {
571 			zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_op_array_handler, op_array);
572 		}
573 	}
574 
575 	if (CG(context).vars_size != op_array->last_var) {
576 		op_array->vars = (zend_string**) erealloc(op_array->vars, sizeof(zend_string*)*op_array->last_var);
577 		CG(context).vars_size = op_array->last_var;
578 	}
579 	if (CG(context).opcodes_size != op_array->last) {
580 		op_array->opcodes = (zend_op *) erealloc(op_array->opcodes, sizeof(zend_op)*op_array->last);
581 		CG(context).opcodes_size = op_array->last;
582 	}
583 	if (CG(context).literals_size != op_array->last_literal) {
584 		op_array->literals = (zval*)erealloc(op_array->literals, sizeof(zval) * op_array->last_literal);
585 		CG(context).literals_size = op_array->last_literal;
586 	}
587 	opline = op_array->opcodes;
588 	end = opline + op_array->last;
589 	while (opline < end) {
590 		switch (opline->opcode) {
591 			case ZEND_FAST_CALL:
592 				opline->op1.opline_num = op_array->try_catch_array[opline->op1.num].finally_op;
593 				ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, opline->op1);
594 				break;
595 			case ZEND_BRK:
596 			case ZEND_CONT:
597 				{
598 					uint32_t jmp_target = zend_get_brk_cont_target(op_array, opline);
599 
600 					if (op_array->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK) {
601 						zend_check_finally_breakout(op_array, opline - op_array->opcodes, jmp_target);
602 					}
603 					opline->opcode = ZEND_JMP;
604 					opline->op1.opline_num = jmp_target;
605 					opline->op2.num = 0;
606 					ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, opline->op1);
607 				}
608 				break;
609 			case ZEND_GOTO:
610 				zend_resolve_goto_label(op_array, opline);
611 				if (op_array->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK) {
612 					zend_check_finally_breakout(op_array, opline - op_array->opcodes, opline->op1.opline_num);
613 				}
614 				/* break omitted intentionally */
615 			case ZEND_JMP:
616 				ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, opline->op1);
617 				break;
618 			case ZEND_JMPZNZ:
619 				/* absolute index to relative offset */
620 				opline->extended_value = ZEND_OPLINE_NUM_TO_OFFSET(op_array, opline, opline->extended_value);
621 				/* break omitted intentionally */
622 			case ZEND_JMPZ:
623 			case ZEND_JMPNZ:
624 			case ZEND_JMPZ_EX:
625 			case ZEND_JMPNZ_EX:
626 			case ZEND_JMP_SET:
627 			case ZEND_COALESCE:
628 			case ZEND_FE_RESET_R:
629 			case ZEND_FE_RESET_RW:
630 				ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, opline->op2);
631 				break;
632 			case ZEND_ASSERT_CHECK:
633 			{
634 				/* If result of assert is unused, result of check is unused as well */
635 				zend_op *call = &op_array->opcodes[opline->op2.opline_num - 1];
636 				if (call->opcode == ZEND_EXT_FCALL_END) {
637 					call--;
638 				}
639 				if (call->result_type == IS_UNUSED) {
640 					opline->result_type = IS_UNUSED;
641 				}
642 				ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, opline->op2);
643 				break;
644 			}
645 			case ZEND_DECLARE_ANON_CLASS:
646 			case ZEND_DECLARE_ANON_INHERITED_CLASS:
647 			case ZEND_CATCH:
648 			case ZEND_FE_FETCH_R:
649 			case ZEND_FE_FETCH_RW:
650 				/* absolute index to relative offset */
651 				opline->extended_value = ZEND_OPLINE_NUM_TO_OFFSET(op_array, opline, opline->extended_value);
652 				break;
653 			case ZEND_RETURN:
654 			case ZEND_RETURN_BY_REF:
655 				if (op_array->fn_flags & ZEND_ACC_GENERATOR) {
656 					opline->opcode = ZEND_GENERATOR_RETURN;
657 				}
658 				break;
659 			case ZEND_SWITCH_LONG:
660 			case ZEND_SWITCH_STRING:
661 			{
662 				/* absolute indexes to relative offsets */
663 				HashTable *jumptable = Z_ARRVAL_P(CT_CONSTANT(opline->op2));
664 				zval *zv;
665 				ZEND_HASH_FOREACH_VAL(jumptable, zv) {
666 					Z_LVAL_P(zv) = ZEND_OPLINE_NUM_TO_OFFSET(op_array, opline, Z_LVAL_P(zv));
667 				} ZEND_HASH_FOREACH_END();
668 
669 				opline->extended_value = ZEND_OPLINE_NUM_TO_OFFSET(op_array, opline, opline->extended_value);
670 				break;
671 			}
672 		}
673 		if (opline->op1_type == IS_CONST) {
674 			ZEND_PASS_TWO_UPDATE_CONSTANT(op_array, opline->op1);
675 		} else if (opline->op1_type & (IS_VAR|IS_TMP_VAR)) {
676 			opline->op1.var = (uint32_t)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, op_array->last_var + opline->op1.var);
677 		}
678 		if (opline->op2_type == IS_CONST) {
679 			ZEND_PASS_TWO_UPDATE_CONSTANT(op_array, opline->op2);
680 		} else if (opline->op2_type & (IS_VAR|IS_TMP_VAR)) {
681 			opline->op2.var = (uint32_t)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, op_array->last_var + opline->op2.var);
682 		}
683 		if (opline->result_type & (IS_VAR|IS_TMP_VAR)) {
684 			opline->result.var = (uint32_t)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, op_array->last_var + opline->result.var);
685 		}
686 		ZEND_VM_SET_OPCODE_HANDLER(opline);
687 		opline++;
688 	}
689 
690 	if (op_array->live_range) {
691 		int i;
692 
693 		for (i = 0; i < op_array->last_live_range; i++) {
694 			op_array->live_range[i].var =
695 				(uint32_t)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, op_array->last_var + (op_array->live_range[i].var / sizeof(zval))) |
696 				(op_array->live_range[i].var & ZEND_LIVE_MASK);
697 		}
698 	}
699 
700 	op_array->fn_flags |= ZEND_ACC_DONE_PASS_TWO;
701 	return 0;
702 }
703 
get_unary_op(int opcode)704 ZEND_API unary_op_type get_unary_op(int opcode)
705 {
706 	switch (opcode) {
707 		case ZEND_BW_NOT:
708 			return (unary_op_type) bitwise_not_function;
709 		case ZEND_BOOL_NOT:
710 			return (unary_op_type) boolean_not_function;
711 		default:
712 			return (unary_op_type) NULL;
713 	}
714 }
715 
get_binary_op(int opcode)716 ZEND_API binary_op_type get_binary_op(int opcode)
717 {
718 	switch (opcode) {
719 		case ZEND_ADD:
720 		case ZEND_ASSIGN_ADD:
721 			return (binary_op_type) add_function;
722 		case ZEND_SUB:
723 		case ZEND_ASSIGN_SUB:
724 			return (binary_op_type) sub_function;
725 		case ZEND_MUL:
726 		case ZEND_ASSIGN_MUL:
727 			return (binary_op_type) mul_function;
728 		case ZEND_POW:
729 		case ZEND_ASSIGN_POW:
730 			return (binary_op_type) pow_function;
731 		case ZEND_DIV:
732 		case ZEND_ASSIGN_DIV:
733 			return (binary_op_type) div_function;
734 		case ZEND_MOD:
735 		case ZEND_ASSIGN_MOD:
736 			return (binary_op_type) mod_function;
737 		case ZEND_SL:
738 		case ZEND_ASSIGN_SL:
739 			return (binary_op_type) shift_left_function;
740 		case ZEND_SR:
741 		case ZEND_ASSIGN_SR:
742 			return (binary_op_type) shift_right_function;
743 		case ZEND_FAST_CONCAT:
744 		case ZEND_CONCAT:
745 		case ZEND_ASSIGN_CONCAT:
746 			return (binary_op_type) concat_function;
747 		case ZEND_IS_IDENTICAL:
748 			return (binary_op_type) is_identical_function;
749 		case ZEND_IS_NOT_IDENTICAL:
750 			return (binary_op_type) is_not_identical_function;
751 		case ZEND_IS_EQUAL:
752 		case ZEND_CASE:
753 			return (binary_op_type) is_equal_function;
754 		case ZEND_IS_NOT_EQUAL:
755 			return (binary_op_type) is_not_equal_function;
756 		case ZEND_IS_SMALLER:
757 			return (binary_op_type) is_smaller_function;
758 		case ZEND_IS_SMALLER_OR_EQUAL:
759 			return (binary_op_type) is_smaller_or_equal_function;
760 		case ZEND_SPACESHIP:
761 			return (binary_op_type) compare_function;
762 		case ZEND_BW_OR:
763 		case ZEND_ASSIGN_BW_OR:
764 			return (binary_op_type) bitwise_or_function;
765 		case ZEND_BW_AND:
766 		case ZEND_ASSIGN_BW_AND:
767 			return (binary_op_type) bitwise_and_function;
768 		case ZEND_BW_XOR:
769 		case ZEND_ASSIGN_BW_XOR:
770 			return (binary_op_type) bitwise_xor_function;
771 		case ZEND_BOOL_XOR:
772 			return (binary_op_type) boolean_xor_function;
773 		default:
774 			return (binary_op_type) NULL;
775 	}
776 }
777 
778 /*
779  * Local variables:
780  * tab-width: 4
781  * c-basic-offset: 4
782  * indent-tabs-mode: t
783  * End:
784  * vim600: sw=4 ts=4 fdm=marker
785  * vim<600: sw=4 ts=4
786  */
787