Skip to content

Commit 5c56abb

Browse files
committed
Fixed bug #50261 (Crash When Calling Parent Constructor with call_user_func())
1 parent 2a3ec70 commit 5c56abb

File tree

2 files changed

+51
-11
lines changed

2 files changed

+51
-11
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ PHP NEWS
3030
calling function). (Felipe)
3131
- Fixed bug #50267 (get_browser(null) does not use HTTP_USER_AGENT). (Jani)
3232
- Fixed bug #50266 (conflicting types for llabs). (Jani)
33+
- Fixed bug #50261 (Crash When Calling Parent Constructor with
34+
call_user_func()). (Dmitry)
3335
- Fixed bug #50255 (isset() and empty() silently casts array to object).
3436
(Felipe)
3537
- Fixed bug #50240 (pdo_mysql.default_socket in php.ini shouldn't used

Zend/zend_API.c

Lines changed: 49 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2117,7 +2117,7 @@ void module_destructor(zend_module_entry *module) /* {{{ */
21172117
#if HAVE_LIBDL
21182118
#if !(defined(NETWARE) && defined(APACHE_1_BUILD))
21192119
if (module->handle) {
2120-
DL_UNLOAD(module->handle);
2120+
// DL_UNLOAD(module->handle);
21212121
}
21222122
#endif
21232123
#endif
@@ -2335,12 +2335,13 @@ ZEND_API int zend_disable_class(char *class_name, uint class_name_length TSRMLS_
23352335
}
23362336
/* }}} */
23372337

2338-
static int zend_is_callable_check_class(const char *name, int name_len, zend_fcall_info_cache *fcc, char **error TSRMLS_DC) /* {{{ */
2338+
static int zend_is_callable_check_class(const char *name, int name_len, zend_fcall_info_cache *fcc, int *strict_class, char **error TSRMLS_DC) /* {{{ */
23392339
{
23402340
int ret = 0;
23412341
zend_class_entry **pce;
23422342
char *lcname = zend_str_tolower_dup(name, name_len);
23432343

2344+
*strict_class = 0;
23442345
if (name_len == sizeof("self") - 1 &&
23452346
!memcmp(lcname, "self", sizeof("self") - 1)) {
23462347
if (!EG(scope)) {
@@ -2365,6 +2366,7 @@ static int zend_is_callable_check_class(const char *name, int name_len, zend_fca
23652366
if (!fcc->object_ptr) {
23662367
fcc->object_ptr = EG(This);
23672368
}
2369+
*strict_class = 1;
23682370
ret = 1;
23692371
}
23702372
} else if (name_len == sizeof("static") - 1 &&
@@ -2377,6 +2379,7 @@ static int zend_is_callable_check_class(const char *name, int name_len, zend_fca
23772379
if (!fcc->object_ptr) {
23782380
fcc->object_ptr = EG(This);
23792381
}
2382+
*strict_class = 1;
23802383
ret = 1;
23812384
}
23822385
} else if (zend_lookup_class_ex(name, name_len, 1, &pce TSRMLS_CC) == SUCCESS) {
@@ -2391,6 +2394,7 @@ static int zend_is_callable_check_class(const char *name, int name_len, zend_fca
23912394
} else {
23922395
fcc->called_scope = fcc->object_ptr ? Z_OBJCE_P(fcc->object_ptr) : fcc->calling_scope;
23932396
}
2397+
*strict_class = 1;
23942398
ret = 1;
23952399
} else {
23962400
if (error) zend_spprintf(error, 0, "class '%.*s' not found", name_len, name);
@@ -2401,7 +2405,7 @@ static int zend_is_callable_check_class(const char *name, int name_len, zend_fca
24012405
/* }}} */
24022406

24032407

2404-
static int zend_is_callable_check_func(int check_flags, zval *callable, zend_fcall_info_cache *fcc, char **error TSRMLS_DC) /* {{{ */
2408+
static int zend_is_callable_check_func(int check_flags, zval *callable, zend_fcall_info_cache *fcc, int strict_class, char **error TSRMLS_DC) /* {{{ */
24052409
{
24062410
zend_class_entry *ce_org = fcc->calling_scope;
24072411
int retval = 0;
@@ -2459,7 +2463,7 @@ static int zend_is_callable_check_func(int check_flags, zval *callable, zend_fca
24592463
EG(scope) = ce_org;
24602464
}
24612465

2462-
if (!zend_is_callable_check_class(Z_STRVAL_P(callable), clen, fcc, error TSRMLS_CC)) {
2466+
if (!zend_is_callable_check_class(Z_STRVAL_P(callable), clen, fcc, &strict_class, error TSRMLS_CC)) {
24632467
EG(scope) = last_scope;
24642468
return 0;
24652469
}
@@ -2486,7 +2490,15 @@ static int zend_is_callable_check_func(int check_flags, zval *callable, zend_fca
24862490
}
24872491

24882492
lmname = zend_str_tolower_dup(mname, mlen);
2489-
if (zend_hash_find(ftable, lmname, mlen+1, (void**)&fcc->function_handler) == SUCCESS) {
2493+
if (strict_class &&
2494+
fcc->calling_scope &&
2495+
mlen == sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1 &&
2496+
!memcmp(lmname, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME))) {
2497+
fcc->function_handler = fcc->calling_scope->constructor;
2498+
if (fcc->function_handler) {
2499+
retval = 1;
2500+
}
2501+
} else if (zend_hash_find(ftable, lmname, mlen+1, (void**)&fcc->function_handler) == SUCCESS) {
24902502
retval = 1;
24912503
if ((fcc->function_handler->op_array.fn_flags & ZEND_ACC_CHANGED) &&
24922504
EG(scope) &&
@@ -2520,11 +2532,36 @@ static int zend_is_callable_check_func(int check_flags, zval *callable, zend_fca
25202532
} else {
25212533
get_function_via_handler:
25222534
if (fcc->object_ptr && fcc->calling_scope == ce_org) {
2523-
if (Z_OBJ_HT_P(fcc->object_ptr)->get_method) {
2535+
if (strict_class && ce_org->__call) {
2536+
fcc->function_handler = emalloc(sizeof(zend_internal_function));
2537+
fcc->function_handler->internal_function.type = ZEND_INTERNAL_FUNCTION;
2538+
fcc->function_handler->internal_function.module = ce_org->module;
2539+
fcc->function_handler->internal_function.handler = zend_std_call_user_call;
2540+
fcc->function_handler->internal_function.arg_info = NULL;
2541+
fcc->function_handler->internal_function.num_args = 0;
2542+
fcc->function_handler->internal_function.scope = ce_org;
2543+
fcc->function_handler->internal_function.fn_flags = ZEND_ACC_CALL_VIA_HANDLER;
2544+
fcc->function_handler->internal_function.function_name = estrndup(mname, mlen);
2545+
fcc->function_handler->internal_function.pass_rest_by_reference = 0;
2546+
fcc->function_handler->internal_function.return_reference = ZEND_RETURN_VALUE;
2547+
call_via_handler = 1;
2548+
retval = 1;
2549+
} else if (Z_OBJ_HT_P(fcc->object_ptr)->get_method) {
25242550
fcc->function_handler = Z_OBJ_HT_P(fcc->object_ptr)->get_method(&fcc->object_ptr, mname, mlen TSRMLS_CC);
25252551
if (fcc->function_handler) {
2526-
retval = 1;
2527-
call_via_handler = (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0;
2552+
if (strict_class &&
2553+
(!fcc->function_handler->common.scope ||
2554+
!instanceof_function(ce_org, fcc->function_handler->common.scope TSRMLS_CC))) {
2555+
if ((fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0) {
2556+
if (fcc->function_handler->type != ZEND_OVERLOADED_FUNCTION) {
2557+
efree(fcc->function_handler->common.function_name);
2558+
}
2559+
efree(fcc->function_handler);
2560+
}
2561+
} else {
2562+
retval = 1;
2563+
call_via_handler = (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0;
2564+
}
25282565
}
25292566
}
25302567
} else if (fcc->calling_scope) {
@@ -2680,7 +2717,7 @@ ZEND_API zend_bool zend_is_callable_ex(zval *callable, zval *object_ptr, uint ch
26802717
return 1;
26812718
}
26822719

2683-
ret = zend_is_callable_check_func(check_flags, callable, fcc, error TSRMLS_CC);
2720+
ret = zend_is_callable_check_func(check_flags, callable, fcc, 0, error TSRMLS_CC);
26842721
if (fcc == &fcc_local &&
26852722
fcc->function_handler &&
26862723
((fcc->function_handler->type == ZEND_INTERNAL_FUNCTION &&
@@ -2698,6 +2735,7 @@ ZEND_API zend_bool zend_is_callable_ex(zval *callable, zval *object_ptr, uint ch
26982735
{
26992736
zval **method = NULL;
27002737
zval **obj = NULL;
2738+
int strict_class = 0;
27012739

27022740
if (zend_hash_num_elements(Z_ARRVAL_P(callable)) == 2) {
27032741
zend_hash_index_find(Z_ARRVAL_P(callable), 0, (void **) &obj);
@@ -2725,7 +2763,7 @@ ZEND_API zend_bool zend_is_callable_ex(zval *callable, zval *object_ptr, uint ch
27252763
return 1;
27262764
}
27272765

2728-
if (!zend_is_callable_check_class(Z_STRVAL_PP(obj), Z_STRLEN_PP(obj), fcc, error TSRMLS_CC)) {
2766+
if (!zend_is_callable_check_class(Z_STRVAL_PP(obj), Z_STRLEN_PP(obj), fcc, &strict_class, error TSRMLS_CC)) {
27292767
return 0;
27302768
}
27312769

@@ -2757,7 +2795,7 @@ ZEND_API zend_bool zend_is_callable_ex(zval *callable, zval *object_ptr, uint ch
27572795
}
27582796
}
27592797

2760-
ret = zend_is_callable_check_func(check_flags, *method, fcc, error TSRMLS_CC);
2798+
ret = zend_is_callable_check_func(check_flags, *method, fcc, strict_class, error TSRMLS_CC);
27612799
if (fcc == &fcc_local &&
27622800
fcc->function_handler &&
27632801
((fcc->function_handler->type == ZEND_INTERNAL_FUNCTION &&

0 commit comments

Comments
 (0)