PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - Zend - zend_opcode.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 379 442 85.7 %
Date: 2016-06-25 Functions: 20 26 76.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | Zend Engine                                                          |
       4             :    +----------------------------------------------------------------------+
       5             :    | Copyright (c) 1998-2016 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             : 
      33           0 : static void zend_extension_op_array_ctor_handler(zend_extension *extension, zend_op_array *op_array)
      34             : {
      35           0 :         if (extension->op_array_ctor) {
      36           0 :                 extension->op_array_ctor(op_array);
      37             :         }
      38           0 : }
      39             : 
      40           0 : static void zend_extension_op_array_dtor_handler(zend_extension *extension, zend_op_array *op_array)
      41             : {
      42           0 :         if (extension->op_array_dtor) {
      43           0 :                 extension->op_array_dtor(op_array);
      44             :         }
      45           0 : }
      46             : 
      47       80056 : static void op_array_alloc_ops(zend_op_array *op_array, uint32_t size)
      48             : {
      49       80056 :         op_array->opcodes = erealloc(op_array->opcodes, size * sizeof(zend_op));
      50       80056 : }
      51             : 
      52       71228 : void init_op_array(zend_op_array *op_array, zend_uchar type, int initial_ops_size)
      53             : {
      54       71228 :         op_array->type = type;
      55       71228 :         op_array->arg_flags[0] = 0;
      56       71228 :         op_array->arg_flags[1] = 0;
      57       71228 :         op_array->arg_flags[2] = 0;
      58             : 
      59       71228 :         op_array->refcount = (uint32_t *) emalloc(sizeof(uint32_t));
      60       71228 :         *op_array->refcount = 1;
      61       71228 :         op_array->last = 0;
      62       71228 :         op_array->opcodes = NULL;
      63       71228 :         op_array_alloc_ops(op_array, initial_ops_size);
      64             : 
      65       71228 :         op_array->last_var = 0;
      66       71228 :         op_array->vars = NULL;
      67             : 
      68       71228 :         op_array->T = 0;
      69             : 
      70       71228 :         op_array->function_name = NULL;
      71       71228 :         op_array->filename = zend_get_compiled_filename();
      72       71228 :         op_array->doc_comment = NULL;
      73             : 
      74       71228 :         op_array->arg_info = NULL;
      75       71228 :         op_array->num_args = 0;
      76       71228 :         op_array->required_num_args = 0;
      77             : 
      78       71228 :         op_array->scope = NULL;
      79       71228 :         op_array->prototype = NULL;
      80             : 
      81       71228 :         op_array->live_range = NULL;
      82       71228 :         op_array->try_catch_array = NULL;
      83       71228 :         op_array->last_live_range = 0;
      84             : 
      85       71228 :         op_array->static_variables = NULL;
      86       71228 :         op_array->last_try_catch = 0;
      87             : 
      88       71228 :         op_array->this_var = -1;
      89             : 
      90       71228 :         op_array->fn_flags = 0;
      91             : 
      92       71228 :         op_array->early_binding = -1;
      93             : 
      94       71228 :         op_array->last_literal = 0;
      95       71228 :         op_array->literals = NULL;
      96             : 
      97       71228 :         op_array->run_time_cache = NULL;
      98       71228 :         op_array->cache_size = 0;
      99             : 
     100       71228 :         memset(op_array->reserved, 0, ZEND_MAX_RESERVED_RESOURCES * sizeof(void*));
     101             : 
     102       71228 :         if (zend_extension_flags & ZEND_EXTENSIONS_HAVE_OP_ARRAY_CTOR) {
     103           0 :                 zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_op_array_ctor_handler, op_array);
     104             :         }
     105       71228 : }
     106             : 
     107           4 : ZEND_API void destroy_zend_function(zend_function *function)
     108             : {
     109           4 :         if (function->type == ZEND_USER_FUNCTION) {
     110           4 :                 destroy_op_array(&function->op_array);
     111             :         } else {
     112             :                 ZEND_ASSERT(function->type == ZEND_INTERNAL_FUNCTION);
     113             :                 ZEND_ASSERT(function->common.function_name);
     114           0 :                 zend_string_release(function->common.function_name);
     115             :         }
     116           4 : }
     117             : 
     118   116839667 : ZEND_API void zend_function_dtor(zval *zv)
     119             : {
     120   116839667 :         zend_function *function = Z_PTR_P(zv);
     121             : 
     122   116839667 :         if (function->type == ZEND_USER_FUNCTION) {
     123             :                 ZEND_ASSERT(function->common.function_name);
     124       57470 :                 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   116782197 :                 zend_string_release(function->common.function_name);
     130   116782197 :                 if (!(function->common.fn_flags & ZEND_ACC_ARENA_ALLOCATED)) {
     131   116734987 :                         pefree(function, 1);
     132             :                 }
     133             :         }
     134   116839667 : }
     135             : 
     136       33938 : ZEND_API void zend_cleanup_op_array_data(zend_op_array *op_array)
     137             : {
     138       36177 :         if (op_array->static_variables &&
     139        2239 :             !(GC_FLAGS(op_array->static_variables) & IS_ARRAY_IMMUTABLE)) {
     140        2238 :                 zend_hash_clean(op_array->static_variables);
     141             :         }
     142       33938 : }
     143             : 
     144        9669 : 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        9669 :         if (ce->ce_flags & ZEND_HAS_STATIC_IN_METHODS) {
     150             :                 zend_function *func;
     151             : 
     152       23645 :                 ZEND_HASH_FOREACH_PTR(&ce->function_table, func) {
     153       11039 :                         if (func->type == ZEND_USER_FUNCTION) {
     154       11014 :                                 zend_cleanup_op_array_data((zend_op_array *) func);
     155             :                         }
     156             :                 } ZEND_HASH_FOREACH_END();
     157             :         }
     158        9669 :         if (ce->static_members_table) {
     159         355 :                 zval *static_members = ce->static_members_table;
     160         355 :                 zval *p = static_members;
     161         355 :                 zval *end = p + ce->default_static_members_count;
     162             : 
     163             : 
     164         355 :                 ce->default_static_members_count = 0;
     165         355 :                 ce->default_static_members_table = ce->static_members_table = NULL;
     166        1355 :                 while (p != end) {
     167             :                         i_zval_ptr_dtor(p ZEND_FILE_LINE_CC);
     168         645 :                         p++;
     169             :                 }
     170         353 :                 efree(static_members);
     171             :         }
     172        9667 : }
     173             : 
     174           0 : ZEND_API void zend_cleanup_internal_class_data(zend_class_entry *ce)
     175             : {
     176           0 :         if (CE_STATIC_MEMBERS(ce)) {
     177           0 :                 zval *static_members = CE_STATIC_MEMBERS(ce);
     178           0 :                 zval *p = static_members;
     179           0 :                 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           0 :                 ce->static_members_table = NULL;
     185             : #endif
     186           0 :                 ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
     187           0 :                 while (p != end) {
     188             :                         i_zval_ptr_dtor(p ZEND_FILE_LINE_CC);
     189           0 :                         p++;
     190             :                 }
     191           0 :                 efree(static_members);
     192             :         }
     193           0 : }
     194             : 
     195        7887 : void _destroy_zend_class_traits_info(zend_class_entry *ce)
     196             : {
     197        7887 :         if (ce->num_traits > 0 && ce->traits) {
     198         187 :                 efree(ce->traits);
     199             :         }
     200             : 
     201        7887 :         if (ce->trait_aliases) {
     202          48 :                 size_t i = 0;
     203         169 :                 while (ce->trait_aliases[i]) {
     204          73 :                         if (ce->trait_aliases[i]->trait_method) {
     205          73 :                                 if (ce->trait_aliases[i]->trait_method->method_name) {
     206          73 :                                         zend_string_release(ce->trait_aliases[i]->trait_method->method_name);
     207             :                                 }
     208          73 :                                 if (ce->trait_aliases[i]->trait_method->class_name) {
     209          31 :                                         zend_string_release(ce->trait_aliases[i]->trait_method->class_name);
     210             :                                 }
     211          73 :                                 efree(ce->trait_aliases[i]->trait_method);
     212             :                         }
     213             : 
     214          73 :                         if (ce->trait_aliases[i]->alias) {
     215          62 :                                 zend_string_release(ce->trait_aliases[i]->alias);
     216             :                         }
     217             : 
     218          73 :                         efree(ce->trait_aliases[i]);
     219          73 :                         i++;
     220             :                 }
     221             : 
     222          48 :                 efree(ce->trait_aliases);
     223             :         }
     224             : 
     225        7887 :         if (ce->trait_precedences) {
     226          11 :                 size_t i = 0;
     227             : 
     228          37 :                 while (ce->trait_precedences[i]) {
     229          15 :                         zend_string_release(ce->trait_precedences[i]->trait_method->method_name);
     230          15 :                         zend_string_release(ce->trait_precedences[i]->trait_method->class_name);
     231          15 :                         efree(ce->trait_precedences[i]->trait_method);
     232             : 
     233          15 :                         if (ce->trait_precedences[i]->exclude_from_classes) {
     234           4 :                                 size_t j = 0;
     235           4 :                                 zend_trait_precedence *cur_precedence = ce->trait_precedences[i];
     236          12 :                                 while (cur_precedence->exclude_from_classes[j].class_name) {
     237           4 :                                         zend_string_release(cur_precedence->exclude_from_classes[j].class_name);
     238           4 :                                         j++;
     239             :                                 }
     240           4 :                                 efree(ce->trait_precedences[i]->exclude_from_classes);
     241             :                         }
     242          15 :                         efree(ce->trait_precedences[i]);
     243          15 :                         i++;
     244             :                 }
     245          11 :                 efree(ce->trait_precedences);
     246             :         }
     247        7887 : }
     248             : 
     249     4381878 : ZEND_API void destroy_zend_class(zval *zv)
     250             : {
     251             :         zend_property_info *prop_info;
     252     4381878 :         zend_class_entry *ce = Z_PTR_P(zv);
     253             : 
     254     4381878 :         if (--ce->refcount > 0) {
     255        7752 :                 return;
     256             :         }
     257     4374126 :         switch (ce->type) {
     258             :                 case ZEND_USER_CLASS:
     259        7887 :                         if (ce->default_properties_table) {
     260        2318 :                                 zval *p = ce->default_properties_table;
     261        2318 :                                 zval *end = p + ce->default_properties_count;
     262             : 
     263       25252 :                                 while (p != end) {
     264             :                                         i_zval_ptr_dtor(p ZEND_FILE_LINE_CC);
     265       20616 :                                         p++;
     266             :                                 }
     267        2318 :                                 efree(ce->default_properties_table);
     268             :                         }
     269        7887 :                         if (ce->default_static_members_table) {
     270           0 :                                 zval *p = ce->default_static_members_table;
     271           0 :                                 zval *end = p + ce->default_static_members_count;
     272             : 
     273           0 :                                 while (p != end) {
     274             :                                         i_zval_ptr_dtor(p ZEND_FILE_LINE_CC);
     275           0 :                                         p++;
     276             :                                 }
     277           0 :                                 efree(ce->default_static_members_table);
     278             :                         }
     279       50025 :                         ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop_info) {
     280       21069 :                                 if (prop_info->ce == ce || (prop_info->flags & ZEND_ACC_SHADOW)) {
     281        2884 :                                         zend_string_release(prop_info->name);
     282        2884 :                                         if (prop_info->doc_comment) {
     283          55 :                                                 zend_string_release(prop_info->doc_comment);
     284             :                                         }
     285             :                                 }
     286             :                         } ZEND_HASH_FOREACH_END();
     287        7887 :                         zend_hash_destroy(&ce->properties_info);
     288        7887 :                         zend_string_release(ce->name);
     289        7887 :                         zend_hash_destroy(&ce->function_table);
     290        7887 :                         if (zend_hash_num_elements(&ce->constants_table)) {
     291             :                                 zend_class_constant *c;
     292             : 
     293       14476 :                                 ZEND_HASH_FOREACH_PTR(&ce->constants_table, c) {
     294        7009 :                                         if (c->ce == ce) {
     295         356 :                                                 zval_ptr_dtor(&c->value);
     296         356 :                                                 if (c->doc_comment) {
     297           8 :                                                         zend_string_release(c->doc_comment);
     298             :                                                 }
     299             :                                         }
     300             :                                 } ZEND_HASH_FOREACH_END();
     301         458 :                                 zend_hash_destroy(&ce->constants_table);
     302             :                         }
     303        7887 :                         if (ce->num_interfaces > 0 && ce->interfaces) {
     304         688 :                                 efree(ce->interfaces);
     305             :                         }
     306        7887 :                         if (ce->info.user.doc_comment) {
     307          71 :                                 zend_string_release(ce->info.user.doc_comment);
     308             :                         }
     309             : 
     310        7887 :                         _destroy_zend_class_traits_info(ce);
     311             : 
     312        7887 :                         break;
     313             :                 case ZEND_INTERNAL_CLASS:
     314     4366239 :                         if (ce->default_properties_table) {
     315     1153773 :                                 zval *p = ce->default_properties_table;
     316     1153773 :                                 zval *end = p + ce->default_properties_count;
     317             : 
     318     8596740 :                                 while (p != end) {
     319     6289194 :                                         zval_internal_ptr_dtor(p);
     320     6289194 :                                         p++;
     321             :                                 }
     322     1153773 :                                 free(ce->default_properties_table);
     323             :                         }
     324     4366239 :                         if (ce->default_static_members_table) {
     325           0 :                                 zval *p = ce->default_static_members_table;
     326           0 :                                 zval *end = p + ce->default_static_members_count;
     327             : 
     328           0 :                                 while (p != end) {
     329           0 :                                         zval_internal_ptr_dtor(p);
     330           0 :                                         p++;
     331             :                                 }
     332           0 :                                 free(ce->default_static_members_table);
     333             :                         }
     334     4366239 :                         zend_hash_destroy(&ce->properties_info);
     335     4366239 :                         zend_string_release(ce->name);
     336     4366239 :                         zend_hash_destroy(&ce->function_table);
     337     4366239 :                         if (zend_hash_num_elements(&ce->constants_table)) {
     338             :                                 zend_class_constant *c;
     339             : 
     340    54430938 :                                 ZEND_HASH_FOREACH_PTR(&ce->constants_table, c) {
     341    26672517 :                                         zval_internal_ptr_dtor(&c->value);
     342    26672517 :                                         if (c->doc_comment && c->ce == ce) {
     343           0 :                                                 zend_string_release(c->doc_comment);
     344             :                                         }
     345             :                                 } ZEND_HASH_FOREACH_END();
     346     1085904 :                                 zend_hash_destroy(&ce->constants_table);
     347             :                         }
     348     4366239 :                         if (ce->num_interfaces > 0) {
     349     2262300 :                                 free(ce->interfaces);
     350             :                         }
     351     4366239 :                         free(ce);
     352             :                         break;
     353             :         }
     354             : }
     355             : 
     356           0 : void zend_class_add_ref(zval *zv)
     357             : {
     358           0 :         zend_class_entry *ce = Z_PTR_P(zv);
     359             : 
     360           0 :         ce->refcount++;
     361           0 : }
     362             : 
     363       89342 : ZEND_API void destroy_op_array(zend_op_array *op_array)
     364             : {
     365       89342 :         zval *literal = op_array->literals;
     366             :         zval *end;
     367             :         uint32_t i;
     368             : 
     369       91717 :         if (op_array->static_variables &&
     370        2375 :             !(GC_FLAGS(op_array->static_variables) & IS_ARRAY_IMMUTABLE)) {
     371        2374 :                 if (--GC_REFCOUNT(op_array->static_variables) == 0) {
     372        2374 :                         zend_array_destroy(op_array->static_variables);
     373             :                 }
     374             :         }
     375             : 
     376       89342 :         if (op_array->run_time_cache && !op_array->function_name) {
     377       31061 :                 efree(op_array->run_time_cache);
     378       31061 :                 op_array->run_time_cache = NULL;
     379             :         }
     380             : 
     381       89342 :         if (!op_array->refcount || --(*op_array->refcount) > 0) {
     382       20419 :                 return;
     383             :         }
     384             : 
     385       68923 :         efree_size(op_array->refcount, sizeof(*(op_array->refcount)));
     386             : 
     387       68923 :         if (op_array->vars) {
     388       51256 :                 i = op_array->last_var;
     389      327632 :                 while (i > 0) {
     390      225120 :                         i--;
     391      225120 :                         zend_string_release(op_array->vars[i]);
     392             :                 }
     393       51256 :                 efree(op_array->vars);
     394             :         }
     395             : 
     396       68923 :         if (literal) {
     397       68875 :                 end = literal + op_array->last_literal;
     398     1296808 :                 while (literal < end) {
     399             :                         zval_ptr_dtor_nogc(literal);
     400     1159058 :                         literal++;
     401             :                 }
     402       68875 :                 efree(op_array->literals);
     403             :         }
     404       68923 :         efree(op_array->opcodes);
     405             : 
     406       68923 :         if (op_array->function_name) {
     407       38156 :                 zend_string_release(op_array->function_name);
     408             :         }
     409       68923 :         if (op_array->doc_comment) {
     410        2409 :                 zend_string_release(op_array->doc_comment);
     411             :         }
     412       68923 :         if (op_array->live_range) {
     413       16836 :                 efree(op_array->live_range);
     414             :         }
     415       68923 :         if (op_array->try_catch_array) {
     416        2002 :                 efree(op_array->try_catch_array);
     417             :         }
     418       68923 :         if (zend_extension_flags & ZEND_EXTENSIONS_HAVE_OP_ARRAY_DTOR) {
     419           0 :                 if (op_array->fn_flags & ZEND_ACC_DONE_PASS_TWO) {
     420           0 :                         zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_op_array_dtor_handler, op_array);
     421             :                 }
     422             :         }
     423       68923 :         if (op_array->arg_info) {
     424       28433 :                 uint32_t num_args = op_array->num_args;
     425       28433 :                 zend_arg_info *arg_info = op_array->arg_info;
     426             : 
     427       28433 :                 if (op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
     428         110 :                         arg_info--;
     429         110 :                         num_args++;
     430             :                 }
     431       28433 :                 if (op_array->fn_flags & ZEND_ACC_VARIADIC) {
     432          39 :                         num_args++;
     433             :                 }
     434      114525 :                 for (i = 0 ; i < num_args; i++) {
     435       86092 :                         if (arg_info[i].name) {
     436       85982 :                                 zend_string_release(arg_info[i].name);
     437             :                         }
     438       86092 :                         if (arg_info[i].class_name) {
     439         234 :                                 zend_string_release(arg_info[i].class_name);
     440             :                         }
     441             :                 }
     442       28433 :                 efree(arg_info);
     443             :         }
     444             : }
     445             : 
     446     2598996 : void init_op(zend_op *op)
     447             : {
     448     2598996 :         memset(op, 0, sizeof(zend_op));
     449     2598996 :         op->lineno = CG(zend_lineno);
     450     2598996 :         SET_UNUSED(op->result);
     451     2598996 : }
     452             : 
     453     2441933 : zend_op *get_next_op(zend_op_array *op_array)
     454             : {
     455     2441933 :         uint32_t next_op_num = op_array->last++;
     456             :         zend_op *next_op;
     457             : 
     458     2441933 :         if (next_op_num >= CG(context).opcodes_size) {
     459        8828 :                 CG(context).opcodes_size *= 4;
     460        8828 :                 op_array_alloc_ops(op_array, CG(context).opcodes_size);
     461             :         }
     462             : 
     463     2441933 :         next_op = &(op_array->opcodes[next_op_num]);
     464             : 
     465     2441933 :         init_op(next_op);
     466             : 
     467     2441933 :         return next_op;
     468             : }
     469             : 
     470      853259 : int get_next_op_number(zend_op_array *op_array)
     471             : {
     472      853259 :         return op_array->last;
     473             : }
     474             : 
     475       16497 : zend_brk_cont_element *get_next_brk_cont_element(void)
     476             : {
     477       16497 :         CG(context).last_brk_cont++;
     478       16497 :         CG(context).brk_cont_array = erealloc(CG(context).brk_cont_array, sizeof(zend_brk_cont_element) * CG(context).last_brk_cont);
     479       16497 :         return &CG(context).brk_cont_array[CG(context).last_brk_cont-1];
     480             : }
     481             : 
     482           0 : static void zend_update_extended_info(zend_op_array *op_array)
     483             : {
     484           0 :         zend_op *opline = op_array->opcodes, *end=opline+op_array->last;
     485             : 
     486           0 :         while (opline<end) {
     487           0 :                 if (opline->opcode == ZEND_EXT_STMT) {
     488           0 :                         if (opline+1<end) {
     489           0 :                                 if ((opline+1)->opcode == ZEND_EXT_STMT) {
     490           0 :                                         opline->opcode = ZEND_NOP;
     491           0 :                                         opline++;
     492           0 :                                         continue;
     493             :                                 }
     494           0 :                                 if (opline+1<end) {
     495           0 :                                         opline->lineno = (opline+1)->lineno;
     496             :                                 }
     497             :                         } else {
     498           0 :                                 opline->opcode = ZEND_NOP;
     499             :                         }
     500             :                 }
     501           0 :                 opline++;
     502             :         }
     503           0 : }
     504             : 
     505           0 : static void zend_extension_op_array_handler(zend_extension *extension, zend_op_array *op_array)
     506             : {
     507           0 :         if (extension->op_array_handler) {
     508           0 :                 extension->op_array_handler(op_array);
     509             :         }
     510           0 : }
     511             : 
     512          29 : static void zend_check_finally_breakout(zend_op_array *op_array, uint32_t op_num, uint32_t dst_num)
     513             : {
     514             :         int i;
     515             : 
     516          85 :         for (i = 0; i < op_array->last_try_catch; i++) {
     517         177 :                 if ((op_num < op_array->try_catch_array[i].finally_op ||
     518          27 :                                         op_num >= op_array->try_catch_array[i].finally_end)
     519          52 :                                 && (dst_num >= op_array->try_catch_array[i].finally_op &&
     520          35 :                                          dst_num <= op_array->try_catch_array[i].finally_end)) {
     521           3 :                         CG(in_compilation) = 1;
     522           3 :                         CG(active_op_array) = op_array;
     523           3 :                         CG(zend_lineno) = op_array->opcodes[op_num].lineno;
     524           3 :                         zend_error_noreturn(E_COMPILE_ERROR, "jump into a finally block is disallowed");
     525         165 :                 } else if ((op_num >= op_array->try_catch_array[i].finally_op
     526          86 :                                         && op_num <= op_array->try_catch_array[i].finally_end)
     527          11 :                                 && (dst_num > op_array->try_catch_array[i].finally_end
     528          19 :                                         || dst_num < op_array->try_catch_array[i].finally_op)) {
     529           4 :                         CG(in_compilation) = 1;
     530           4 :                         CG(active_op_array) = op_array;
     531           4 :                         CG(zend_lineno) = op_array->opcodes[op_num].lineno;
     532           4 :                         zend_error_noreturn(E_COMPILE_ERROR, "jump out of a finally block is disallowed");
     533             :                 }
     534             :         }
     535          22 : }
     536             : 
     537         150 : static void zend_resolve_fast_call(zend_op_array *op_array, uint32_t op_num)
     538             : {
     539             :         int i;
     540         150 :         uint32_t finally_num = (uint32_t)-1;
     541             : 
     542         506 :         for (i = 0; i < op_array->last_try_catch; i++) {
     543         824 :                 if (op_num >= op_array->try_catch_array[i].finally_op
     544         468 :                                 && op_num < op_array->try_catch_array[i].finally_end) {
     545          20 :                         finally_num = i;
     546             :                 }
     547             :         }
     548             : 
     549         150 :         if (finally_num != (uint32_t)-1) {
     550             :                 /* Must be ZEND_FAST_CALL */
     551             :                 ZEND_ASSERT(op_array->opcodes[op_array->try_catch_array[finally_num].finally_op - 2].opcode == ZEND_FAST_CALL);
     552          13 :                 op_array->opcodes[op_num].extended_value = ZEND_FAST_CALL_FROM_FINALLY;
     553          13 :                 op_array->opcodes[op_num].op2.num = finally_num;
     554             :         }
     555         150 : }
     556             : 
     557          99 : static void zend_resolve_finally_ret(zend_op_array *op_array, uint32_t op_num)
     558             : {
     559             :         int i;
     560          99 :         uint32_t finally_num = (uint32_t)-1;
     561          99 :         uint32_t catch_num = (uint32_t)-1;
     562             : 
     563         319 :         for (i = 0; i < op_array->last_try_catch; i++) {
     564         229 :                 if (op_array->try_catch_array[i].try_op > op_num) {
     565           9 :                         break;
     566             :                 }
     567         220 :                 if (op_num < op_array->try_catch_array[i].finally_op) {
     568          29 :                         finally_num = i;
     569             :                 }
     570         220 :                 if (op_num < op_array->try_catch_array[i].catch_op) {
     571          25 :                         catch_num = i;
     572             :                 }
     573             :         }
     574             : 
     575         126 :         if (finally_num != (uint32_t)-1 &&
     576             :             (catch_num == (uint32_t)-1 ||
     577          34 :              op_array->try_catch_array[catch_num].catch_op >=
     578          17 :              op_array->try_catch_array[finally_num].finally_op)) {
     579             :                 /* in case of unhandled exception return to upward finally block */
     580          10 :                 op_array->opcodes[op_num].extended_value = ZEND_FAST_RET_TO_FINALLY;
     581          10 :                 op_array->opcodes[op_num].op2.num = finally_num;
     582          89 :         } else if (catch_num != (uint32_t)-1) {
     583             :                 /* in case of unhandled exception return to upward catch block */
     584          20 :                 op_array->opcodes[op_num].extended_value = ZEND_FAST_RET_TO_CATCH;
     585          20 :                 op_array->opcodes[op_num].op2.num = catch_num;
     586             :         }
     587          99 : }
     588             : 
     589        2187 : static uint32_t zend_get_brk_cont_target(const zend_op_array *op_array, const zend_op *opline) {
     590        2187 :         int nest_levels = opline->op2.num;
     591        2187 :         int array_offset = opline->op1.num;
     592             :         zend_brk_cont_element *jmp_to;
     593             :         do {
     594        2213 :                 jmp_to = &CG(context).brk_cont_array[array_offset];
     595        2213 :                 if (nest_levels > 1) {
     596          26 :                         array_offset = jmp_to->parent;
     597             :                 }
     598        2213 :         } while (--nest_levels > 0);
     599             : 
     600        2187 :         return opline->opcode == ZEND_BRK ? jmp_to->brk : jmp_to->cont;
     601             : }
     602             : 
     603       70925 : ZEND_API int pass_two(zend_op_array *op_array)
     604             : {
     605             :         zend_op *opline, *end;
     606             : 
     607       70925 :         if (!ZEND_USER_CODE(op_array->type)) {
     608           0 :                 return 0;
     609             :         }
     610       70925 :         if (CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO) {
     611           0 :                 zend_update_extended_info(op_array);
     612             :         }
     613       70925 :         if (CG(compiler_options) & ZEND_COMPILE_HANDLE_OP_ARRAY) {
     614       70700 :                 if (zend_extension_flags & ZEND_EXTENSIONS_HAVE_OP_ARRAY_HANDLER) {
     615           0 :                         zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_op_array_handler, op_array);
     616             :                 }
     617             :         }
     618             : 
     619       70925 :         if (CG(context).vars_size != op_array->last_var) {
     620       51836 :                 op_array->vars = (zend_string**) erealloc(op_array->vars, sizeof(zend_string*)*op_array->last_var);
     621       51836 :                 CG(context).vars_size = op_array->last_var;
     622             :         }
     623       70925 :         if (CG(context).opcodes_size != op_array->last) {
     624       70758 :                 op_array->opcodes = (zend_op *) erealloc(op_array->opcodes, sizeof(zend_op)*op_array->last);
     625       70758 :                 CG(context).opcodes_size = op_array->last;
     626             :         }
     627       70925 :         if (CG(context).literals_size != op_array->last_literal) {
     628       68808 :                 op_array->literals = (zval*)erealloc(op_array->literals, sizeof(zval) * op_array->last_literal);
     629       68808 :                 CG(context).literals_size = op_array->last_literal;
     630             :         }
     631       70925 :         opline = op_array->opcodes;
     632       70925 :         end = opline + op_array->last;
     633     2583261 :         while (opline < end) {
     634     2441423 :                 switch (opline->opcode) {
     635             :                         case ZEND_FAST_CALL:
     636         150 :                                 opline->op1.opline_num = op_array->try_catch_array[opline->op1.num].finally_op;
     637         150 :                                 zend_resolve_fast_call(op_array, opline - op_array->opcodes);
     638         150 :                                 ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, opline->op1);
     639         150 :                                 break;
     640             :                         case ZEND_FAST_RET:
     641          99 :                                 zend_resolve_finally_ret(op_array, opline - op_array->opcodes);
     642          99 :                                 break;
     643             :                         case ZEND_BRK:
     644             :                         case ZEND_CONT:
     645             :                                 {
     646        2187 :                                         uint32_t jmp_target = zend_get_brk_cont_target(op_array, opline);
     647             : 
     648        2187 :                                         if (op_array->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK) {
     649          13 :                                                 zend_check_finally_breakout(op_array, opline - op_array->opcodes, jmp_target);
     650             :                                         }
     651        2185 :                                         opline->opcode = ZEND_JMP;
     652        2185 :                                         opline->op1.opline_num = jmp_target;
     653        2185 :                                         opline->op2.num = 0;
     654        2185 :                                         ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, opline->op1);
     655             :                                 }
     656        2185 :                                 break;
     657             :                         case ZEND_GOTO:
     658          43 :                                 zend_resolve_goto_label(op_array, opline);
     659          38 :                                 if (op_array->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK) {
     660          16 :                                         zend_check_finally_breakout(op_array, opline - op_array->opcodes, opline->op1.opline_num);
     661             :                                 }
     662             :                                 /* break omitted intentionally */
     663             :                         case ZEND_JMP:
     664       66669 :                                 ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, opline->op1);
     665       66669 :                                 break;
     666             :                         case ZEND_JMPZNZ:
     667             :                                 /* absolute index to relative offset */
     668           0 :                                 opline->extended_value = ZEND_OPLINE_NUM_TO_OFFSET(op_array, opline, opline->extended_value);
     669             :                                 /* break omitted intentionally */
     670             :                         case ZEND_JMPZ:
     671             :                         case ZEND_JMPNZ:
     672             :                         case ZEND_JMPZ_EX:
     673             :                         case ZEND_JMPNZ_EX:
     674             :                         case ZEND_JMP_SET:
     675             :                         case ZEND_COALESCE:
     676             :                         case ZEND_NEW:
     677             :                         case ZEND_FE_RESET_R:
     678             :                         case ZEND_FE_RESET_RW:
     679      149980 :                                 ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, opline->op2);
     680      149980 :                                 break;
     681             :                         case ZEND_ASSERT_CHECK:
     682             :                                 /* If result of assert is unused, result of check is unused as well */
     683         230 :                                 if (op_array->opcodes[opline->op2.opline_num - 1].result_type == IS_UNUSED) {
     684         190 :                                         opline->result_type = IS_UNUSED;
     685             :                                 }
     686         230 :                                 ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, opline->op2);
     687         230 :                                 break;
     688             :                         case ZEND_DECLARE_ANON_CLASS:
     689             :                         case ZEND_DECLARE_ANON_INHERITED_CLASS:
     690             :                         case ZEND_CATCH:
     691             :                         case ZEND_FE_FETCH_R:
     692             :                         case ZEND_FE_FETCH_RW:
     693             :                                 /* absolute index to relative offset */
     694       14226 :                                 opline->extended_value = ZEND_OPLINE_NUM_TO_OFFSET(op_array, opline, opline->extended_value);
     695       14226 :                                 break;
     696             :                         case ZEND_VERIFY_RETURN_TYPE:
     697         182 :                                 if (op_array->fn_flags & ZEND_ACC_GENERATOR) {
     698          12 :                                         if (opline->op1_type != IS_UNUSED) {
     699           1 :                                                 zend_op *ret = opline;
     700           1 :                                                 do ret++; while (ret->opcode != ZEND_RETURN);
     701             : 
     702           1 :                                                 ret->op1 = opline->op1;
     703           1 :                                                 ret->op1_type = opline->op1_type;
     704             :                                         }
     705             : 
     706          12 :                                         MAKE_NOP(opline);
     707             :                                 }
     708         182 :                                 break;
     709             :                         case ZEND_RETURN:
     710             :                         case ZEND_RETURN_BY_REF:
     711      115716 :                                 if (op_array->fn_flags & ZEND_ACC_GENERATOR) {
     712         209 :                                         opline->opcode = ZEND_GENERATOR_RETURN;
     713             :                                 }
     714             :                                 break;
     715             :                 }
     716     2441411 :                 if (opline->op1_type == IS_CONST) {
     717      472552 :                         ZEND_PASS_TWO_UPDATE_CONSTANT(op_array, opline->op1);
     718     1968859 :                 } else if (opline->op1_type & (IS_VAR|IS_TMP_VAR)) {
     719      551081 :                         opline->op1.var = (uint32_t)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, op_array->last_var + opline->op1.var);
     720             :                 }
     721     2441411 :                 if (opline->op2_type == IS_CONST) {
     722      611035 :                         ZEND_PASS_TWO_UPDATE_CONSTANT(op_array, opline->op2);
     723     1830376 :                 } else if (opline->op2_type & (IS_VAR|IS_TMP_VAR)) {
     724      132977 :                         opline->op2.var = (uint32_t)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, op_array->last_var + opline->op2.var);
     725             :                 }
     726     2441411 :                 if (opline->result_type & (IS_VAR|IS_TMP_VAR)) {
     727      736764 :                         opline->result.var = (uint32_t)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, op_array->last_var + opline->result.var);
     728             :                 }
     729     2441411 :                 ZEND_VM_SET_OPCODE_HANDLER(opline);
     730     2441411 :                 opline++;
     731             :         }
     732             : 
     733       70913 :         if (op_array->live_range) {
     734             :                 uint32_t i;
     735             : 
     736       62121 :                 for (i = 0; i < op_array->last_live_range; i++) {
     737       90112 :                         op_array->live_range[i].var =
     738       90112 :                                 (uint32_t)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, op_array->last_var + (op_array->live_range[i].var / sizeof(zval))) |
     739       45056 :                                 (op_array->live_range[i].var & ZEND_LIVE_MASK);
     740             :                 }
     741             :         }
     742             : 
     743       70913 :         op_array->fn_flags |= ZEND_ACC_DONE_PASS_TWO;
     744       70913 :         return 0;
     745             : }
     746             : 
     747         307 : ZEND_API unary_op_type get_unary_op(int opcode)
     748             : {
     749         307 :         switch (opcode) {
     750             :                 case ZEND_BW_NOT:
     751          84 :                         return (unary_op_type) bitwise_not_function;
     752             :                 case ZEND_BOOL_NOT:
     753         223 :                         return (unary_op_type) boolean_not_function;
     754             :                 default:
     755           0 :                         return (unary_op_type) NULL;
     756             :         }
     757             : }
     758             : 
     759        5067 : ZEND_API binary_op_type get_binary_op(int opcode)
     760             : {
     761        5067 :         switch (opcode) {
     762             :                 case ZEND_ADD:
     763             :                 case ZEND_ASSIGN_ADD:
     764         245 :                         return (binary_op_type) add_function;
     765             :                 case ZEND_SUB:
     766             :                 case ZEND_ASSIGN_SUB:
     767         202 :                         return (binary_op_type) sub_function;
     768             :                 case ZEND_MUL:
     769             :                 case ZEND_ASSIGN_MUL:
     770          79 :                         return (binary_op_type) mul_function;
     771             :                 case ZEND_POW:
     772           9 :                         return (binary_op_type) pow_function;
     773             :                 case ZEND_DIV:
     774             :                 case ZEND_ASSIGN_DIV:
     775          32 :                         return (binary_op_type) div_function;
     776             :                 case ZEND_MOD:
     777             :                 case ZEND_ASSIGN_MOD:
     778           6 :                         return (binary_op_type) mod_function;
     779             :                 case ZEND_SL:
     780             :                 case ZEND_ASSIGN_SL:
     781          33 :                         return (binary_op_type) shift_left_function;
     782             :                 case ZEND_SR:
     783             :                 case ZEND_ASSIGN_SR:
     784           3 :                         return (binary_op_type) shift_right_function;
     785             :                 case ZEND_FAST_CONCAT:
     786             :                 case ZEND_CONCAT:
     787             :                 case ZEND_ASSIGN_CONCAT:
     788        3282 :                         return (binary_op_type) concat_function;
     789             :                 case ZEND_IS_IDENTICAL:
     790           3 :                         return (binary_op_type) is_identical_function;
     791             :                 case ZEND_IS_NOT_IDENTICAL:
     792          19 :                         return (binary_op_type) is_not_identical_function;
     793             :                 case ZEND_IS_EQUAL:
     794          80 :                         return (binary_op_type) is_equal_function;
     795             :                 case ZEND_IS_NOT_EQUAL:
     796         407 :                         return (binary_op_type) is_not_equal_function;
     797             :                 case ZEND_IS_SMALLER:
     798          45 :                         return (binary_op_type) is_smaller_function;
     799             :                 case ZEND_IS_SMALLER_OR_EQUAL:
     800           1 :                         return (binary_op_type) is_smaller_or_equal_function;
     801             :                 case ZEND_SPACESHIP:
     802           3 :                         return (binary_op_type) compare_function;
     803             :                 case ZEND_BW_OR:
     804             :                 case ZEND_ASSIGN_BW_OR:
     805         527 :                         return (binary_op_type) bitwise_or_function;
     806             :                 case ZEND_BW_AND:
     807             :                 case ZEND_ASSIGN_BW_AND:
     808          80 :                         return (binary_op_type) bitwise_and_function;
     809             :                 case ZEND_BW_XOR:
     810             :                 case ZEND_ASSIGN_BW_XOR:
     811           9 :                         return (binary_op_type) bitwise_xor_function;
     812             :                 case ZEND_BOOL_XOR:
     813           2 :                         return (binary_op_type) boolean_xor_function;
     814             :                 default:
     815           0 :                         return (binary_op_type) NULL;
     816             :         }
     817             : }
     818             : 
     819             : /*
     820             :  * Local variables:
     821             :  * tab-width: 4
     822             :  * c-basic-offset: 4
     823             :  * indent-tabs-mode: t
     824             :  * End:
     825             :  */

Generated by: LCOV version 1.10

Generated at Sat, 25 Jun 2016 07:08:51 +0000 (19 hours ago)

Copyright © 2005-2016 The PHP Group
All rights reserved.