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