diff options
Diffstat (limited to 'ext/reflection/php_reflection.c')
| -rw-r--r-- | ext/reflection/php_reflection.c | 211 | 
1 files changed, 105 insertions, 106 deletions
diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index 315580615d..c1919afb5f 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -41,6 +41,15 @@  #include "zend_closures.h"  #include "zend_extensions.h" +#define reflection_update_property(object, name, value) do { \ +		zval *member; \ +		MAKE_STD_ZVAL(member); \ +		ZVAL_STRINGL(member, name, sizeof(name)-1, 1); \ +		zend_std_write_property(object, member, value, NULL TSRMLS_CC); \ +		Z_DELREF_P(value); \ +		zval_ptr_dtor(&member); \ +	} while (0) +  /* Class entry pointers */  PHPAPI zend_class_entry *reflector_ptr;  PHPAPI zend_class_entry *reflection_exception_ptr; @@ -296,7 +305,6 @@ static void reflection_free_objects_storage(void *object TSRMLS_DC)  static zend_object_value reflection_objects_new(zend_class_entry *class_type TSRMLS_DC)  { -	zval tmp;  	zend_object_value retval;  	reflection_object *intern; @@ -304,7 +312,7 @@ static zend_object_value reflection_objects_new(zend_class_entry *class_type TSR  	intern->zo.ce = class_type;  	zend_object_std_init(&intern->zo, class_type TSRMLS_CC); -	zend_hash_copy(intern->zo.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); +	object_properties_init(&intern->zo, class_type);  	retval.handle = zend_objects_store_put(intern, NULL, reflection_free_objects_storage, NULL TSRMLS_CC);  	retval.handlers = &reflection_object_handlers;  	return retval; @@ -1157,7 +1165,7 @@ PHPAPI void zend_reflection_class_factory(zend_class_entry *ce, zval *object TSR  	intern->ptr = ce;  	intern->ref_type = REF_TYPE_OTHER;  	intern->ce = ce; -	zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL); +	reflection_update_property(object, "name", name);  }  /* }}} */ @@ -1186,7 +1194,7 @@ static void reflection_extension_factory(zval *object, const char *name_str TSRM  	intern->ptr = module;  	intern->ref_type = REF_TYPE_OTHER;  	intern->ce = NULL; -	zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL); +	reflection_update_property(object, "name", name);  }  /* }}} */ @@ -1217,7 +1225,7 @@ static void reflection_parameter_factory(zend_function *fptr, zval *closure_obje  	intern->ref_type = REF_TYPE_PARAMETER;  	intern->ce = fptr->common.scope;  	intern->obj = closure_object; -	zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL); +	reflection_update_property(object, "name", name);  }  /* }}} */ @@ -1239,7 +1247,7 @@ static void reflection_function_factory(zend_function *function, zval *closure_o  	intern->ref_type = REF_TYPE_FUNCTION;  	intern->ce = NULL;  	intern->obj = closure_object; -	zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL); +	reflection_update_property(object, "name", name);  }  /* }}} */ @@ -1263,8 +1271,8 @@ static void reflection_method_factory(zend_class_entry *ce, zend_function *metho  	intern->ref_type = REF_TYPE_FUNCTION;  	intern->ce = ce;  	intern->obj = closure_object; -	zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL); -	zend_hash_update(Z_OBJPROP_P(object), "class", sizeof("class"), (void **) &classname, sizeof(zval *), NULL); +	reflection_update_property(object, "name", name); +	reflection_update_property(object, "class", classname);  }  /* }}} */ @@ -1310,8 +1318,8 @@ static void reflection_property_factory(zend_class_entry *ce, zend_property_info  	intern->ref_type = REF_TYPE_PROPERTY;  	intern->ce = ce;  	intern->ignore_visibility = 0; -	zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL); -	zend_hash_update(Z_OBJPROP_P(object), "class", sizeof("class"), (void **) &classname, sizeof(zval *), NULL); +	reflection_update_property(object, "name", name); +	reflection_update_property(object, "class", classname);  }  /* }}} */ @@ -1556,7 +1564,7 @@ ZEND_METHOD(reflection_function, __construct)  	MAKE_STD_ZVAL(name);  	ZVAL_STRING(name, fptr->common.function_name, 1); -	zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL); +	reflection_update_property(object, "name", name TSRMLS_CC);  	intern->ptr = fptr;  	intern->ref_type = REF_TYPE_FUNCTION;  	intern->obj = closure; @@ -2185,7 +2193,7 @@ ZEND_METHOD(reflection_parameter, __construct)  	} else {  		ZVAL_NULL(name);  	} -	zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL); +	reflection_update_property(object, "name", name);  	ref = (parameter_reference*) emalloc(sizeof(parameter_reference));  	ref->arg_info = &arg_info[position]; @@ -2663,11 +2671,11 @@ ZEND_METHOD(reflection_method, __construct)  	MAKE_STD_ZVAL(classname);  	ZVAL_STRINGL(classname, mptr->common.scope->name, mptr->common.scope->name_length, 1); -	zend_hash_update(Z_OBJPROP_P(object), "class", sizeof("class"), (void **) &classname, sizeof(zval *), NULL); +	reflection_update_property(object, "class", classname);  	MAKE_STD_ZVAL(name);  	ZVAL_STRING(name, mptr->common.function_name, 1); -	zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL); +	reflection_update_property(object, "name", name);  	intern->ptr = mptr;  	intern->ref_type = REF_TYPE_FUNCTION;  	intern->ce = ce; @@ -3202,7 +3210,7 @@ static void reflection_class_object_ctor(INTERNAL_FUNCTION_PARAMETERS, int is_ob  	if (Z_TYPE_P(argument) == IS_OBJECT) {  		MAKE_STD_ZVAL(classname);  		ZVAL_STRINGL(classname, Z_OBJCE_P(argument)->name, Z_OBJCE_P(argument)->name_length, 1); -		zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &classname, sizeof(zval *), NULL); +		reflection_update_property(object, "name", classname);  		intern->ptr = Z_OBJCE_P(argument);  		if (is_object) {  			intern->obj = argument; @@ -3219,7 +3227,7 @@ static void reflection_class_object_ctor(INTERNAL_FUNCTION_PARAMETERS, int is_ob  		MAKE_STD_ZVAL(classname);  		ZVAL_STRINGL(classname, (*ce)->name, (*ce)->name_length, 1); -		zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &classname, sizeof(zval *), NULL); +		reflection_update_property(object, "name", classname);  		intern->ptr = *ce;  	} @@ -3235,14 +3243,63 @@ ZEND_METHOD(reflection_class, __construct)  }  /* }}} */ +/* {{{ add_class_vars */ +static void add_class_vars(zend_class_entry *ce, int statics, zval *return_value TSRMLS_DC) +{ +	HashPosition pos; +	zend_property_info *prop_info; +	zval *prop, *prop_copy; +	char *key; +	uint key_len; +	ulong num_index; + +	zend_hash_internal_pointer_reset_ex(&ce->properties_info, &pos); +	while (zend_hash_get_current_data_ex(&ce->properties_info, (void **) &prop_info, &pos) == SUCCESS) { +		zend_hash_get_current_key_ex(&ce->properties_info, &key, &key_len, &num_index, 0, &pos); +		zend_hash_move_forward_ex(&ce->properties_info, &pos); +		if (((prop_info->flags & ZEND_ACC_SHADOW) && +		     prop_info->ce != ce) || +		    ((prop_info->flags & ZEND_ACC_PROTECTED) && +		     !zend_check_protected(prop_info->ce, ce)) || +		    ((prop_info->flags & ZEND_ACC_PRIVATE) && +		     prop_info->ce != ce)) { +			continue; +		} +		prop = NULL; +		if (prop_info->offset >= 0) { +			if (statics && (prop_info->flags & ZEND_ACC_STATIC) != 0) { +				prop = ce->default_static_members_table[prop_info->offset]; +			} else if (!statics && (prop_info->flags & ZEND_ACC_STATIC) == 0) { +				prop = ce->default_properties_table[prop_info->offset]; +			} +		} +		if (!prop) { +			continue; +		} + +		/* copy: enforce read only access */ +		ALLOC_ZVAL(prop_copy); +		*prop_copy = *prop; +		zval_copy_ctor(prop_copy); +		INIT_PZVAL(prop_copy); + +		/* this is necessary to make it able to work with default array  +		* properties, returned to user */ +		if (Z_TYPE_P(prop_copy) == IS_CONSTANT_ARRAY || (Z_TYPE_P(prop_copy) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) { +			zval_update_constant(&prop_copy, 1 TSRMLS_CC); +		} + +		add_assoc_zval(return_value, key, prop_copy); +	} +} +/* }}} */ +  /* {{{ proto public array ReflectionClass::getStaticProperties()     Returns an associative array containing all static property values of the class */  ZEND_METHOD(reflection_class, getStaticProperties)  {  	reflection_object *intern;  	zend_class_entry *ce; -	HashPosition pos; -	zval **value;  	if (zend_parse_parameters_none() == FAILURE) {  		return; @@ -3253,31 +3310,7 @@ ZEND_METHOD(reflection_class, getStaticProperties)  	zend_update_class_constants(ce TSRMLS_CC);  	array_init(return_value); - -	zend_hash_internal_pointer_reset_ex(CE_STATIC_MEMBERS(ce), &pos); - -	while (zend_hash_get_current_data_ex(CE_STATIC_MEMBERS(ce), (void **) &value, &pos) == SUCCESS) { -		uint key_len; -		char *key; -		ulong num_index; - -		if (zend_hash_get_current_key_ex(CE_STATIC_MEMBERS(ce), &key, &key_len, &num_index, 0, &pos) != FAILURE && key) { -			char *prop_name, *class_name; -			zval *prop_copy; - -			zend_unmangle_property_name(key, key_len-1, &class_name, &prop_name); - -			/* filter privates from base classes */ -			if (!(class_name && class_name[0] != '*' && strcmp(class_name, ce->name))) { -				/* copy: enforce read only access */ -				ALLOC_ZVAL(prop_copy); -				MAKE_COPY_ZVAL(value, prop_copy); - -				add_assoc_zval(return_value, prop_name, prop_copy); -			} -		} -		zend_hash_move_forward_ex(CE_STATIC_MEMBERS(ce), &pos); -	} +	add_class_vars(ce, 1, return_value TSRMLS_CC);  }  /* }}} */ @@ -3355,51 +3388,15 @@ ZEND_METHOD(reflection_class, getDefaultProperties)  {  	reflection_object *intern;  	zend_class_entry *ce; -	int count, i; -	HashTable *ht_list[3];  	if (zend_parse_parameters_none() == FAILURE) {  		return;  	}  	GET_REFLECTION_OBJECT_PTR(ce);  	array_init(return_value); -  	zend_update_class_constants(ce TSRMLS_CC); - -	ht_list[0] = CE_STATIC_MEMBERS(ce); -	ht_list[1] = &ce->default_properties; -	ht_list[2] = NULL; - -	for (i = 0; ht_list[i] != NULL; i++) { - -		count = zend_hash_num_elements(ht_list[i]); -		if (count > 0) { -			HashPosition pos; -			zval **prop; - -			zend_hash_internal_pointer_reset_ex(ht_list[i], &pos); -			while (zend_hash_get_current_data_ex(ht_list[i], (void **) &prop, &pos) == SUCCESS) { -				char *key, *class_name, *prop_name; -				uint key_len; -				ulong num_index; -				zval *prop_copy; - -				zend_hash_get_current_key_ex(ht_list[i], &key, &key_len, &num_index, 0, &pos); -				zend_hash_move_forward_ex(ht_list[i], &pos); -				zend_unmangle_property_name(key, key_len-1, &class_name, &prop_name); -				if (class_name && class_name[0] != '*' && strcmp(class_name, ce->name)) { -					/* filter privates from base classes */ -					continue; -				} - -				/* copy: enforce read only access */ -				ALLOC_ZVAL(prop_copy); -				MAKE_COPY_ZVAL(prop, prop_copy); - -				add_assoc_zval(return_value, prop_name, prop_copy); -			} -		} -	} +	add_class_vars(ce, 1, return_value TSRMLS_CC); +	add_class_vars(ce, 0, return_value TSRMLS_CC);  }  /* }}} */ @@ -4564,8 +4561,8 @@ ZEND_METHOD(reflection_property, __construct)  		ZVAL_STRINGL(classname, ce->name, ce->name_length, 1);	  		ZVAL_STRINGL(propname, name_str, name_len, 1);  	} -	zend_hash_update(Z_OBJPROP_P(object), "class", sizeof("class"), (void **) &classname, sizeof(zval *), NULL); -	zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &propname, sizeof(zval *), NULL); +	reflection_update_property(object, "class", classname); +	reflection_update_property(object, "name", propname);  	reference = (property_reference*) emalloc(sizeof(property_reference));  	if (dynam_prop) { @@ -4690,7 +4687,7 @@ ZEND_METHOD(reflection_property, getValue)  	reflection_object *intern;  	property_reference *ref;  	zval *object, name; -	zval **member = NULL, *member_p = NULL; +	zval *member_p = NULL;  	METHOD_NOTSTATIC(reflection_property_ptr);  	GET_REFLECTION_OBJECT_PTR(ref); @@ -4705,11 +4702,13 @@ ZEND_METHOD(reflection_property, getValue)  	if ((ref->prop.flags & ZEND_ACC_STATIC)) {  		zend_update_class_constants(intern->ce TSRMLS_CC); -		if (zend_hash_quick_find(CE_STATIC_MEMBERS(intern->ce), ref->prop.name, ref->prop.name_length + 1, ref->prop.h, (void **) &member) == FAILURE) { +		if (!CE_STATIC_MEMBERS(intern->ce)[ref->prop.offset]) {  			php_error_docref(NULL TSRMLS_CC, E_ERROR, "Internal error: Could not find the property %s::%s", intern->ce->name, ref->prop.name);  			/* Bails out */  		} -		MAKE_COPY_ZVAL(member, return_value); +		*return_value= *CE_STATIC_MEMBERS(intern->ce)[ref->prop.offset]; +		zval_copy_ctor(return_value); + 		INIT_PZVAL(return_value);  	} else {  		char *class_name, *prop_name; @@ -4738,7 +4737,6 @@ ZEND_METHOD(reflection_property, setValue)  	zval *value;  	int setter_done = 0;  	zval *tmp; -	HashTable *prop_table;  	METHOD_NOTSTATIC(reflection_property_ptr);  	GET_REFLECTION_OBJECT_PTR(ref); @@ -4758,33 +4756,34 @@ ZEND_METHOD(reflection_property, setValue)  			}  		}  		zend_update_class_constants(intern->ce TSRMLS_CC); -		prop_table = CE_STATIC_MEMBERS(intern->ce); -		if (zend_hash_quick_find(prop_table, ref->prop.name, ref->prop.name_length + 1, ref->prop.h, (void **) &variable_ptr) == FAILURE) { +		if (!CE_STATIC_MEMBERS(intern->ce)[ref->prop.offset]) {  			php_error_docref(NULL TSRMLS_CC, E_ERROR, "Internal error: Could not find the property %s::%s", intern->ce->name, ref->prop.name);  			/* Bails out */  		} -		if (*variable_ptr == value) { -			setter_done = 1; -		} else { +		variable_ptr = &CE_STATIC_MEMBERS(intern->ce)[ref->prop.offset]; +		if (*variable_ptr != value) {  			if (PZVAL_IS_REF(*variable_ptr)) { -				zval_dtor(*variable_ptr); -				(*variable_ptr)->type = value->type; +				zval garbage = **variable_ptr; /* old value should be destroyed */ + +				/* To check: can't *variable_ptr be some system variable like error_zval here? */ +				Z_TYPE_PP(variable_ptr) = Z_TYPE_P(value);  				(*variable_ptr)->value = value->value;  				if (Z_REFCOUNT_P(value) > 0) {  					zval_copy_ctor(*variable_ptr);  				} -				setter_done = 1; -			} -		} -		if (!setter_done) { -			zval **foo; +				zval_dtor(&garbage); +			} else { +				zval *garbage = *variable_ptr; -			Z_ADDREF_P(value); -			if (PZVAL_IS_REF(value)) { -				SEPARATE_ZVAL(&value); +				/* if we assign referenced variable, we should separate it */ +				Z_ADDREF_P(value); +				if (PZVAL_IS_REF(value)) { +					SEPARATE_ZVAL(&value); +				} +				*variable_ptr = value; +				zval_ptr_dtor(&garbage);  			} -			zend_hash_quick_update(prop_table, ref->prop.name, ref->prop.name_length+1, ref->prop.h, &value, sizeof(zval *), (void **) &foo);  		}  	} else {  		char *class_name, *prop_name; @@ -4917,7 +4916,7 @@ ZEND_METHOD(reflection_extension, __construct)  	free_alloca(lcname, use_heap);  	MAKE_STD_ZVAL(name);  	ZVAL_STRING(name, module->name, 1); -	zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL); +	reflection_update_property( object, "name", name);  	intern->ptr = module;  	intern->ref_type = REF_TYPE_OTHER;  	intern->ce = NULL; @@ -5269,7 +5268,7 @@ ZEND_METHOD(reflection_zend_extension, __construct)  	}  	MAKE_STD_ZVAL(name);  	ZVAL_STRING(name, extension->name, 1); -	zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL); +	reflection_update_property(object, "name", name);  	intern->ptr = extension;  	intern->ref_type = REF_TYPE_OTHER;  	intern->ce = NULL; @@ -5783,7 +5782,7 @@ static zend_object_handlers *zend_std_obj_handlers;  static void _reflection_write_property(zval *object, zval *member, zval *value, const zend_literal *key TSRMLS_DC)  {  	if ((Z_TYPE_P(member) == IS_STRING) -		&& zend_hash_exists(&Z_OBJCE_P(object)->default_properties, Z_STRVAL_P(member), Z_STRLEN_P(member)+1) +		&& zend_hash_exists(&Z_OBJCE_P(object)->properties_info, Z_STRVAL_P(member), Z_STRLEN_P(member)+1)  		&& ((Z_STRLEN_P(member) == sizeof("name") - 1  && !memcmp(Z_STRVAL_P(member), "name",  sizeof("name")))  			|| (Z_STRLEN_P(member) == sizeof("class") - 1 && !memcmp(Z_STRVAL_P(member), "class", sizeof("class")))))  	{  | 
