diff options
| author | Dmitry Stogov <dmitry@php.net> | 2008-07-24 09:42:18 +0000 |
|---|---|---|
| committer | Dmitry Stogov <dmitry@php.net> | 2008-07-24 09:42:18 +0000 |
| commit | feb85801667b7e94b65920801d6b39bcacd32276 (patch) | |
| tree | 6ff179d421b1d0d006a0e336c6905970095a0d6c /Zend/zend_execute_API.c | |
| parent | 6895773affe2fc5f3ef0b45350c2d8a957fdf2fa (diff) | |
| download | php-git-feb85801667b7e94b65920801d6b39bcacd32276.tar.gz | |
LSB parent/self forwarding
Diffstat (limited to 'Zend/zend_execute_API.c')
| -rw-r--r-- | Zend/zend_execute_API.c | 51 |
1 files changed, 37 insertions, 14 deletions
diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 7fbb65a7df..0fb5851586 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -41,7 +41,7 @@ ZEND_API void (*zend_execute_internal)(zend_execute_data *execute_data_ptr, int /* true globals */ ZEND_API zend_fcall_info empty_fcall_info = { 0, NULL, NULL, NULL, NULL, 0, NULL, NULL, 0 }; -ZEND_API zend_fcall_info_cache empty_fcall_info_cache = { 0, NULL, NULL, NULL }; +ZEND_API zend_fcall_info_cache empty_fcall_info_cache = { 0, NULL, NULL, NULL, NULL }; #ifdef ZEND_WIN32 #include <process.h> @@ -684,6 +684,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS zend_class_entry *current_scope; zend_class_entry *current_called_scope; zend_class_entry *calling_scope = NULL; + zend_class_entry *called_scope = NULL; zend_class_entry *check_scope_or_static = NULL; zval *current_this; zend_execute_data execute_data; @@ -758,24 +759,26 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS return FAILURE; } - calling_scope = Z_OBJCE_PP(fci->object_pp); + calling_scope = called_scope = Z_OBJCE_PP(fci->object_pp); fci->function_table = &calling_scope->function_table; EX(object) = *fci->object_pp; } else if (Z_TYPE_PP(fci->object_pp) == IS_STRING) { zend_class_entry **ce; int found = FAILURE; - if (EG(active_op_array) && strcmp(Z_STRVAL_PP(fci->object_pp), "self") == 0) { - if (!EG(active_op_array)->scope) { + if (strcmp(Z_STRVAL_PP(fci->object_pp), "self") == 0) { + if (!EG(active_op_array) || !EG(active_op_array)->scope) { zend_error(E_ERROR, "Cannot access self:: when no class scope is active"); } ce = &(EG(active_op_array)->scope); found = (*ce != NULL?SUCCESS:FAILURE); fci->object_pp = EG(This)?&EG(This):NULL; EX(object) = EG(This); + calling_scope = *ce; + called_scope = EG(called_scope) ? EG(called_scope) : calling_scope; } else if (strcmp(Z_STRVAL_PP(fci->object_pp), "parent") == 0 && EG(active_op_array)) { - if (!EG(active_op_array)->scope) { + if (!EG(active_op_array) || !EG(active_op_array)->scope) { zend_error(E_ERROR, "Cannot access parent:: when no class scope is active"); } if (!EG(active_op_array)->scope->parent) { @@ -785,6 +788,8 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS found = (*ce != NULL?SUCCESS:FAILURE); fci->object_pp = EG(This)?&EG(This):NULL; EX(object) = EG(This); + calling_scope = *ce; + called_scope = EG(called_scope) ? EG(called_scope) : calling_scope; } else if (Z_STRLEN_PP(fci->object_pp) == sizeof("static") - 1 && !memcmp(Z_STRVAL_PP(fci->object_pp), "static", sizeof("static") - 1) ) { @@ -792,9 +797,10 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS zend_error(E_ERROR, "Cannot access static:: when no class scope is active"); } ce = &(EG(called_scope)); - found = (*ce != NULL?SUCCESS:FAILURE); + found = (EG(called_scope) != NULL?SUCCESS:FAILURE); fci->object_pp = EG(This)?&EG(This):NULL; EX(object) = EG(This); + calling_scope = called_scope = EG(called_scope); } else { zend_class_entry *scope; scope = EG(active_op_array) ? EG(active_op_array)->scope : NULL; @@ -811,12 +817,12 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS } else { fci->object_pp = NULL; } + calling_scope = called_scope = *ce; } if (found == FAILURE) return FAILURE; fci->function_table = &(*ce)->function_table; - calling_scope = *ce; } else { zend_error(E_NOTICE, "Non-callable array passed to zend_call_function()"); return FAILURE; @@ -829,6 +835,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS if (Z_TYPE_P(fci->function_name) == IS_OBJECT) { if (zend_get_closure(fci->function_name, &calling_scope, &EX(function_state).function, NULL, &fci->object_pp TSRMLS_CC) == SUCCESS) { + called_scope = calling_scope; goto init_fci_cache; } } else if (Z_TYPE_P(fci->function_name) != IS_STRING) { @@ -865,20 +872,34 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS lcname = zend_str_tolower_dup(cname, clen); /* caution: lcname is not '\0' terminated */ - if (calling_scope && clen == sizeof("self") - 1 && + if (clen == sizeof("self") - 1 && memcmp(lcname, "self", sizeof("self") - 1) == 0 ) { + if (!EG(active_op_array) || !EG(active_op_array)->scope) { + zend_error(E_ERROR, "Cannot access self:: when no class scope is active"); + } ce_child = EG(active_op_array) ? EG(active_op_array)->scope : NULL; - } else if (calling_scope && clen == sizeof("parent") - 1 && + called_scope = EG(called_scope) ? EG(called_scope) : ce_child; + } else if (clen == sizeof("parent") - 1 && memcmp(lcname, "parent", sizeof("parent") - 1) == 0 ) { - ce_child = EG(active_op_array) && EG(active_op_array)->scope ? EG(scope)->parent : NULL; + if (!EG(active_op_array) || !EG(active_op_array)->scope) { + zend_error(E_ERROR, "Cannot access parent:: when no class scope is active"); + } + if (!EG(active_op_array)->scope->parent) { + zend_error(E_ERROR, "Cannot access parent:: when current class scope has no parent"); + } + ce_child = EG(active_op_array) && EG(active_op_array)->scope ? EG(active_op_array)->scope->parent : NULL; + called_scope = EG(called_scope) ? EG(called_scope) : ce_child; } else if (clen == sizeof("static") - 1 && memcmp(lcname, "static", sizeof("static") - 1) ) { - ce_child = EG(called_scope); + if (!EG(called_scope)) { + zend_error(E_ERROR, "Cannot access static:: when no class scope is active"); + } + called_scope = ce_child = EG(called_scope); } else if (zend_lookup_class(lcname, clen, &pce TSRMLS_CC) == SUCCESS) { - ce_child = *pce; + called_scope = ce_child = *pce; } efree(lcname); @@ -949,11 +970,13 @@ init_fci_cache: fci_cache->function_handler = EX(function_state).function; fci_cache->object_pp = fci->object_pp; fci_cache->calling_scope = calling_scope; + fci_cache->called_scope = called_scope; fci_cache->initialized = 1; } } else { EX(function_state).function = fci_cache->function_handler; calling_scope = fci_cache->calling_scope; + called_scope = fci_cache->called_scope; fci->object_pp = fci_cache->object_pp; EX(object) = fci->object_pp ? *fci->object_pp : NULL; if (fci->object_pp && *fci->object_pp && Z_TYPE_PP(fci->object_pp) == IS_OBJECT @@ -1048,8 +1071,8 @@ init_fci_cache: current_this = EG(This); current_called_scope = EG(called_scope); - if (calling_scope) { - EG(called_scope) = calling_scope; + if (called_scope) { + EG(called_scope) = called_scope; } else if (EX(function_state).function->type != ZEND_INTERNAL_FUNCTION) { EG(called_scope) = NULL; } |
