Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 52 additions & 71 deletions Zend/zend_API.c
Original file line number Diff line number Diff line change
Expand Up @@ -3818,62 +3818,32 @@ ZEND_API void zend_release_fcall_info_cache(zend_fcall_info_cache *fcc) {
}
}

static zend_always_inline bool zend_is_callable_check_func(const zval *callable, const zend_execute_data *frame, zend_fcall_info_cache *fcc, bool strict_class, char **error, bool suppress_deprecation) /* {{{ */
static zend_always_inline bool zend_is_method_callable(zend_string *callable, const zend_execute_data *frame, zend_fcall_info_cache *fcc, bool strict_class, char **error, bool suppress_deprecation) /* {{{ */
{
zend_class_entry *ce_org = fcc->calling_scope;
bool retval = false;
zend_string *mname, *cname;
zend_string *lmname;
zend_string *mname;
const char *colon;
size_t clen;
HashTable *ftable;
int call_via_handler = 0;
bool call_via_handler = false;
zend_class_entry *scope;
zval *zv;
ALLOCA_FLAG(use_heap)

fcc->calling_scope = NULL;

if (!ce_org) {
zend_function *func;
zend_string *lmname;

/* Check if function with given name exists.
* This may be a compound name that includes namespace name */
if (UNEXPECTED(Z_STRVAL_P(callable)[0] == '\\')) {
/* Skip leading \ */
ZSTR_ALLOCA_ALLOC(lmname, Z_STRLEN_P(callable) - 1, use_heap);
zend_str_tolower_copy(ZSTR_VAL(lmname), Z_STRVAL_P(callable) + 1, Z_STRLEN_P(callable) - 1);
func = zend_fetch_function(lmname);
ZSTR_ALLOCA_FREE(lmname, use_heap);
} else {
lmname = Z_STR_P(callable);
func = zend_fetch_function(lmname);
if (!func) {
ZSTR_ALLOCA_ALLOC(lmname, Z_STRLEN_P(callable), use_heap);
zend_str_tolower_copy(ZSTR_VAL(lmname), Z_STRVAL_P(callable), Z_STRLEN_P(callable));
func = zend_fetch_function(lmname);
ZSTR_ALLOCA_FREE(lmname, use_heap);
}
}
if (EXPECTED(func != NULL)) {
fcc->function_handler = func;
return 1;
}
}

/* Split name into class/namespace and method/function names */
if ((colon = zend_memrchr(Z_STRVAL_P(callable), ':', Z_STRLEN_P(callable))) != NULL &&
colon > Z_STRVAL_P(callable) &&
if ((colon = zend_memrchr(ZSTR_VAL(callable), ':', ZSTR_LEN(callable))) != NULL &&
colon > ZSTR_VAL(callable) &&
*(colon-1) == ':'
) {
size_t mlen;

colon--;
clen = colon - Z_STRVAL_P(callable);
mlen = Z_STRLEN_P(callable) - clen - 2;

if (colon == Z_STRVAL_P(callable)) {
size_t class_name_len = colon - ZSTR_VAL(callable);
mlen = ZSTR_LEN(callable) - class_name_len - 2;

if (colon == ZSTR_VAL(callable)) {
if (error) *error = estrdup("invalid function name");
return 0;
}
Expand All @@ -3886,9 +3856,9 @@ static zend_always_inline bool zend_is_callable_check_func(const zval *callable,
scope = get_scope(frame);
}

cname = zend_string_init_interned(Z_STRVAL_P(callable), clen, 0);
if (ZSTR_HAS_CE_CACHE(cname) && ZSTR_GET_CE_CACHE(cname)) {
fcc->calling_scope = ZSTR_GET_CE_CACHE(cname);
zend_string *class_name = zend_string_init_interned(ZSTR_VAL(callable), class_name_len, 0);
if (ZSTR_HAS_CE_CACHE(class_name) && ZSTR_GET_CE_CACHE(class_name)) {
fcc->calling_scope = ZSTR_GET_CE_CACHE(class_name);
if (scope && !fcc->object) {
zend_object *object = zend_get_this_object(frame);

Expand All @@ -3904,11 +3874,11 @@ static zend_always_inline bool zend_is_callable_check_func(const zval *callable,
fcc->called_scope = fcc->object ? fcc->object->ce : fcc->calling_scope;
}
strict_class = true;
} else if (!zend_is_callable_check_class(cname, scope, frame, fcc, &strict_class, error, suppress_deprecation || ce_org != NULL)) {
zend_string_release_ex(cname, 0);
} else if (!zend_is_callable_check_class(class_name, scope, frame, fcc, &strict_class, error, suppress_deprecation || ce_org != NULL)) {
zend_string_release_ex(class_name, 0);
return 0;
}
zend_string_release_ex(cname, 0);
zend_string_release_ex(class_name, 0);

ftable = &fcc->calling_scope->function_table;
if (ce_org && !instanceof_function(ce_org, fcc->calling_scope)) {
Expand All @@ -3918,24 +3888,24 @@ static zend_always_inline bool zend_is_callable_check_func(const zval *callable,
if (ce_org && !suppress_deprecation) {
zend_error(E_DEPRECATED,
"Callables of the form [\"%s\", \"%s\"] are deprecated",
ZSTR_VAL(ce_org->name), Z_STRVAL_P(callable));
ZSTR_VAL(ce_org->name), ZSTR_VAL(callable));
}
mname = zend_string_init(Z_STRVAL_P(callable) + clen + 2, mlen, 0);
mname = zend_string_init(ZSTR_VAL(callable) + class_name_len + 2, mlen, 0);
} else if (ce_org) {
/* Try to fetch find static method of given class. */
mname = Z_STR_P(callable);
mname = callable;
zend_string_addref(mname);
ftable = &ce_org->function_table;
fcc->calling_scope = ce_org;
} else {
/* We already checked for plain function before. */
if (error) {
zend_spprintf(error, 0, "function \"%s\" not found or invalid function name", Z_STRVAL_P(callable));
zend_spprintf(error, 0, "function \"%s\" not found or invalid function name", ZSTR_VAL(callable));
}
return 0;
}

lmname = zend_string_tolower(mname);
zend_string *lmname = zend_string_tolower(mname);
if (strict_class &&
fcc->calling_scope &&
zend_string_equals_literal(lmname, ZEND_CONSTRUCTOR_FUNC_NAME)) {
Expand Down Expand Up @@ -3980,7 +3950,7 @@ static zend_always_inline bool zend_is_callable_check_func(const zval *callable,
if (fcc->object && fcc->calling_scope == ce_org) {
if (strict_class && ce_org->__call) {
fcc->function_handler = zend_get_call_trampoline_func(ce_org->__call, mname);
call_via_handler = 1;
call_via_handler = true;
retval = true;
} else {
fcc->function_handler = fcc->object->handlers->get_method(&fcc->object, mname, NULL);
Expand Down Expand Up @@ -4198,22 +4168,30 @@ ZEND_API bool zend_is_callable_at_frame(
again:
switch (Z_TYPE_P(callable)) {
case IS_STRING:
if (object) {
/* First check for a normal function */
if (!object) {
if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) {
return true;
}

zend_function *func = zend_fetch_function(Z_STR_P(callable));
if (EXPECTED(func != NULL)) {
fcc->function_handler = func;
return true;
}
/* Might be a static method */
} else {
fcc->object = object;
fcc->calling_scope = object->ce;
}

if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) {
fcc->called_scope = fcc->calling_scope;
return 1;
return true;
}

check_func:
ret = zend_is_callable_check_func(callable, frame, fcc, strict_class, error, check_flags & IS_CALLABLE_SUPPRESS_DEPRECATIONS);
if (fcc == &fcc_local) {
zend_release_fcall_info_cache(fcc);
}
return ret;
ret = zend_is_method_callable(Z_STR_P(callable), frame, fcc, strict_class, error, check_flags & IS_CALLABLE_SUPPRESS_DEPRECATIONS);
break;

case IS_ARRAY:
{
Expand Down Expand Up @@ -4260,28 +4238,31 @@ ZEND_API bool zend_is_callable_at_frame(
}
}

callable = method;
goto check_func;
ret = zend_is_method_callable(Z_STR_P(method), frame, fcc, strict_class, error, check_flags & IS_CALLABLE_SUPPRESS_DEPRECATIONS);
break;
}
return 0;

case IS_OBJECT:
if (Z_OBJ_HANDLER_P(callable, get_closure) && Z_OBJ_HANDLER_P(callable, get_closure)(Z_OBJ_P(callable), &fcc->calling_scope, &fcc->function_handler, &fcc->object, 1) == SUCCESS) {
fcc->called_scope = fcc->calling_scope;
fcc->closure = Z_OBJ_P(callable);
if (fcc == &fcc_local) {
zend_release_fcall_info_cache(fcc);
}
return 1;
if (Z_OBJ_HANDLER_P(callable, get_closure) && Z_OBJ_HANDLER_P(callable, get_closure)(Z_OBJ_P(callable), &fcc->calling_scope, &fcc->function_handler, &fcc->object, 1) == FAILURE) {
if (error) *error = estrdup("no array or string given");
return 0;
}
if (error) *error = estrdup("no array or string given");
return 0;
fcc->called_scope = fcc->calling_scope;
fcc->closure = Z_OBJ_P(callable);
ret = true;
break;
case IS_REFERENCE:
callable = Z_REFVAL_P(callable);
goto again;
default:
if (error) *error = estrdup("no array or string given");
return 0;
}

if (fcc == &fcc_local) {
zend_release_fcall_info_cache(fcc);
}
return ret;
}
/* }}} */

Expand Down
11 changes: 6 additions & 5 deletions Zend/zend_ast.c
Original file line number Diff line number Diff line change
Expand Up @@ -1241,15 +1241,16 @@ static zend_result ZEND_FASTCALL zend_ast_evaluate_inner(

if (!fptr) {
zend_string *function_name = zend_ast_get_str(ast->child[0]);
zend_string *function_name_lc = zend_string_tolower(function_name);
fptr = zend_fetch_function(function_name_lc);
fptr = zend_fetch_function(function_name);

/* Search for global function of the same name */
if (!fptr && ast->child[0]->attr != ZEND_NAME_FQ) {
const char *backslash = zend_memrchr(ZSTR_VAL(function_name_lc), '\\', ZSTR_LEN(function_name_lc));
const char *backslash = zend_memrchr(ZSTR_VAL(function_name), '\\', ZSTR_LEN(function_name));
if (backslash) {
fptr = zend_fetch_function_str(backslash + 1, ZSTR_LEN(function_name_lc) - (backslash - ZSTR_VAL(function_name_lc) + 1));
fptr = zend_fetch_function_str(backslash + 1, ZSTR_LEN(function_name) - (backslash - ZSTR_VAL(function_name) + 1));
}
}
zend_string_release(function_name_lc);

if (!fptr) {
zend_throw_error(NULL, "Call to undefined function %s()", ZSTR_VAL(function_name));
return FAILURE;
Expand Down
38 changes: 20 additions & 18 deletions Zend/zend_execute.c
Original file line number Diff line number Diff line change
Expand Up @@ -4498,32 +4498,34 @@ static zend_never_inline void ZEND_FASTCALL init_func_run_time_cache(zend_op_arr

ZEND_API zend_function * ZEND_FASTCALL zend_fetch_function(zend_string *name) /* {{{ */
{
zval *zv = zend_hash_find(EG(function_table), name);

if (EXPECTED(zv != NULL)) {
zend_function *fbc = Z_FUNC_P(zv);
zend_function *fbc;
if (UNEXPECTED(ZSTR_VAL(name)[0] == '\\')) {
/* Ignore leading "\" */
fbc = zend_hash_str_find_ptr_lc(EG(function_table), ZSTR_VAL(name) + 1, ZSTR_LEN(name) - 1);
} else {
fbc = zend_hash_find_ptr_lc(EG(function_table), name);
}

if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache_i(&fbc->op_array);
}
return fbc;
if (EXPECTED(fbc && fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache_i(&fbc->op_array);
}
return NULL;
return fbc;
} /* }}} */

ZEND_API zend_function * ZEND_FASTCALL zend_fetch_function_str(const char *name, size_t len) /* {{{ */
{
const zval *zv = zend_hash_str_find(EG(function_table), name, len);

if (EXPECTED(zv != NULL)) {
zend_function *fbc = Z_FUNC_P(zv);
zend_function *fbc;
if (UNEXPECTED(name[0] == '\\')) {
/* Ignore leading "\" */
fbc = zend_hash_str_find_ptr_lc(EG(function_table), name + 1, len - 1);
} else {
fbc = zend_hash_str_find_ptr_lc(EG(function_table), name, len);
}

if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache_i(&fbc->op_array);
}
return fbc;
if (EXPECTED(fbc && fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache_i(&fbc->op_array);
}
return NULL;
return fbc;
} /* }}} */

ZEND_API void ZEND_FASTCALL zend_init_func_run_time_cache(zend_op_array *op_array) /* {{{ */
Expand Down
40 changes: 27 additions & 13 deletions docs/release-process.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ releases.
* php-8.4.0 (initial GA)
* php-8.4.9 (periodic bugfix or security release)

12. Ensure you are familiar with our procedure for [merging upwards][].

## Packaging a non-stable release (alpha/beta/RC)

Expand Down Expand Up @@ -321,7 +322,7 @@ slightly different steps. We'll call attention where the steps differ.
git add main/php_version.h Zend/zend.h configure.ac
git merge --continue
```

Be sure to set up a merge driver for the `NEWS` file as described in
the [Git FAQ page on the PHP wiki][gitfaq-mandatory].

Expand Down Expand Up @@ -543,25 +544,38 @@ slightly different steps. We'll call attention where the steps differ.

## Packaging a stable release

1. Check out the *patch-level version branch* for the release
(e.g., `PHP-8.1.7`).
1. Check out the *patch-level version branch* for the release.

```
git switch PHP-X.Y.Z
```

> 💬 **Hint** \
> You should have created this branch when packaging the non-stable release
> candidate for this version. If it is for a PHP-X.Y.0 version, then the branch
> was created as part of the final planned release candidate, PHP-X.Y.0RC4.

2. If a CVE commit needs to be merged to the release, have it committed to
the base branches and [merged upwards as usual][] (e.g. commit the CVE fix
to 7.2, merge to 7.3, 7.4, etc.). Then, you can cherry-pick it into the
patch-level version branch for this release.
2. If the upcoming release is a security release, you will have been informed
about it by the security release manager (SRM) by Tuesday noon (UTC).

Commit these changes and push the patch-level version branch. Ensure
that CI is still passing (see above).
> 💬 **Hint** \
> If you haven't set up a git remote for the security repo yet, do so:
> ```bash
> git remote add security git@github.com:php/php-src-security.git
> ```

> 💡 **Tip** \
> Don't forget to update `NEWS` manually in an extra commit to the
> patch-level version branch.
The SRM will provide you with a branch to merge in your
*patch-level version branch*.

```bash
git fetch security
git merge security/PHP-X.Y.Z-security
git push upstream PHP-X.Y.Z
```

> 💬 **Hint** \
> You do not need to merge this back into PHP-X.Y; the SRM will take care
> of it.

3. Run the `./scripts/dev/credits` script in the patch-level version branch,
and commit the changes in the credits files in `ext/standard`.
Expand Down Expand Up @@ -1182,7 +1196,7 @@ volunteers to begin the selection process for the next release managers.
[Update NEWS for PHP 8.2.0RC6]: https://github.com/php/php-src/commit/4ccc414961a70200d638ca281a35f893226d74e2
[PHP 8.3 is now for PHP 8.3.21-dev]: https://github.com/php/php-src/commit/b57f425cfe20a11003253427424cc0517483550b
[GitHub command line tool]: https://cli.github.com
[merged upwards as usual]: https://wiki.php.net/vcs/gitworkflow
[merging upwards]: https://wiki.php.net/vcs/gitworkflow
[Update versions for PHP 8.1.7]: https://github.com/php/php-src/commit/d35e577a1bd0b35b9386cea97cddc73fd98eed6d
[Update NEWS for PHP 8.1.7]: https://github.com/php/php-src/commit/b241f07f52ca9f87bf52be81817f475e6e727439
[Announce PHP 8.1.6]: https://github.com/php/web-php/commit/9f796a96c65f07e45845ec248933bfb0010b94a9
Expand Down
Loading