Browse Source

Improve handling of static member variables

PHP-5
Zeev Suraski 24 years ago
parent
commit
d22cc2f329
  1. 49
      Zend/zend_execute.c
  2. 76
      Zend/zend_object_handlers.c
  3. 5
      Zend/zend_object_handlers.h

49
Zend/zend_execute.c

@ -662,7 +662,7 @@ static void zend_fetch_var_address(zend_op *opline, temp_variable *Ts, int type
if (opline->op2.u.EA.type == ZEND_FETCH_STATIC_MEMBER) {
target_symbol_table = NULL;
retval = zend_get_static_property(T(opline->op2.u.var).EA.class_entry, Z_STRVAL_P(varname), Z_STRLEN_P(varname), type TSRMLS_CC);
retval = zend_std_get_static_property(T(opline->op2.u.var).EA.class_entry, Z_STRVAL_P(varname), Z_STRLEN_P(varname), 0 TSRMLS_CC);
} else {
target_symbol_table = zend_get_target_symbol_table(opline, Ts, type, varname TSRMLS_CC);
if (!target_symbol_table) {
@ -2502,7 +2502,7 @@ int zend_init_static_method_call_handler(ZEND_OPCODE_HANDLER_ARGS)
ce = EX_T(EX(opline)->op1.u.var).EA.class_entry;
EX(fbc) = zend_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
EX(calling_scope) = EX(fbc)->common.scope;
if (!is_const) {
@ -3451,23 +3451,26 @@ int zend_include_or_eval_handler(ZEND_OPCODE_HANDLER_ARGS)
int zend_unset_var_handler(ZEND_OPCODE_HANDLER_ARGS)
{
zval tmp, *variable;
zval tmp, *varname;
HashTable *target_symbol_table;
variable = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R);
varname = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R);
if (variable->type != IS_STRING) {
tmp = *variable;
if (varname->type != IS_STRING) {
tmp = *varname;
zval_copy_ctor(&tmp);
convert_to_string(&tmp);
variable = &tmp;
varname = &tmp;
}
target_symbol_table = zend_get_target_symbol_table(EX(opline), EX(Ts), BP_VAR_IS, variable TSRMLS_CC);
zend_hash_del(target_symbol_table, variable->value.str.val, variable->value.str.len+1);
if (EX(opline)->op2.u.EA.type == ZEND_FETCH_STATIC_MEMBER) {
zend_std_unset_static_property(EX_T(EX(opline)->op2.u.var).EA.class_entry, Z_STRVAL_P(varname), Z_STRLEN_P(varname) TSRMLS_CC);
} else {
target_symbol_table = zend_get_target_symbol_table(EX(opline), EX(Ts), BP_VAR_IS, varname TSRMLS_CC);
zend_hash_del(target_symbol_table, varname->value.str.val, varname->value.str.len+1);
}
if (variable == &tmp) {
if (varname == &tmp) {
zval_dtor(&tmp);
}
FREE_OP(EX(Ts), &EX(opline)->op1, EG(free_op1));
@ -3643,22 +3646,28 @@ int zend_jmp_no_ctor_handler(ZEND_OPCODE_HANDLER_ARGS)
int zend_isset_isempty_var_handler(ZEND_OPCODE_HANDLER_ARGS)
{
zval tmp, *variable = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R);
zval tmp, *varname = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R);
zval **value;
zend_bool isset = 1;
HashTable *target_symbol_table;
if (variable->type != IS_STRING) {
tmp = *variable;
if (varname->type != IS_STRING) {
tmp = *varname;
zval_copy_ctor(&tmp);
convert_to_string(&tmp);
variable = &tmp;
varname = &tmp;
}
target_symbol_table = zend_get_target_symbol_table(EX(opline), EX(Ts), BP_VAR_IS, variable TSRMLS_CC);
if (zend_hash_find(target_symbol_table, variable->value.str.val, variable->value.str.len+1, (void **) &value) == FAILURE) {
isset = 0;
if (EX(opline)->op2.u.EA.type == ZEND_FETCH_STATIC_MEMBER) {
value = zend_std_get_static_property(EX_T(EX(opline)->op2.u.var).EA.class_entry, Z_STRVAL_P(varname), Z_STRLEN_P(varname), 1 TSRMLS_CC);
if (!value) {
isset = 0;
}
} else {
target_symbol_table = zend_get_target_symbol_table(EX(opline), EX(Ts), BP_VAR_IS, varname TSRMLS_CC);
if (zend_hash_find(target_symbol_table, varname->value.str.val, varname->value.str.len+1, (void **) &value) == FAILURE) {
isset = 0;
}
}
EX_T(EX(opline)->result.u.var).tmp_var.type = IS_BOOL;
@ -3680,7 +3689,7 @@ int zend_isset_isempty_var_handler(ZEND_OPCODE_HANDLER_ARGS)
break;
}
if (variable == &tmp) {
if (varname == &tmp) {
zval_dtor(&tmp);
}
FREE_OP(EX(Ts), &EX(opline)->op1, EG(free_op1));

76
Zend/zend_object_handlers.c

@ -592,7 +592,7 @@ static union _zend_function *zend_std_get_method(zval *object, char *method_name
/* This is not (yet?) in the API, but it belongs in the built-in objects callbacks */
zend_function *zend_get_static_method(zend_class_entry *ce, char *function_name_strval, int function_name_strlen TSRMLS_DC)
zend_function *zend_std_get_static_method(zend_class_entry *ce, char *function_name_strval, int function_name_strlen TSRMLS_DC)
{
zend_function *fbc;
@ -623,7 +623,7 @@ zend_function *zend_get_static_method(zend_class_entry *ce, char *function_name_
}
zval **zend_get_static_property(zend_class_entry *ce, char *property_name, int property_name_len, int type TSRMLS_DC)
zval **zend_std_get_static_property(zend_class_entry *ce, char *property_name, int property_name_len, zend_bool silent TSRMLS_DC)
{
HashTable *statics_table;
zval **retval = NULL;
@ -631,64 +631,54 @@ zval **zend_get_static_property(zend_class_entry *ce, char *property_name, int p
zend_property_info *property_info;
zend_property_info std_property_info;
if(ce->type == ZEND_NAMESPACE) {
if (ce->type == ZEND_NAMESPACE) {
zend_hash_find(ce->static_members, property_name, property_name_len+1, (void **) &retval);
} else {
if (zend_hash_find(&ce->properties_info, property_name, property_name_len+1, (void **) &property_info)==FAILURE) {
std_property_info.flags = ZEND_ACC_PUBLIC;
std_property_info.name = property_name;
std_property_info.name_length = property_name_len;
std_property_info.h = zend_get_hash_value(std_property_info.name, std_property_info.name_length+1);
property_info = &std_property_info;
}
if (zend_hash_find(&ce->properties_info, property_name, property_name_len+1, (void **) &property_info)==FAILURE) {
std_property_info.flags = ZEND_ACC_PUBLIC;
std_property_info.name = property_name;
std_property_info.name_length = property_name_len;
std_property_info.h = zend_get_hash_value(std_property_info.name, std_property_info.name_length+1);
property_info = &std_property_info;
}
#if 1&&DEBUG_OBJECT_HANDLERS
zend_printf("Access type for %s::%s is %s\n", ce->name, property_name, zend_visibility_string(property_info->flags));
zend_printf("Access type for %s::%s is %s\n", ce->name, property_name, zend_visibility_string(property_info->flags));
#endif
if (!zend_verify_property_access(property_info, ce TSRMLS_CC)) {
zend_error(E_ERROR, "Cannot access %s property %s::$%s", zend_visibility_string(property_info->flags), ce->name, property_name);
}
if (!zend_verify_property_access(property_info, ce TSRMLS_CC)) {
zend_error(E_ERROR, "Cannot access %s property %s::$%s", zend_visibility_string(property_info->flags), ce->name, property_name);
}
while (tmp_ce) {
if (zend_hash_quick_find(tmp_ce->static_members, property_info->name, property_info->name_length+1, property_info->h, (void **) &retval)==SUCCESS) {
statics_table = tmp_ce->static_members;
break;
while (tmp_ce) {
if (zend_hash_quick_find(tmp_ce->static_members, property_info->name, property_info->name_length+1, property_info->h, (void **) &retval)==SUCCESS) {
statics_table = tmp_ce->static_members;
break;
}
tmp_ce = tmp_ce->parent;
}
tmp_ce = tmp_ce->parent;
}
}
if (!retval) {
switch (type) {
case BP_VAR_R:
zend_error(E_NOTICE,"Undefined variable: %s::$%s", ce->name, property_name);
/* break missing intentionally */
case BP_VAR_IS:
retval = &EG(uninitialized_zval_ptr);
break;
case BP_VAR_RW:
zend_error(E_NOTICE,"Undefined variable: %s::$%s", ce->name, property_name);
/* break missing intentionally */
case BP_VAR_W: {
zval *new_zval = &EG(uninitialized_zval);
if(ce->type != ZEND_NAMESPACE) {
new_zval->refcount++;
zend_hash_quick_update(ce->static_members, property_info->name, property_info->name_length+1, property_info->h, &new_zval, sizeof(zval *), (void **) &retval);
}
}
break;
EMPTY_SWITCH_DEFAULT_CASE()
if (silent) {
return NULL;
} else {
zend_error(E_ERROR, "Access to undeclared static property: %s::$%s", ce->name, property_name);
}
} else {
zval_update_constant(retval, (void *) 1 TSRMLS_CC);
}
zval_update_constant(retval, (void *) 1 TSRMLS_CC);
return retval;
}
zend_bool zend_std_unset_static_property(zend_class_entry *ce, char *property_name, int property_name_len TSRMLS_DC)
{
zend_error(E_ERROR, "Attempt to unset static property %s::$%s", ce->name, property_name);
return 0;
}
static union _zend_function *zend_std_get_constructor(zval *object TSRMLS_DC)
{
zend_object *zobj = Z_OBJ_P(object);

5
Zend/zend_object_handlers.h

@ -93,8 +93,9 @@ typedef struct _zend_object_handlers {
} zend_object_handlers;
extern zend_object_handlers std_object_handlers;
union _zend_function *zend_get_static_method(zend_class_entry *ce, char *function_name_strval, int function_name_strlen TSRMLS_DC);
zval **zend_get_static_property(zend_class_entry *ce, char *property_name, int property_name_len, int type TSRMLS_DC);
union _zend_function *zend_std_get_static_method(zend_class_entry *ce, char *function_name_strval, int function_name_strlen TSRMLS_DC);
zval **zend_std_get_static_property(zend_class_entry *ce, char *property_name, int property_name_len, zend_bool silent TSRMLS_DC);
zend_bool zend_std_unset_static_property(zend_class_entry *ce, char *property_name, int property_name_len TSRMLS_DC);
#define IS_ZEND_STD_OBJECT(z) ((z).type == IS_OBJECT && (Z_OBJ_HT((z))->get_class_entry != NULL))

Loading…
Cancel
Save