}
/* }}} */
-static int zend_is_callable_check_class(zend_uchar utype, const zstr name, int name_len, zend_fcall_info_cache *fcc, char **error TSRMLS_DC) /* {{{ */
+static int zend_is_callable_check_class(zend_uchar utype, const zstr name, int name_len, zend_fcall_info_cache *fcc, int *strict_class, char **error TSRMLS_DC) /* {{{ */
{
int ret = 0;
zend_class_entry **pce;
unsigned int lcname_len;
zstr lcname = zend_u_str_case_fold(utype, name, name_len, 1, &lcname_len);
+ *strict_class = 0;
if (lcname_len == sizeof("self") - 1 &&
ZEND_U_EQUAL(utype, lcname, lcname_len, "self", sizeof("self") - 1)) {
if (!EG(scope)) {
if (!fcc->object_ptr) {
fcc->object_ptr = EG(This);
}
+ *strict_class = 1;
ret = 1;
}
} else if (lcname_len == sizeof("parent") - 1 &&
if (!fcc->object_ptr) {
fcc->object_ptr = EG(This);
}
+ *strict_class = 1;
ret = 1;
}
} else if (lcname_len == sizeof("static") - 1 &&
} else {
fcc->called_scope = fcc->object_ptr ? Z_OBJCE_P(fcc->object_ptr) : fcc->calling_scope;
}
+ *strict_class = 1;
ret = 1;
} else {
if (error) {
}
/* }}} */
-static int zend_is_callable_check_func(int check_flags, zval *callable, zend_fcall_info_cache *fcc, char **error TSRMLS_DC) /* {{{ */
+static int zend_is_callable_check_func(int check_flags, zval *callable, zend_fcall_info_cache *fcc, int strict_class, char **error TSRMLS_DC) /* {{{ */
{
zend_class_entry *ce_org = fcc->calling_scope;
int retval = 0;
EG(scope) = ce_org;
}
- if (!zend_is_callable_check_class(Z_TYPE_P(callable), Z_UNIVAL_P(callable), clen, fcc, error TSRMLS_CC)) {
+ if (!zend_is_callable_check_class(Z_TYPE_P(callable), Z_UNIVAL_P(callable), clen, fcc, &strict_class, error TSRMLS_CC)) {
EG(scope) = last_scope;
return 0;
}
}
lmname = zend_u_str_case_fold(Z_TYPE_P(callable), mname, mlen, 1, &lmlen);
- if (zend_u_hash_find(ftable, Z_TYPE_P(callable), lmname, lmlen+1, (void**)&fcc->function_handler) == SUCCESS) {
+ if (strict_class &&
+ fcc->calling_scope &&
+ mlen == sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1 &&
+ ZEND_U_EQUAL(Z_TYPE_P(callable), lmname, lmlen, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1)) {
+ fcc->function_handler = fcc->calling_scope->constructor;
+ if (fcc->function_handler) {
+ retval = 1;
+ }
+ } else if (zend_u_hash_find(ftable, Z_TYPE_P(callable), lmname, lmlen+1, (void**)&fcc->function_handler) == SUCCESS) {
retval = 1;
if ((fcc->function_handler->op_array.fn_flags & ZEND_ACC_CHANGED) &&
EG(scope) &&
} else {
get_function_via_handler:
if (fcc->object_ptr && fcc->calling_scope == ce_org) {
- if (Z_OBJ_HT_P(fcc->object_ptr)->get_method) {
+ if (strict_class && ce_org->__call) {
+ fcc->function_handler = emalloc(sizeof(zend_internal_function));
+ fcc->function_handler->internal_function.type = ZEND_INTERNAL_FUNCTION;
+ fcc->function_handler->internal_function.module = ce_org->module;
+ fcc->function_handler->internal_function.handler = zend_std_call_user_call;
+ fcc->function_handler->internal_function.arg_info = NULL;
+ fcc->function_handler->internal_function.num_args = 0;
+ fcc->function_handler->internal_function.scope = ce_org;
+ fcc->function_handler->internal_function.fn_flags = ZEND_ACC_CALL_VIA_HANDLER;
+ if (Z_TYPE_P(callable) == IS_STRING) {
+ fcc->function_handler->internal_function.function_name.s = estrndup(mname.s, lmlen);
+ } else {
+ fcc->function_handler->internal_function.function_name.u = eustrndup(mname.u, lmlen);
+ }
+ fcc->function_handler->internal_function.pass_rest_by_reference = 0;
+ fcc->function_handler->internal_function.return_reference = ZEND_RETURN_VALUE;
+ call_via_handler = 1;
+ retval = 1;
+ } else if (Z_OBJ_HT_P(fcc->object_ptr)->get_method) {
zstr method = mname;
int method_len = mlen;
efree(method.v);
}
if (fcc->function_handler) {
+ if (strict_class &&
+ (!fcc->function_handler->common.scope ||
+ !instanceof_function(ce_org, fcc->function_handler->common.scope TSRMLS_CC))) {
+ if ((fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0) {
+ if (fcc->function_handler->type != ZEND_OVERLOADED_FUNCTION) {
+ efree(fcc->function_handler->common.function_name.v);
+ }
+ efree(fcc->function_handler);
+ }
+ } else {
+ retval = 1;
+ call_via_handler = (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0;
+ }
retval = 1;
call_via_handler = (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0;
}
return 1;
}
- ret = zend_is_callable_check_func(check_flags, callable, fcc, error TSRMLS_CC);
+ ret = zend_is_callable_check_func(check_flags, callable, fcc, 0, error TSRMLS_CC);
if (fcc == &fcc_local &&
fcc->function_handler &&
((fcc->function_handler->type == ZEND_INTERNAL_FUNCTION &&
{
zval **method;
zval **obj = NULL;
+ int strict_class = 0;
if (zend_hash_num_elements(Z_ARRVAL_P(callable)) == 2 &&
zend_hash_index_find(Z_ARRVAL_P(callable), 0, (void **) &obj) == SUCCESS &&
return 1;
}
- if (!zend_is_callable_check_class(Z_TYPE_PP(obj), Z_UNIVAL_PP(obj), Z_UNILEN_PP(obj), fcc, error TSRMLS_CC)) {
+ if (!zend_is_callable_check_class(Z_TYPE_PP(obj), Z_UNIVAL_PP(obj), Z_UNILEN_PP(obj), fcc, &strict_class, error TSRMLS_CC)) {
return 0;
}
} else {
}
}
- ret = zend_is_callable_check_func(check_flags, *method, fcc, error TSRMLS_CC);
+ ret = zend_is_callable_check_func(check_flags, *method, fcc, strict_class, error TSRMLS_CC);
if (fcc == &fcc_local &&
fcc->function_handler &&
((fcc->function_handler->type == ZEND_INTERNAL_FUNCTION &&