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