summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcus Boerger <helly@php.net>2004-09-09 09:51:43 +0000
committerMarcus Boerger <helly@php.net>2004-09-09 09:51:43 +0000
commitbe24e2455c1016cb0fc5767c4719d64261903166 (patch)
treeb337b63450a75eeb8cdd9c99d43ba869c8e59a63
parent8e56b3b6a6fbd87a68630fa5703c8eb1394bc0ed (diff)
downloadphp-git-be24e2455c1016cb0fc5767c4719d64261903166.tar.gz
- Check signature of magic methods
- Register __get/__set/__call for internal classes
-rw-r--r--Zend/zend_API.c83
-rw-r--r--Zend/zend_API.h1
-rw-r--r--Zend/zend_compile.c23
3 files changed, 81 insertions, 26 deletions
diff --git a/Zend/zend_API.c b/Zend/zend_API.c
index 41ebc35d2e..1733720130 100644
--- a/Zend/zend_API.c
+++ b/Zend/zend_API.c
@@ -1218,6 +1218,29 @@ ZEND_API int zend_startup_module(zend_module_entry *module)
return zend_register_module_ex(module TSRMLS_CC);
}
+ZEND_API void zend_check_magic_method_implementation(zend_class_entry *ce, zend_function *fptr, int error_type TSRMLS_DC)
+{
+ char lcname[16];
+ int name_len;
+
+ /* we don't care if the function name is longer, in fact lowercasing only
+ * the beginning of the name speeds up the check process */
+ name_len = strlen(fptr->common.function_name);
+ zend_str_tolower_copy(lcname, fptr->common.function_name, MIN(name_len, sizeof(lcname)-1));
+ lcname[sizeof(lcname)-1] = '\0'; /* zend_str_tolower_copy won't necessarily set the zero byte */
+
+ if (name_len == sizeof(ZEND_DESTRUCTOR_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_DESTRUCTOR_FUNC_NAME, sizeof(ZEND_DESTRUCTOR_FUNC_NAME)) && fptr->common.num_args != 0) {
+ zend_error(error_type, "Destuctor %s::%s() cannot take arguments", ce->name, ZEND_DESTRUCTOR_FUNC_NAME);
+ } else if (name_len == sizeof(ZEND_CLONE_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME)) && fptr->common.num_args != 0) {
+ zend_error(error_type, "Method %s::%s() cannot accept any arguments", ce->name, ZEND_CLONE_FUNC_NAME);
+ } else if (name_len == sizeof(ZEND_GET_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME)) && fptr->common.num_args != 1) {
+ zend_error(error_type, "Method %s::%s() must take exactly 1 argument", ce->name, ZEND_GET_FUNC_NAME);
+ } else if (name_len == sizeof(ZEND_SET_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME)) && fptr->common.num_args != 2) {
+ zend_error(error_type, "Method %s::%s() must take exactly 2 arguments", ce->name, ZEND_SET_FUNC_NAME);
+ } else if (name_len == sizeof(ZEND_CALL_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)) && fptr->common.num_args != 2) {
+ zend_error(error_type, "Method %s::%s() must take exactly 2 arguments", ce->name, ZEND_CALL_FUNC_NAME);
+ }
+}
/* registers all functions in *library_functions in the function hash */
ZEND_API int zend_register_functions(zend_class_entry *scope, zend_function_entry *functions, HashTable *function_table, int type TSRMLS_DC)
@@ -1228,9 +1251,11 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, zend_function_entr
int count=0, unload=0;
HashTable *target_function_table = function_table;
int error_type;
- zend_function *ctor = NULL, *dtor = NULL, *clone = NULL;
+ zend_function *ctor = NULL, *dtor = NULL, *clone = NULL, *__get = NULL, *__set = NULL, *__call = NULL;
char *lowercase_name;
int fname_len;
+ char *lc_class_name;
+ int class_name_len;
if (type==MODULE_PERSISTENT) {
error_type = E_CORE_WARNING;
@@ -1242,6 +1267,11 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, zend_function_entr
target_function_table = CG(function_table);
}
internal_function->type = ZEND_INTERNAL_FUNCTION;
+
+ if (scope) {
+ class_name_len = strlen(scope->name);
+ lc_class_name = zend_str_tolower_dup(scope->name, class_name_len);
+ }
while (ptr->fname) {
internal_function->handler = ptr->handler;
@@ -1311,18 +1341,28 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, zend_function_entr
* If it's an old-style constructor, store it only if we don't have
* a constructor already.
*/
- if (!strcmp(ptr->fname, scope->name) && !ctor) {
+ if ((fname_len == class_name_len) && !memcmp(lowercase_name, lc_class_name, class_name_len+1) && !ctor) {
ctor = reg_function;
- } else if (!strcmp(ptr->fname, ZEND_CONSTRUCTOR_FUNC_NAME)) {
+ } else if ((fname_len == sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME))) {
ctor = reg_function;
- } else if (!strcmp(ptr->fname, ZEND_DESTRUCTOR_FUNC_NAME)) {
+ } else if ((fname_len == sizeof(ZEND_DESTRUCTOR_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_DESTRUCTOR_FUNC_NAME, sizeof(ZEND_DESTRUCTOR_FUNC_NAME))) {
dtor = reg_function;
if (internal_function->num_args) {
zend_error(error_type, "Destructor %s::%s() cannot take arguments", scope->name, ptr->fname);
}
-
- } else if (!strcmp(ptr->fname, ZEND_CLONE_FUNC_NAME)) {
+ } else if ((fname_len == sizeof(ZEND_CLONE_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME))) {
clone = reg_function;
+ } else if ((fname_len == sizeof(ZEND_CALL_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME))) {
+ __call = reg_function;
+ } else if ((fname_len == sizeof(ZEND_GET_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME))) {
+ __get = reg_function;
+ } else if ((fname_len == sizeof(ZEND_SET_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME))) {
+ __set = reg_function;
+ } else {
+ reg_function = NULL;
+ }
+ if (reg_function) {
+ zend_check_magic_method_implementation(scope, reg_function, error_type TSRMLS_CC);
}
}
ptr++;
@@ -1330,6 +1370,9 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, zend_function_entr
free_alloca(lowercase_name);
}
if (unload) { /* before unloading, display all remaining bad function in the module */
+ if (scope) {
+ efree(lc_class_name);
+ }
while (ptr->fname) {
if (zend_hash_exists(target_function_table, ptr->fname, strlen(ptr->fname)+1)) {
zend_error(error_type, "Function registration failed - duplicate name - %s", ptr->fname);
@@ -1343,27 +1386,49 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, zend_function_entr
scope->constructor = ctor;
scope->destructor = dtor;
scope->clone = clone;
+ scope->__call = __call;
+ scope->__get = __get;
+ scope->__set = __set;
if (ctor) {
ctor->common.fn_flags |= ZEND_ACC_CTOR;
if (ctor->common.fn_flags & ZEND_ACC_STATIC) {
- zend_error(error_type, "Constructor %s::%s() cannot be static", ctor->common.scope->name, ctor->common.function_name);
+ zend_error(error_type, "Constructor %s::%s() cannot be static", scope->name, ctor->common.function_name);
}
ctor->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
}
if (dtor) {
dtor->common.fn_flags |= ZEND_ACC_DTOR;
if (dtor->common.fn_flags & ZEND_ACC_STATIC) {
- zend_error(error_type, "Destructor %s::%s() cannot be static", dtor->common.scope->name, dtor->common.function_name);
+ zend_error(error_type, "Destructor %s::%s() cannot be static", scope->name, dtor->common.function_name);
}
dtor->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
}
if (clone) {
clone->common.fn_flags |= ZEND_ACC_CLONE;
if (clone->common.fn_flags & ZEND_ACC_STATIC) {
- zend_error(error_type, "Constructor %s::%s() cannot be static", clone->common.scope->name, clone->common.function_name);
+ zend_error(error_type, "Constructor %s::%s() cannot be static", scope->name, clone->common.function_name);
}
clone->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
}
+ if (__call) {
+ if (__call->common.fn_flags & ZEND_ACC_STATIC) {
+ zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __call->common.function_name);
+ }
+ __call->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
+ }
+ if (__get) {
+ if (__get->common.fn_flags & ZEND_ACC_STATIC) {
+ zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __get->common.function_name);
+ }
+ __get->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
+ }
+ if (__set) {
+ if (__set->common.fn_flags & ZEND_ACC_STATIC) {
+ zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __set->common.function_name);
+ }
+ __set->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
+ }
+ efree(lc_class_name);
}
return SUCCESS;
}
diff --git a/Zend/zend_API.h b/Zend/zend_API.h
index 313dd217ee..12312938c0 100644
--- a/Zend/zend_API.h
+++ b/Zend/zend_API.h
@@ -168,6 +168,7 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, zend_function_entr
ZEND_API void zend_unregister_functions(zend_function_entry *functions, int count, HashTable *function_table TSRMLS_DC);
ZEND_API int zend_register_module(zend_module_entry *module_entry);
ZEND_API int zend_register_module_ex(zend_module_entry *module TSRMLS_DC);
+ZEND_API void zend_check_magic_method_implementation(zend_class_entry *ce, zend_function *fptr, int error_type TSRMLS_DC);
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_ex(zend_class_entry *class_entry, zend_class_entry *parent_ce, char *parent_name TSRMLS_DC);
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 55049cef6c..5710115689 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -1103,25 +1103,14 @@ void zend_do_end_function_declaration(znode *function_token TSRMLS_DC)
pass_two(CG(active_op_array) TSRMLS_CC);
- /* we don't care if the function name is longer, in fact lowercasing only
- * the beginning of the name speeds up the check process */
- name_len = strlen(CG(active_op_array)->function_name);
- zend_str_tolower_copy(lcname, CG(active_op_array)->function_name, MIN(name_len, sizeof(lcname)-1));
- lcname[sizeof(lcname)-1] = '\0'; /* zend_str_tolower_copy won't necessarily set the zero byte */
-
if (CG(active_class_entry)) {
- if (name_len == sizeof(ZEND_DESTRUCTOR_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_DESTRUCTOR_FUNC_NAME, sizeof(ZEND_DESTRUCTOR_FUNC_NAME)) && CG(active_op_array)->num_args != 0) {
- zend_error(E_COMPILE_ERROR, "Destuctor %s::%s() cannot take arguments", CG(active_class_entry)->name, ZEND_DESTRUCTOR_FUNC_NAME);
- } else if (name_len == sizeof(ZEND_CLONE_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME)) && CG(active_op_array)->num_args != 0) {
- zend_error(E_COMPILE_ERROR, "Method %s::%s() cannot accept any arguments", CG(active_class_entry)->name, ZEND_CLONE_FUNC_NAME);
- } else if (name_len == sizeof(ZEND_GET_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME)) && CG(active_op_array)->num_args != 1) {
- zend_error(E_COMPILE_ERROR, "Method %s::%s() must take exactly 1 argument", CG(active_class_entry)->name, ZEND_GET_FUNC_NAME);
- } else if (name_len == sizeof(ZEND_SET_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME)) && CG(active_op_array)->num_args != 2) {
- zend_error(E_COMPILE_ERROR, "Method %s::%s() must take exactly 2 arguments", CG(active_class_entry)->name, ZEND_SET_FUNC_NAME);
- } else if (name_len == sizeof(ZEND_CALL_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)) && CG(active_op_array)->num_args != 2) {
- zend_error(E_COMPILE_ERROR, "Method %s::%s() must take exactly 2 arguments", CG(active_class_entry)->name, ZEND_CALL_FUNC_NAME);
- }
+ zend_check_magic_method_implementation(CG(active_class_entry), (zend_function*)CG(active_op_array), E_COMPILE_ERROR TSRMLS_CC);
} else {
+ /* we don't care if the function name is longer, in fact lowercasing only
+ * the beginning of the name speeds up the check process */
+ name_len = strlen(CG(active_op_array)->function_name);
+ zend_str_tolower_copy(lcname, CG(active_op_array)->function_name, MIN(name_len, sizeof(lcname)-1));
+ lcname[sizeof(lcname)-1] = '\0'; /* zend_str_tolower_copy won't necessarily set the zero byte */
if (name_len == sizeof(ZEND_AUTOLOAD_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_AUTOLOAD_FUNC_NAME, sizeof(ZEND_AUTOLOAD_FUNC_NAME)) && CG(active_op_array)->num_args != 1) {
zend_error(E_COMPILE_ERROR, "%s() must take exactly 1 argument", ZEND_AUTOLOAD_FUNC_NAME);
}