/* Build CFG, Step 4, Mark Reachable Basic Blocks */
zend_mark_reachable_blocks(op_array, cfg, 0);
+ cfg->dynamic = (flags & ZEND_FUNC_INDIRECT_VAR_ACCESS);
+
if (func_flags) {
*func_flags |= flags;
}
unsigned int split_at_live_ranges : 1;
unsigned int split_at_calls : 1;
unsigned int split_at_recv : 1;
+ unsigned int dynamic : 1; /* accesses varables by name */
} zend_cfg;
/* Build Flags */
/* Narrowing integer initialization to doubles */
zend_type_narrowing(op_array, script, ssa);
- for (j = 0; j < op_array->last_var; j++) {
- /* $php_errormsg and $http_response_header may be updated indirectly */
- if (zend_string_equals_literal(op_array->vars[j], "php_errormsg")) {
- int i;
- for (i = 0; i < ssa_vars_count; i++) {
- if (ssa->vars[i].var == j) {
- ssa_var_info[i].type |= MAY_BE_STRING | MAY_BE_RC1 | MAY_BE_RCN;
- }
- }
- } else if (zend_string_equals_literal(op_array->vars[j], "http_response_header")) {
- int i;
- for (i = 0; i < ssa_vars_count; i++) {
- if (ssa->vars[i].var == j) {
- ssa_var_info[i].type |= MAY_BE_ARRAY | MAY_BE_ARRAY_KEY_LONG | MAY_BE_ARRAY_OF_STRING | MAY_BE_RC1 | MAY_BE_RCN;
- }
+ for (j = 0; j < ssa_vars_count; j++) {
+ if (ssa->vars[j].alias) {
+ if (ssa->vars[j].alias == PHP_ERRORMSG_ALIAS) {
+ ssa_var_info[j].type |= MAY_BE_STRING | MAY_BE_RC1 | MAY_BE_RCN;
+ } else if (ssa->vars[j].alias == PHP_ERRORMSG_ALIAS) {
+ ssa_var_info[j].type |= MAY_BE_ARRAY | MAY_BE_ARRAY_KEY_LONG | MAY_BE_ARRAY_OF_STRING | MAY_BE_RC1 | MAY_BE_RCN;
+ } else {
+ ssa_var_info[j].type = MAY_BE_UNDEF | MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_REF | MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
}
}
}
}
}
+ /* Mark indirectly accessed variables */
+ for (i = 0; i < op_array->last_var; i++) {
+ if (ssa->cfg.dynamic) {
+ ssa_vars[i].alias = SYMTABLE_ALIAS;
+ } else if (zend_string_equals_literal(op_array->vars[i], "php_errormsg")) {
+ ssa_vars[i].alias = PHP_ERRORMSG_ALIAS;
+ } else if (zend_string_equals_literal(op_array->vars[i], "http_response_header")) {
+ ssa_vars[i].alias = HTTP_RESPONSE_HEADER_ALIAS;
+ }
+ }
+ for (i = op_array->last_var; i < ssa->vars_count; i++) {
+ if (ssa_vars[i].var < op_array->last_var) {
+ ssa_vars[i].alias = ssa_vars[ssa_vars[i].var].alias;
+ }
+ }
+
return SUCCESS;
}
/* }}} */
int res_use_chain;
} zend_ssa_op;
+typedef enum _zend_ssa_alias_kind {
+ NO_ALIAS,
+ SYMTABLE_ALIAS,
+ PHP_ERRORMSG_ALIAS,
+ HTTP_RESPONSE_HEADER_ALIAS
+} zend_ssa_alias_kind;
+
typedef struct _zend_ssa_var {
int var; /* original var number; op.var for CVs and following numbers for VARs and TMP_VARs */
int scc; /* strongly connected component */
zend_ssa_phi *sym_use_chain; /* uses of this value in Pi constaints */
unsigned int no_val : 1; /* value doesn't mater (used as op1 in ZEND_ASSIGN) */
unsigned int scc_entry : 1;
+ zend_ssa_alias_kind alias : 2; /* value may be changed indirectly */
} zend_ssa_var;
typedef struct _zend_ssa_var_info {