From 92dd5e611b897bdca8ba27cbfcdc0fc3d7416c85 Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Tue, 12 Mar 2002 10:08:47 +0000 Subject: [PATCH] - make class tables contain class_entry *, not class_entry - fix isset($this) --- Zend/zend.c | 46 +++++---- Zend/zend.h | 2 +- Zend/zend_API.c | 27 +++-- Zend/zend_builtin_functions.c | 20 ++-- Zend/zend_compile.c | 184 ++++++++++++++++++---------------- Zend/zend_compile.h | 2 +- Zend/zend_execute.c | 53 ++++++---- Zend/zend_execute_API.c | 4 +- Zend/zend_opcode.c | 6 +- 9 files changed, 196 insertions(+), 148 deletions(-) diff --git a/Zend/zend.c b/Zend/zend.c index afeb01a628..713bdfd5e8 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -44,7 +44,7 @@ BOOL WINAPI IsDebuggerPresent(VOID); #endif /* true multithread-shared globals */ -ZEND_API zend_class_entry zend_standard_class_def; +ZEND_API zend_class_entry *zend_standard_class_def = NULL; ZEND_API int (*zend_printf)(const char *format, ...); ZEND_API zend_write_func_t zend_write; ZEND_API FILE *(*zend_fopen)(const char *filename, char **opened_path); @@ -148,7 +148,7 @@ ZEND_API void zend_make_printable_zval(zval *expr, zval *expr_copy, int *use_cop break; case IS_OBJECT: expr_copy->value.str.val = (char *) emalloc(sizeof("Object id #")-1 + MAX_LENGTH_OF_LONG); - expr_copy->value.str.len = sprintf(expr_copy->value.str.val, "Object id #%ld", expr->value.obj.handle); + expr_copy->value.str.len = sprintf(expr_copy->value.str.val, "Object id #%ld", (long)expr->value.obj.handle); #if 0 /* FIXME: This might break BC for some people */ expr_copy->value.str.len = sizeof("Object")-1; @@ -246,26 +246,28 @@ static FILE *zend_fopen_wrapper(const char *filename, char **opened_path) static void register_standard_class(void) { - zend_standard_class_def.type = ZEND_INTERNAL_CLASS; - zend_standard_class_def.name_length = sizeof("stdClass") - 1; - zend_standard_class_def.name = zend_strndup("stdClass", zend_standard_class_def.name_length); - zend_standard_class_def.parent = NULL; - zend_hash_init_ex(&zend_standard_class_def.default_properties, 0, NULL, ZVAL_PTR_DTOR, 1, 0); - zend_hash_init_ex(&zend_standard_class_def.private_properties, 0, NULL, ZVAL_PTR_DTOR, 1, 0); - zend_standard_class_def.static_members = (HashTable *) malloc(sizeof(HashTable)); - zend_hash_init_ex(zend_standard_class_def.static_members, 0, NULL, ZVAL_PTR_DTOR, 1, 0); - zend_hash_init_ex(&zend_standard_class_def.constants_table, 0, NULL, ZVAL_PTR_DTOR, 1, 0); - zend_hash_init_ex(&zend_standard_class_def.class_table, 10, NULL, ZEND_CLASS_DTOR, 1, 0); - zend_hash_init_ex(&zend_standard_class_def.function_table, 0, NULL, ZEND_FUNCTION_DTOR, 1, 0); - zend_standard_class_def.constructor = NULL; - zend_standard_class_def.destructor = NULL; - zend_standard_class_def.clone = NULL; - zend_standard_class_def.handle_function_call = NULL; - zend_standard_class_def.handle_property_get = NULL; - zend_standard_class_def.handle_property_set = NULL; - zend_standard_class_def.refcount = (int *) malloc(sizeof(int)); - *zend_standard_class_def.refcount = 1; - zend_hash_add(GLOBAL_CLASS_TABLE, "stdclass", sizeof("stdclass"), &zend_standard_class_def, sizeof(zend_class_entry), NULL); + zend_standard_class_def = malloc(sizeof(zend_class_entry)); + + zend_standard_class_def->type = ZEND_INTERNAL_CLASS; + zend_standard_class_def->name_length = sizeof("stdClass") - 1; + zend_standard_class_def->name = zend_strndup("stdClass", zend_standard_class_def->name_length); + zend_standard_class_def->parent = NULL; + zend_hash_init_ex(&zend_standard_class_def->default_properties, 0, NULL, ZVAL_PTR_DTOR, 1, 0); + zend_hash_init_ex(&zend_standard_class_def->private_properties, 0, NULL, ZVAL_PTR_DTOR, 1, 0); + zend_standard_class_def->static_members = (HashTable *) malloc(sizeof(HashTable)); + zend_hash_init_ex(zend_standard_class_def->static_members, 0, NULL, ZVAL_PTR_DTOR, 1, 0); + zend_hash_init_ex(&zend_standard_class_def->constants_table, 0, NULL, ZVAL_PTR_DTOR, 1, 0); + zend_hash_init_ex(&zend_standard_class_def->class_table, 10, NULL, ZEND_CLASS_DTOR, 1, 0); + zend_hash_init_ex(&zend_standard_class_def->function_table, 0, NULL, ZEND_FUNCTION_DTOR, 1, 0); + zend_standard_class_def->constructor = NULL; + zend_standard_class_def->destructor = NULL; + zend_standard_class_def->clone = NULL; + zend_standard_class_def->handle_function_call = NULL; + zend_standard_class_def->handle_property_get = NULL; + zend_standard_class_def->handle_property_set = NULL; + zend_standard_class_def->refcount = (int *) malloc(sizeof(int)); + *zend_standard_class_def->refcount = 1; + zend_hash_add(GLOBAL_CLASS_TABLE, "stdclass", sizeof("stdclass"), &zend_standard_class_def, sizeof(zend_class_entry *), NULL); } diff --git a/Zend/zend.h b/Zend/zend.h index 98501df6ca..e7b0704b0a 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -428,7 +428,7 @@ ZEND_API void zend_error(int type, const char *format, ...); void zenderror(char *error); -extern ZEND_API zend_class_entry zend_standard_class_def; +extern ZEND_API zend_class_entry *zend_standard_class_def; extern zend_utility_values zend_uv; extern ZEND_API zval zval_used_for_init; diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 9fec995375..16f11712d6 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -1202,9 +1202,12 @@ ZEND_API zend_class_entry *zend_register_internal_class_ex(zend_class_entry *cla zend_class_entry *register_class; if (!parent_ce && parent_name) { - if (zend_hash_find(CG(class_table), parent_name, strlen(parent_name)+1, (void **) &parent_ce)==FAILURE) { - return NULL; - } + zend_class_entry **pce; + if (zend_hash_find(CG(class_table), parent_name, strlen(parent_name)+1, (void **) &pce)==FAILURE) { + return NULL; + } else { + parent_ce = *pce; + } } register_class = zend_register_internal_class(class_entry TSRMLS_CC); @@ -1215,10 +1218,11 @@ ZEND_API zend_class_entry *zend_register_internal_class_ex(zend_class_entry *cla return register_class; } -ZEND_API zend_class_entry *zend_register_internal_class(zend_class_entry *class_entry TSRMLS_DC) +ZEND_API zend_class_entry *zend_register_internal_class(zend_class_entry *orig_class_entry TSRMLS_DC) { - zend_class_entry *register_class; - char *lowercase_name = zend_strndup(class_entry->name, class_entry->name_length); + zend_class_entry *class_entry = malloc(sizeof(zend_class_entry)); + char *lowercase_name = zend_strndup(orig_class_entry->name, orig_class_entry->name_length); + *class_entry = *orig_class_entry; zend_str_tolower(lowercase_name, class_entry->name_length); @@ -1239,9 +1243,9 @@ ZEND_API zend_class_entry *zend_register_internal_class(zend_class_entry *class_ zend_register_functions(class_entry->builtin_functions, &class_entry->function_table, MODULE_PERSISTENT TSRMLS_CC); } - zend_hash_update(CG(class_table), lowercase_name, class_entry->name_length+1, class_entry, sizeof(zend_class_entry), (void **) ®ister_class); + zend_hash_update(CG(class_table), lowercase_name, class_entry->name_length+1, &class_entry, sizeof(zend_class_entry *), NULL); free(lowercase_name); - return register_class; + return class_entry; } @@ -1327,7 +1331,7 @@ zend_bool zend_is_callable(zval *callable, zend_bool syntax_only, char **callabl { zval **method; zval **obj; - zend_class_entry *ce = NULL; + zend_class_entry *ce = NULL, **pce; char callable_name_len; if (zend_hash_num_elements(Z_ARRVAL_P(callable)) == 2 && @@ -1354,7 +1358,10 @@ zend_bool zend_is_callable(zval *callable, zend_bool syntax_only, char **callabl lcname = estrndup(Z_STRVAL_PP(obj), Z_STRLEN_PP(obj)); zend_str_tolower(lcname, Z_STRLEN_PP(obj)); - zend_hash_find(EG(class_table), lcname, Z_STRLEN_PP(obj) + 1, (void**)&ce); + if(zend_hash_find(EG(class_table), lcname, Z_STRLEN_PP(obj) + 1, (void**)&pce) == SUCCESS) { + ce = *pce; + } + efree(lcname); } else { ce = Z_OBJCE_PP(obj); /* ??? */ diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index 55e183a929..8341bd7df3 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -532,9 +532,13 @@ ZEND_FUNCTION(get_parent_class) } RETURN_STRINGL(name, name_length, 1); } else if (Z_TYPE_PP(arg) == IS_STRING) { + zend_class_entry **pce; + SEPARATE_ZVAL(arg); zend_str_tolower(Z_STRVAL_PP(arg), Z_STRLEN_PP(arg)); - zend_hash_find(EG(class_table), Z_STRVAL_PP(arg), Z_STRLEN_PP(arg)+1, (void **)&ce); + if(zend_hash_find(EG(class_table), Z_STRVAL_PP(arg), Z_STRLEN_PP(arg)+1, (void **)&pce) == SUCCESS) { + ce = *pce; + } } if (ce && ce->parent) { @@ -609,7 +613,7 @@ ZEND_FUNCTION(get_class_vars) { zval **class_name; char *lcname; - zend_class_entry *ce; + zend_class_entry *ce, **pce; zval *tmp; if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &class_name)==FAILURE) { @@ -620,10 +624,11 @@ ZEND_FUNCTION(get_class_vars) lcname = estrndup((*class_name)->value.str.val, (*class_name)->value.str.len); zend_str_tolower(lcname, (*class_name)->value.str.len); - if (zend_hash_find(EG(class_table), lcname, (*class_name)->value.str.len+1, (void **)&ce)==FAILURE) { + if (zend_hash_find(EG(class_table), lcname, (*class_name)->value.str.len+1, (void **)&pce) == FAILURE) { efree(lcname); RETURN_FALSE; } else { + ce = *pce; efree(lcname); array_init(return_value); if (!ce->constants_updated) { @@ -667,7 +672,7 @@ ZEND_FUNCTION(get_class_methods) { zval **class; zval *method_name; - zend_class_entry *ce = NULL; + zend_class_entry *ce = NULL, **pce; char *string_key; ulong num_key; int key_type; @@ -685,7 +690,9 @@ ZEND_FUNCTION(get_class_methods) } else if (Z_TYPE_PP(class) == IS_STRING) { SEPARATE_ZVAL(class); zend_str_tolower(Z_STRVAL_PP(class), Z_STRLEN_PP(class)); - zend_hash_find(EG(class_table), Z_STRVAL_PP(class), Z_STRLEN_PP(class)+1, (void **)&ce); + if(zend_hash_find(EG(class_table), Z_STRVAL_PP(class), Z_STRLEN_PP(class)+1, (void **)&pce) == SUCCESS) { + ce = *pce; + } } if (!ce) { @@ -926,9 +933,10 @@ ZEND_FUNCTION(restore_error_handler) } -static int copy_class_name(zend_class_entry *ce, int num_args, va_list args, zend_hash_key *hash_key) +static int copy_class_name(zend_class_entry **pce, int num_args, va_list args, zend_hash_key *hash_key) { zval *array = va_arg(args, zval *); + zend_class_entry *ce = *pce; if (hash_key->nKeyLength==0 || hash_key->arKey[0]!=0) { add_next_index_stringl(array, ce->name, ce->name_length, 1); diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index b5943c1464..e0540ffe48 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -1509,37 +1509,39 @@ void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent_ce) static void create_class(HashTable *class_table, char *name, int name_length, zend_class_entry **ce) { - zend_class_entry new_class_entry; - - new_class_entry.type = ZEND_USER_CLASS; - new_class_entry.name = estrndup(name, name_length); - new_class_entry.name_length = name_length; - new_class_entry.refcount = (int *) emalloc(sizeof(int)); - *new_class_entry.refcount = 1; - new_class_entry.constants_updated = 0; - - zend_str_tolower(new_class_entry.name, new_class_entry.name_length); - - zend_hash_init(&new_class_entry.function_table, 10, NULL, ZEND_FUNCTION_DTOR, 0); - zend_hash_init(&new_class_entry.class_table, 10, NULL, ZEND_CLASS_DTOR, 0); - zend_hash_init(&new_class_entry.default_properties, 10, NULL, ZVAL_PTR_DTOR, 0); - zend_hash_init(&new_class_entry.private_properties, 10, NULL, ZVAL_PTR_DTOR, 0); - ALLOC_HASHTABLE(new_class_entry.static_members); - zend_hash_init(new_class_entry.static_members, 10, NULL, ZVAL_PTR_DTOR, 0); - zend_hash_init(&new_class_entry.constants_table, 10, NULL, ZVAL_PTR_DTOR, 0); - - new_class_entry.constructor = NULL; - new_class_entry.destructor = NULL; - new_class_entry.clone = NULL; - - new_class_entry.create_object = NULL; - new_class_entry.handle_function_call = NULL; - new_class_entry.handle_property_set = NULL; - new_class_entry.handle_property_get = NULL; - - new_class_entry.parent = NULL; - - if (zend_hash_update(class_table, new_class_entry.name, name_length+1, &new_class_entry, sizeof(zend_class_entry), (void **)ce) == FAILURE) { + zend_class_entry *new_class_entry; + + new_class_entry = emalloc(sizeof(zend_class_entry)); + *ce = new_class_entry; + new_class_entry->type = ZEND_USER_CLASS; + new_class_entry->name = estrndup(name, name_length); + new_class_entry->name_length = name_length; + new_class_entry->refcount = (int *) emalloc(sizeof(int)); + *new_class_entry->refcount = 1; + new_class_entry->constants_updated = 0; + + zend_str_tolower(new_class_entry->name, new_class_entry->name_length); + + zend_hash_init(&new_class_entry->function_table, 10, NULL, ZEND_FUNCTION_DTOR, 0); + zend_hash_init(&new_class_entry->class_table, 10, NULL, ZEND_CLASS_DTOR, 0); + zend_hash_init(&new_class_entry->default_properties, 10, NULL, ZVAL_PTR_DTOR, 0); + zend_hash_init(&new_class_entry->private_properties, 10, NULL, ZVAL_PTR_DTOR, 0); + ALLOC_HASHTABLE(new_class_entry->static_members); + zend_hash_init(new_class_entry->static_members, 10, NULL, ZVAL_PTR_DTOR, 0); + zend_hash_init(&new_class_entry->constants_table, 10, NULL, ZVAL_PTR_DTOR, 0); + + new_class_entry->constructor = NULL; + new_class_entry->destructor = NULL; + new_class_entry->clone = NULL; + + new_class_entry->create_object = NULL; + new_class_entry->handle_function_call = NULL; + new_class_entry->handle_property_set = NULL; + new_class_entry->handle_property_get = NULL; + + new_class_entry->parent = NULL; + + if (zend_hash_update(class_table, new_class_entry->name, name_length+1, &new_class_entry, sizeof(zend_class_entry *), NULL) == FAILURE) { zend_error(E_ERROR, "Can't create class. Fatal error, please report!"); } } @@ -1551,13 +1553,15 @@ static int create_nested_class(HashTable *class_table, char *path, zend_class_en { char *cur, *temp; char *last; - zend_class_entry *ce; + zend_class_entry *ce, **pce; cur = tsrm_strtok_r(path, ":", &temp); - if (zend_hash_find(class_table, cur, strlen(cur)+1, (void **)&ce) == FAILURE) { + if (zend_hash_find(class_table, cur, strlen(cur)+1, (void **)&pce) == FAILURE) { create_class(class_table, cur, strlen(cur), &ce); + } else { + ce = *pce; } last = tsrm_strtok_r(NULL, ":", &temp); @@ -1567,13 +1571,15 @@ static int create_nested_class(HashTable *class_table, char *path, zend_class_en if (!cur) { break; } - if (zend_hash_find(&ce->class_table, last, strlen(last)+1, (void **)&ce) == FAILURE) { + if (zend_hash_find(&ce->class_table, last, strlen(last)+1, (void **)&pce) == FAILURE) { create_class(&ce->class_table, last, strlen(last), &ce); + } else { + ce = *pce; } last = cur; } (*new_ce->refcount)++; - if (zend_hash_add(&ce->class_table, last, strlen(last)+1, new_ce, sizeof(zend_class_entry), NULL) == FAILURE) { + if (zend_hash_add(&ce->class_table, last, strlen(last)+1, &new_ce, sizeof(zend_class_entry *), NULL) == FAILURE) { (*new_ce->refcount)--; zend_error(E_ERROR, "Cannot redeclare class %s", last); return FAILURE; @@ -1611,17 +1617,19 @@ ZEND_API int do_bind_function_or_class(zend_op *opline, HashTable *function_tabl } break; case ZEND_DECLARE_CLASS: { - zend_class_entry *ce; + zend_class_entry *ce, **pce; - if (zend_hash_find(class_table, opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len, (void **) &ce)==FAILURE) { + if (zend_hash_find(class_table, opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len, (void **) &pce)==FAILURE) { zend_error(E_ERROR, "Internal Zend error - Missing class information for %s", opline->op1.u.constant.value.str.val); return FAILURE; + } else { + ce = *pce; } if (strchr(opline->op2.u.constant.value.str.val, ':')) { return create_nested_class(class_table, opline->op2.u.constant.value.str.val, ce); } (*ce->refcount)++; - if (zend_hash_add(class_table, opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len+1, ce, sizeof(zend_class_entry), NULL)==FAILURE) { + if (zend_hash_add(class_table, opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len+1, &ce, sizeof(zend_class_entry *), NULL)==FAILURE) { (*ce->refcount)--; if (!compile_time) { zend_error(E_ERROR, "Cannot redeclare class %s", opline->op2.u.constant.value.str.val); @@ -1633,13 +1641,13 @@ ZEND_API int do_bind_function_or_class(zend_op *opline, HashTable *function_tabl } break; case ZEND_DECLARE_INHERITED_CLASS: { - zend_class_entry *ce, *parent_ce; + zend_class_entry **parent_pce, *ce, **pce; int parent_name_length; char *class_name, *parent_name; int found_ce; - found_ce = zend_hash_find(class_table, opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len, (void **) &ce); + found_ce = zend_hash_find(class_table, opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len, (void **) &pce); /* Restore base class / derived class names */ class_name = strchr(opline->op2.u.constant.value.str.val, ':'); @@ -1651,14 +1659,15 @@ ZEND_API int do_bind_function_or_class(zend_op *opline, HashTable *function_tabl if (found_ce==FAILURE) { zend_error(E_ERROR, "Cannot redeclare class %s", class_name); return FAILURE; + } else { + ce = *pce; } - (*ce->refcount)++; /* Obtain parent class */ parent_name_length = class_name - opline->op2.u.constant.value.str.val - 1; parent_name = estrndup(opline->op2.u.constant.value.str.val, parent_name_length); - if (zend_hash_find(class_table, parent_name, parent_name_length+1, (void **) &parent_ce)==FAILURE) { + if (zend_hash_find(class_table, parent_name, parent_name_length+1, (void **) &parent_pce)==FAILURE) { if (!compile_time) { zend_error(E_ERROR, "Class %s: Cannot inherit from undefined class %s", class_name, parent_name); } @@ -1668,10 +1677,10 @@ ZEND_API int do_bind_function_or_class(zend_op *opline, HashTable *function_tabl } efree(parent_name); - zend_do_inheritance(ce, parent_ce); + zend_do_inheritance(ce, *parent_pce); /* Register the derived class */ - if (zend_hash_add(class_table, class_name, strlen(class_name)+1, ce, sizeof(zend_class_entry), NULL)==FAILURE) { + if (zend_hash_add(class_table, class_name, strlen(class_name)+1, pce, sizeof(zend_class_entry *), NULL)==FAILURE) { if (!compile_time) { zend_error(E_ERROR, "Cannot redeclare class %s", opline->op2.u.constant.value.str.val); } @@ -2000,38 +2009,38 @@ void zend_do_begin_class_declaration(znode *class_token, znode *class_name, znod { zend_op *opline; int runtime_inheritance = 0; - zend_class_entry new_class_entry; + zend_class_entry *new_class_entry = emalloc(sizeof(zend_class_entry)); class_token->u.previously_active_class_entry = CG(active_class_entry); - new_class_entry.type = ZEND_USER_CLASS; - new_class_entry.name = class_name->u.constant.value.str.val; - new_class_entry.name_length = class_name->u.constant.value.str.len; - new_class_entry.refcount = (int *) emalloc(sizeof(int)); - *new_class_entry.refcount = 1; - new_class_entry.constants_updated = 0; + new_class_entry->type = ZEND_USER_CLASS; + new_class_entry->name = class_name->u.constant.value.str.val; + new_class_entry->name_length = class_name->u.constant.value.str.len; + new_class_entry->refcount = (int *) emalloc(sizeof(int)); + *new_class_entry->refcount = 1; + new_class_entry->constants_updated = 0; - zend_str_tolower(new_class_entry.name, new_class_entry.name_length); + zend_str_tolower(new_class_entry->name, new_class_entry->name_length); - zend_hash_init(&new_class_entry.function_table, 10, NULL, ZEND_FUNCTION_DTOR, 0); - zend_hash_init(&new_class_entry.class_table, 10, NULL, ZEND_CLASS_DTOR, 0); - zend_hash_init(&new_class_entry.default_properties, 10, NULL, ZVAL_PTR_DTOR, 0); - zend_hash_init(&new_class_entry.private_properties, 10, NULL, ZVAL_PTR_DTOR, 0); - ALLOC_HASHTABLE(new_class_entry.static_members); - zend_hash_init(new_class_entry.static_members, 10, NULL, ZVAL_PTR_DTOR, 0); - zend_hash_init(&new_class_entry.constants_table, 10, NULL, ZVAL_PTR_DTOR, 0); + zend_hash_init(&new_class_entry->function_table, 10, NULL, ZEND_FUNCTION_DTOR, 0); + zend_hash_init(&new_class_entry->class_table, 10, NULL, ZEND_CLASS_DTOR, 0); + zend_hash_init(&new_class_entry->default_properties, 10, NULL, ZVAL_PTR_DTOR, 0); + zend_hash_init(&new_class_entry->private_properties, 10, NULL, ZVAL_PTR_DTOR, 0); + ALLOC_HASHTABLE(new_class_entry->static_members); + zend_hash_init(new_class_entry->static_members, 10, NULL, ZVAL_PTR_DTOR, 0); + zend_hash_init(&new_class_entry->constants_table, 10, NULL, ZVAL_PTR_DTOR, 0); - new_class_entry.constructor = NULL; - new_class_entry.destructor = NULL; - new_class_entry.clone = NULL; + new_class_entry->constructor = NULL; + new_class_entry->destructor = NULL; + new_class_entry->clone = NULL; - new_class_entry.create_object = NULL; - new_class_entry.handle_function_call = NULL; - new_class_entry.handle_property_set = NULL; - new_class_entry.handle_property_get = NULL; + new_class_entry->create_object = NULL; + new_class_entry->handle_function_call = NULL; + new_class_entry->handle_property_set = NULL; + new_class_entry->handle_property_get = NULL; /* code for inheritance from parent class */ if (parent_class_name) { - zend_class_entry *parent_class; + zend_class_entry *parent_class, **parent_class_p; zend_function tmp_zend_function; zval *tmp; @@ -2040,44 +2049,46 @@ void zend_do_begin_class_declaration(znode *class_token, znode *class_name, znod CG(active_ce_parent_class_name).value.str.len = parent_class_name->u.constant.value.str.len; if (zend_hash_find(CG(active_class_entry)?&CG(active_class_entry)->class_table:CG(class_table), parent_class_name->u.constant.value.str.val, parent_class_name->u.constant.value.str.len+1, (void **) &parent_class)==SUCCESS) { + parent_class = *parent_class_p; /* copy functions */ - zend_hash_copy(&new_class_entry.function_table, &parent_class->function_table, (copy_ctor_func_t) function_add_ref, &tmp_zend_function, sizeof(zend_function)); + zend_hash_copy(&new_class_entry->function_table, &parent_class->function_table, (copy_ctor_func_t) function_add_ref, &tmp_zend_function, sizeof(zend_function)); /* copy default properties */ - zend_hash_copy(&new_class_entry.default_properties, &parent_class->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); + zend_hash_copy(&new_class_entry->default_properties, &parent_class->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); /* copy static members */ - zend_hash_copy(new_class_entry.static_members, parent_class->static_members, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); + zend_hash_copy(new_class_entry->static_members, parent_class->static_members, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); /* copy constants */ - zend_hash_copy(&new_class_entry.constants_table, &parent_class->constants_table, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); + zend_hash_copy(&new_class_entry->constants_table, &parent_class->constants_table, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); - new_class_entry.constructor = parent_class->constructor; - new_class_entry.destructor = parent_class->destructor; + new_class_entry->constructor = parent_class->constructor; + new_class_entry->destructor = parent_class->destructor; /* FIXME: What do we do with clone? */ /* copy overloaded handlers */ - new_class_entry.handle_function_call = parent_class->handle_function_call; - new_class_entry.handle_property_get = parent_class->handle_property_get; - new_class_entry.handle_property_set = parent_class->handle_property_set; + new_class_entry->handle_function_call = parent_class->handle_function_call; + new_class_entry->handle_property_get = parent_class->handle_property_get; + new_class_entry->handle_property_set = parent_class->handle_property_set; - new_class_entry.parent = parent_class; + new_class_entry->parent = parent_class; zval_dtor(&parent_class_name->u.constant); } else { runtime_inheritance = 1; - new_class_entry.parent = NULL; + new_class_entry->parent = NULL; } } else { - new_class_entry.parent = NULL; + new_class_entry->parent = NULL; } if (CG(active_class_entry)) { if (runtime_inheritance) { zend_error(E_ERROR, "Only first level classes can inherit from undefined classes"); } - zend_hash_update(&CG(active_class_entry)->class_table, new_class_entry.name, new_class_entry.name_length+1, &new_class_entry, sizeof(zend_class_entry), (void **) &CG(active_class_entry)); + zend_hash_update(&CG(active_class_entry)->class_table, new_class_entry->name, new_class_entry->name_length+1, &new_class_entry, sizeof(zend_class_entry *), NULL); + CG(active_class_entry) = new_class_entry; return; } @@ -2091,25 +2102,26 @@ void zend_do_begin_class_declaration(znode *class_token, znode *class_name, znod if (runtime_inheritance) { char *full_class_name; - opline->op2.u.constant.value.str.len = parent_class_name->u.constant.value.str.len+1+new_class_entry.name_length; + opline->op2.u.constant.value.str.len = parent_class_name->u.constant.value.str.len+1+new_class_entry->name_length; full_class_name = opline->op2.u.constant.value.str.val = (char *) emalloc(opline->op2.u.constant.value.str.len+1); memcpy(full_class_name, parent_class_name->u.constant.value.str.val, parent_class_name->u.constant.value.str.len); full_class_name += parent_class_name->u.constant.value.str.len; full_class_name[0] = ':'; full_class_name++; - memcpy(full_class_name, new_class_entry.name, new_class_entry.name_length); + memcpy(full_class_name, new_class_entry->name, new_class_entry->name_length); zval_dtor(&parent_class_name->u.constant); - full_class_name += new_class_entry.name_length; + full_class_name += new_class_entry->name_length; full_class_name[0] = 0; opline->extended_value = ZEND_DECLARE_INHERITED_CLASS; } else { - opline->op2.u.constant.value.str.val = estrndup(new_class_entry.name, new_class_entry.name_length); - opline->op2.u.constant.value.str.len = new_class_entry.name_length; + opline->op2.u.constant.value.str.val = estrndup(new_class_entry->name, new_class_entry->name_length); + opline->op2.u.constant.value.str.len = new_class_entry->name_length; opline->extended_value = ZEND_DECLARE_CLASS; } - zend_hash_update(CG(class_table), opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len, &new_class_entry, sizeof(zend_class_entry), (void **) &CG(active_class_entry)); + zend_hash_update(CG(class_table), opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len, &new_class_entry, sizeof(zend_class_entry *), NULL); + CG(active_class_entry) = new_class_entry; } diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 1a24312e4c..bc6dbd21c6 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -387,7 +387,7 @@ ZEND_API void zend_destroy_file_handle(zend_file_handle *file_handle TSRMLS_DC); ZEND_API void zend_file_handle_dtor(zend_file_handle *fh); ZEND_API void destroy_zend_function(zend_function *function); -ZEND_API void destroy_zend_class(zend_class_entry *ce); +ZEND_API void destroy_zend_class(zend_class_entry **pce); void zend_class_add_ref(zend_class_entry *ce); #define ZEND_FUNCTION_DTOR (void (*)(void *)) destroy_zend_function diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 35c717a37a..5253113ab3 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -1737,7 +1737,7 @@ binary_assign_op_addr_obj: case ZEND_IMPORT_CLASS: { zend_class_entry *ce; - zend_class_entry *import_ce; + zend_class_entry **import_ce; ce = EX(Ts)[EX(opline)->op1.u.var].EA.class_entry; @@ -1751,14 +1751,14 @@ binary_assign_op_addr_obj: if (zend_hash_find(&ce->class_table, class_name_strval, class_name_strlen + 1, (void **) &import_ce)==FAILURE) { zend_error(E_ERROR, "Import: class %s not found", class_name_strval); } - if (zend_hash_add(EG(class_table), class_name_strval, class_name_strlen + 1, import_ce, sizeof(zend_class_entry), NULL) == FAILURE) { + if (zend_hash_add(EG(class_table), class_name_strval, class_name_strlen + 1, import_ce, sizeof(zend_class_entry *), NULL) == FAILURE) { zend_error(E_ERROR, "Import: class %s already exists in current scope", class_name_strval); } - zend_class_add_ref(import_ce); + zend_class_add_ref(*import_ce); } else { - zend_class_entry tmp_zend_class_entry; + zend_class_entry *tmp_zend_class_entry; - zend_hash_copy(EG(class_table), &ce->class_table, (copy_ctor_func_t) zend_class_add_ref, &tmp_zend_class_entry, sizeof(zend_class_entry)); + zend_hash_copy(EG(class_table), &ce->class_table, (copy_ctor_func_t) zend_class_add_ref, &tmp_zend_class_entry, sizeof(zend_class_entry *)); } NEXT_OPCODE(); @@ -1816,6 +1816,8 @@ binary_assign_op_addr_obj: } case ZEND_FETCH_CLASS: { + zend_class_entry **pce; + if (EX(opline)->op1.op_type == IS_UNUSED) { zval tmp; zval *class_name; @@ -1860,16 +1862,20 @@ binary_assign_op_addr_obj: class_name_strlen = tmp.value.str.len; } - if (zend_hash_find(EG(class_table), class_name_strval, class_name_strlen+1, (void **) &EX(Ts)[EX(opline)->result.u.var].EA.class_entry) == FAILURE) { + if (zend_hash_find(EG(class_table), class_name_strval, class_name_strlen+1, (void **) &pce) == FAILURE) { zend_error(E_ERROR, "Class '%s' not found", class_name_strval); + } else { + EX(Ts)[EX(opline)->result.u.var].EA.class_entry = *pce; } if (!is_const) { zval_dtor(&tmp); FREE_OP(EX(Ts), &EX(opline)->op2, EG(free_op2)); } } else { - if (zend_hash_find(&EX(Ts)[EX(opline)->op1.u.var].EA.class_entry->class_table, EX(opline)->op2.u.constant.value.str.val, EX(opline)->op2.u.constant.value.str.len+1, (void **) &EX(Ts)[EX(opline)->result.u.var].EA.class_entry) == FAILURE) { + if (zend_hash_find(&EX(Ts)[EX(opline)->op1.u.var].EA.class_entry->class_table, EX(opline)->op2.u.constant.value.str.val, EX(opline)->op2.u.constant.value.str.len+1, (void **)&pce) == FAILURE) { zend_error(E_ERROR, "Class '%s' not found", EX(opline)->op2.u.constant.value.str.val); + } else { + EX(Ts)[EX(opline)->result.u.var].EA.class_entry = *pce; } } NEXT_OPCODE(); @@ -3026,20 +3032,29 @@ send_by_ref: zval **value; zend_bool isset = 1; HashTable *target_symbol_table; + + if (EX(opline)->op2.u.EA.type == ZEND_FETCH_THIS) { + if (!EG(This)) { + isset = 0; + } else { + isset = 1; + value = &EG(This); + } + } else { + target_symbol_table = zend_get_target_symbol_table(EX(opline), EX(Ts), BP_VAR_IS TSRMLS_CC); - target_symbol_table = zend_get_target_symbol_table(EX(opline), EX(Ts), BP_VAR_IS TSRMLS_CC); - - if (variable->type != IS_STRING) { - tmp = *variable; - zval_copy_ctor(&tmp); - convert_to_string(&tmp); - variable = &tmp; - } - - if (zend_hash_find(target_symbol_table, variable->value.str.val, variable->value.str.len+1, (void **) &value) == FAILURE) { - isset = 0; + if (variable->type != IS_STRING) { + tmp = *variable; + zval_copy_ctor(&tmp); + convert_to_string(&tmp); + variable = &tmp; + } + + if (zend_hash_find(target_symbol_table, variable->value.str.val, variable->value.str.len+1, (void **) &value) == FAILURE) { + isset = 0; + } } - + EX(Ts)[EX(opline)->result.u.var].tmp_var.type = IS_BOOL; switch (EX(opline)->extended_value) { diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 65eb87d52b..944c2aac39 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -100,9 +100,9 @@ static int is_not_internal_function(zend_function *function TSRMLS_DC) } -static int is_not_internal_class(zend_class_entry *ce TSRMLS_DC) +static int is_not_internal_class(zend_class_entry **ce TSRMLS_DC) { - if (ce->type == ZEND_INTERNAL_CLASS) { + if ((*ce)->type == ZEND_INTERNAL_CLASS) { return EG(full_tables_cleanup) ? 0 : ZEND_HASH_APPLY_STOP; } else { return EG(full_tables_cleanup) ? 1 : ZEND_HASH_APPLY_REMOVE; diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index 672a55bf8f..6e5ca2aad2 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -106,8 +106,10 @@ ZEND_API void destroy_zend_function(zend_function *function) } -ZEND_API void destroy_zend_class(zend_class_entry *ce) +ZEND_API void destroy_zend_class(zend_class_entry **pce) { + zend_class_entry *ce = *pce; + if (--(*ce->refcount)>0) { return; } @@ -122,6 +124,7 @@ ZEND_API void destroy_zend_class(zend_class_entry *ce) FREE_HASHTABLE(ce->static_members); zend_hash_destroy(&ce->constants_table); zend_hash_destroy(&ce->class_table); + efree(ce); break; case ZEND_INTERNAL_CLASS: zend_hash_destroy(&ce->default_properties); @@ -133,6 +136,7 @@ ZEND_API void destroy_zend_class(zend_class_entry *ce) free(ce->static_members); zend_hash_destroy(&ce->constants_table); zend_hash_destroy(&ce->class_table); + free(ce); break; } } -- 2.50.1