Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
02c67b4
Fix accessing of overridden private property in get_object_vars()
iluuu1994 Oct 15, 2025
f5fc755
Merge branch 'PHP-8.3' into PHP-8.4
iluuu1994 Oct 20, 2025
fbf11f9
Merge branch 'PHP-8.4' into PHP-8.5
iluuu1994 Oct 20, 2025
8c239d1
Merge branch 'PHP-8.5'
iluuu1994 Oct 20, 2025
939b972
Improve bug60602.phpt portability
iluuu1994 Oct 17, 2025
e37a207
NEWS
arnaud-lb Oct 20, 2025
92f3d90
Merge branch 'PHP-8.4' into PHP-8.5
arnaud-lb Oct 20, 2025
43549ea
NEWS
arnaud-lb Oct 20, 2025
5f062de
Merge branch 'PHP-8.5'
arnaud-lb Oct 20, 2025
4289bda
Merge branch 'PHP-8.3' into PHP-8.4
iluuu1994 Oct 20, 2025
9e96637
Merge branch 'PHP-8.4' into PHP-8.5
iluuu1994 Oct 20, 2025
5ce8a86
Merge branch 'PHP-8.5'
iluuu1994 Oct 20, 2025
45a50d0
phar: Remove pointless efree() (#20232)
ndossche Oct 20, 2025
40b3f88
phar: Avoid string duplication just for error message, use truncation…
ndossche Oct 20, 2025
0805953
phar: Restructure code to get rid of a goto
ndossche Oct 19, 2025
0098f3e
phar: De-indent code
ndossche Oct 19, 2025
6291f97
phar: Move code to avoid goto
ndossche Oct 19, 2025
a69b353
phar: Re-indent code
ndossche Oct 19, 2025
9c90e16
phar: Avoid an error goto in phar_zip_flush() (#20233)
ndossche Oct 20, 2025
df8ce6d
Zend: remove zval_dtor() compatibility macro
ndossche Oct 19, 2025
8e84e9a
pgsql: Use cheaper string conversion functions
ndossche Oct 18, 2025
e2396a6
pgsql: Simplify pgsql_copy_from_query() by using character buffers
ndossche Oct 18, 2025
da96382
pgsql: Avoid unnecessary work in pgsql_copy_from_query() if the input…
ndossche Oct 18, 2025
5eec4d8
pgsql: Avoid duplicating strings and factor out parameter building code
ndossche Oct 18, 2025
020bbea
phar: Fix memory leak when openssl polyfill returns garbage
ndossche Oct 17, 2025
4c043d8
Merge branch 'PHP-8.3' into PHP-8.4
ndossche Oct 20, 2025
90eabf5
Merge branch 'PHP-8.4' into PHP-8.5
ndossche Oct 20, 2025
41d6d36
Merge branch 'PHP-8.5'
ndossche Oct 20, 2025
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
2 changes: 2 additions & 0 deletions UPGRADING.INTERNALS
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ PHP 8.6 INTERNALS UPGRADE NOTES
. ZEND_LTOA() (and ZEND_LTOA_BUF_LEN) has been removed, as it was
unsafe. Directly use ZEND_LONG_FMT with a function from the
printf family.
. The zval_dtor() alias of zval_ptr_dtor_nogc() has been removed.
Call zval_ptr_dtor_nogc() directly instead.

========================
2. Build system changes
Expand Down
25 changes: 25 additions & 0 deletions Zend/tests/gh20177.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
--TEST--
GH-20177: Access overridden private property in get_object_vars()
--FILE--
<?php

class A {
private $prop = 'A::$prop';

public function __construct() {
var_dump(get_object_vars($this));
}
}

class B extends A {
protected $prop = 'B::$prop';
}

new B;

?>
--EXPECT--
array(1) {
["prop"]=>
string(8) "A::$prop"
}
5 changes: 5 additions & 0 deletions Zend/zend_object_handlers.c
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,11 @@ ZEND_API zend_result zend_check_property_access(const zend_object *zobj, zend_st
return FAILURE;
}
} else {
/* We were looking for a protected property but found a private one
* belonging to the parent class. */
if (property_info->flags & ZEND_ACC_PRIVATE) {
return FAILURE;
}
ZEND_ASSERT(property_info->flags & ZEND_ACC_PROTECTED);
}
return SUCCESS;
Expand Down
3 changes: 0 additions & 3 deletions Zend/zend_variables.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,6 @@ ZEND_API void zval_ptr_dtor(zval *zval_ptr);
ZEND_API void zval_ptr_safe_dtor(zval *zval_ptr);
ZEND_API void zval_internal_ptr_dtor(zval *zvalue);

/* Kept for compatibility */
#define zval_dtor(zvalue) zval_ptr_dtor_nogc(zvalue)

ZEND_API void zval_add_ref(zval *p);

END_EXTERN_C()
Expand Down
2 changes: 1 addition & 1 deletion ext/pdo/pdo_stmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -1052,7 +1052,7 @@ PHP_METHOD(PDOStatement, fetch)
array_init_size(return_value, 1);
bool success = pdo_do_key_pair_fetch(stmt, ori, off, Z_ARRVAL_P(return_value));
if (!success) {
zval_dtor(return_value);
zval_ptr_dtor_nogc(return_value);
PDO_HANDLE_STMT_ERR();
RETURN_FALSE;
}
Expand Down
177 changes: 70 additions & 107 deletions ext/pgsql/pgsql.c
Original file line number Diff line number Diff line change
Expand Up @@ -1223,26 +1223,55 @@ PHP_FUNCTION(pg_query)
}
}

static void _php_pgsql_free_params(char **params, int num_params)
/* The char pointer MUST refer to the char* of a zend_string struct */
static void php_pgsql_zend_string_release_from_char_pointer(char *ptr) {
zend_string_release((zend_string*) (ptr - XtOffsetOf(zend_string, val)));
}

static void _php_pgsql_free_params(char **params, uint32_t num_params)
{
int i;
for (i = 0; i < num_params; i++) {
for (uint32_t i = 0; i < num_params; i++) {
if (params[i]) {
efree(params[i]);
php_pgsql_zend_string_release_from_char_pointer(params[i]);
}
}
efree(params);
}

static char **php_pgsql_make_arguments(const HashTable *param_arr, int *num_params)
{
/* This conversion is safe because of the limit of number of elements in a table. */
*num_params = (int) zend_hash_num_elements(param_arr);
char **params = safe_emalloc(sizeof(char *), *num_params, 0);
uint32_t i = 0;

ZEND_HASH_FOREACH_VAL(param_arr, zval *tmp) {
ZVAL_DEREF(tmp);
if (Z_TYPE_P(tmp) == IS_NULL) {
params[i] = NULL;
} else {
zend_string *param_str = zval_try_get_string(tmp);
if (!param_str) {
_php_pgsql_free_params(params, i);
return NULL;
}
params[i] = ZSTR_VAL(param_str);
}
i++;
} ZEND_HASH_FOREACH_END();

return params;
}

/* Execute a query */
PHP_FUNCTION(pg_query_params)
{
zval *pgsql_link = NULL;
zval *pv_param_arr, *tmp;
zval *pv_param_arr;
char *query;
size_t query_len;
bool leftover = false;
int num_params = 0;
int num_params;
char **params = NULL;
pgsql_link_handle *link;
PGconn *pgsql;
Expand Down Expand Up @@ -1286,26 +1315,9 @@ PHP_FUNCTION(pg_query_params)
php_error_docref(NULL, E_NOTICE, "Found results on this connection. Use pg_get_result() to get these results first");
}

num_params = zend_hash_num_elements(Z_ARRVAL_P(pv_param_arr));
if (num_params > 0) {
int i = 0;
params = (char **)safe_emalloc(sizeof(char *), num_params, 0);

ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(pv_param_arr), tmp) {
ZVAL_DEREF(tmp);
if (Z_TYPE_P(tmp) == IS_NULL) {
params[i] = NULL;
} else {
zend_string *param_str = zval_try_get_string(tmp);
if (!param_str) {
_php_pgsql_free_params(params, i);
RETURN_THROWS();
}
params[i] = estrndup(ZSTR_VAL(param_str), ZSTR_LEN(param_str));
zend_string_release(param_str);
}
i++;
} ZEND_HASH_FOREACH_END();
params = php_pgsql_make_arguments(Z_ARRVAL_P(pv_param_arr), &num_params);
if (UNEXPECTED(!params)) {
RETURN_THROWS();
}

pgsql_result = PQexecParams(pgsql, query, num_params,
Expand Down Expand Up @@ -1440,11 +1452,11 @@ PHP_FUNCTION(pg_prepare)
PHP_FUNCTION(pg_execute)
{
zval *pgsql_link = NULL;
zval *pv_param_arr, *tmp;
zval *pv_param_arr;
char *stmtname;
size_t stmtname_len;
bool leftover = false;
int num_params = 0;
int num_params;
char **params = NULL;
PGconn *pgsql;
pgsql_link_handle *link;
Expand Down Expand Up @@ -1488,25 +1500,9 @@ PHP_FUNCTION(pg_execute)
php_error_docref(NULL, E_NOTICE, "Found results on this connection. Use pg_get_result() to get these results first");
}

num_params = zend_hash_num_elements(Z_ARRVAL_P(pv_param_arr));
if (num_params > 0) {
int i = 0;
params = (char **)safe_emalloc(sizeof(char *), num_params, 0);

ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(pv_param_arr), tmp) {
ZVAL_DEREF(tmp);
if (Z_TYPE_P(tmp) == IS_NULL) {
params[i] = NULL;
} else {
zend_string *tmp_str;
zend_string *str = zval_get_tmp_string(tmp, &tmp_str);

params[i] = estrndup(ZSTR_VAL(str), ZSTR_LEN(str));
zend_tmp_string_release(tmp_str);
}

i++;
} ZEND_HASH_FOREACH_END();
params = php_pgsql_make_arguments(Z_ARRVAL_P(pv_param_arr), &num_params);
if (UNEXPECTED(!params)) {
RETURN_THROWS();
}

pgsql_result = PQexecPrepared(pgsql, stmtname, num_params,
Expand Down Expand Up @@ -3409,26 +3405,27 @@ PHP_FUNCTION(pg_copy_to)

static zend_result pgsql_copy_from_query(PGconn *pgsql, PGresult *pgsql_result, zval *value)
{
zend_string *tmp = zval_try_get_string(value);
zend_string *tmp_tmp;
zend_string *tmp = zval_try_get_tmp_string(value, &tmp_tmp);
if (UNEXPECTED(!tmp)) {
return FAILURE;
}
zend_string *zquery = zend_string_alloc(ZSTR_LEN(tmp) + 2, false);
memcpy(ZSTR_VAL(zquery), ZSTR_VAL(tmp), ZSTR_LEN(tmp) + 1);
ZSTR_LEN(zquery) = ZSTR_LEN(tmp);
if (ZSTR_LEN(tmp) > 0 && ZSTR_VAL(zquery)[ZSTR_LEN(tmp) - 1] != '\n') {
ZSTR_VAL(zquery)[ZSTR_LEN(tmp)] = '\n';
ZSTR_VAL(zquery)[ZSTR_LEN(tmp) + 1] = '\0';
ZSTR_LEN(zquery) ++;
}
if (PQputCopyData(pgsql, ZSTR_VAL(zquery), ZSTR_LEN(zquery)) != 1) {
zend_string_release_ex(zquery, false);
zend_string_release(tmp);
return FAILURE;

int result;
if (ZSTR_LEN(tmp) > 0 && ZSTR_VAL(tmp)[ZSTR_LEN(tmp) - 1] != '\n') {
char *zquery = emalloc(ZSTR_LEN(tmp) + 2);
memcpy(zquery, ZSTR_VAL(tmp), ZSTR_LEN(tmp) + 1);
zquery[ZSTR_LEN(tmp)] = '\n';
zquery[ZSTR_LEN(tmp) + 1] = '\0';
result = PQputCopyData(pgsql, zquery, ZSTR_LEN(tmp) + 1);
efree(zquery);
} else {
result = PQputCopyData(pgsql, ZSTR_VAL(tmp), ZSTR_LEN(tmp));
}
zend_string_release_ex(zquery, false);
zend_string_release(tmp);
return SUCCESS;

zend_tmp_string_release(tmp_tmp);

return result != 1 ? FAILURE : SUCCESS;
}

/* {{{ Copy table from array */
Expand Down Expand Up @@ -4033,9 +4030,9 @@ PHP_FUNCTION(pg_send_query)
/* {{{ Send asynchronous parameterized query */
PHP_FUNCTION(pg_send_query_params)
{
zval *pgsql_link, *pv_param_arr, *tmp;
zval *pgsql_link, *pv_param_arr;
pgsql_link_handle *link;
int num_params = 0;
int num_params;
char **params = NULL;
char *query;
size_t query_len;
Expand Down Expand Up @@ -4065,25 +4062,9 @@ PHP_FUNCTION(pg_send_query_params)
"There are results on this connection. Call pg_get_result() until it returns FALSE");
}

num_params = zend_hash_num_elements(Z_ARRVAL_P(pv_param_arr));
if (num_params > 0) {
int i = 0;
params = (char **)safe_emalloc(sizeof(char *), num_params, 0);

ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(pv_param_arr), tmp) {
ZVAL_DEREF(tmp);
if (Z_TYPE_P(tmp) == IS_NULL) {
params[i] = NULL;
} else {
zend_string *tmp_str;
zend_string *str = zval_get_tmp_string(tmp, &tmp_str);

params[i] = estrndup(ZSTR_VAL(str), ZSTR_LEN(str));
zend_tmp_string_release(tmp_str);
}

i++;
} ZEND_HASH_FOREACH_END();
params = php_pgsql_make_arguments(Z_ARRVAL_P(pv_param_arr), &num_params);
if (UNEXPECTED(!params)) {
RETURN_THROWS();
}

if (PQsendQueryParams(pgsql, query, num_params, NULL, (const char * const *)params, NULL, NULL, 0)) {
Expand Down Expand Up @@ -4205,8 +4186,8 @@ PHP_FUNCTION(pg_send_execute)
{
zval *pgsql_link;
pgsql_link_handle *link;
zval *pv_param_arr, *tmp;
int num_params = 0;
zval *pv_param_arr;
int num_params;
char **params = NULL;
char *stmtname;
size_t stmtname_len;
Expand Down Expand Up @@ -4236,27 +4217,9 @@ PHP_FUNCTION(pg_send_execute)
"There are results on this connection. Call pg_get_result() until it returns FALSE");
}

num_params = zend_hash_num_elements(Z_ARRVAL_P(pv_param_arr));
if (num_params > 0) {
int i = 0;
params = (char **)safe_emalloc(sizeof(char *), num_params, 0);

ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(pv_param_arr), tmp) {
ZVAL_DEREF(tmp);
if (Z_TYPE_P(tmp) == IS_NULL) {
params[i] = NULL;
} else {
zend_string *tmp_str = zval_try_get_string(tmp);
if (UNEXPECTED(!tmp_str)) {
_php_pgsql_free_params(params, i);
return;
}
params[i] = estrndup(ZSTR_VAL(tmp_str), ZSTR_LEN(tmp_str));
zend_string_release(tmp_str);
}

i++;
} ZEND_HASH_FOREACH_END();
params = php_pgsql_make_arguments(Z_ARRVAL_P(pv_param_arr), &num_params);
if (UNEXPECTED(!params)) {
RETURN_THROWS();
}

if (PQsendQueryPrepared(pgsql, stmtname, num_params, (const char * const *)params, NULL, NULL, 0)) {
Expand Down
41 changes: 19 additions & 22 deletions ext/phar/dirstream.c
Original file line number Diff line number Diff line change
Expand Up @@ -188,8 +188,6 @@ static php_stream *phar_make_dirstream(const char *dir, size_t dirlen, const Has
entry = safe_emalloc(keylen, 1, 1);
memcpy(entry, ZSTR_VAL(str_key), keylen);
entry[keylen] = '\0';

goto PHAR_ADD_ENTRY;
} else {
if (0 != memcmp(ZSTR_VAL(str_key), dir, dirlen)) {
/* entry in directory not found */
Expand All @@ -199,28 +197,28 @@ static php_stream *phar_make_dirstream(const char *dir, size_t dirlen, const Has
continue;
}
}
}

const char *save = ZSTR_VAL(str_key);
save += dirlen + 1; /* seek to just past the path separator */
const char *save = ZSTR_VAL(str_key);
save += dirlen + 1; /* seek to just past the path separator */

const char *has_slash = memchr(save, '/', keylen - dirlen - 1);
if (has_slash) {
/* is subdirectory */
save -= dirlen + 1;
entry = safe_emalloc(has_slash - save + dirlen, 1, 1);
memcpy(entry, save + dirlen + 1, has_slash - save - dirlen - 1);
keylen = has_slash - save - dirlen - 1;
entry[keylen] = '\0';
} else {
/* is file */
save -= dirlen + 1;
entry = safe_emalloc(keylen - dirlen, 1, 1);
memcpy(entry, save + dirlen + 1, keylen - dirlen - 1);
entry[keylen - dirlen - 1] = '\0';
keylen = keylen - dirlen - 1;
const char *has_slash = memchr(save, '/', keylen - dirlen - 1);
if (has_slash) {
/* is subdirectory */
save -= dirlen + 1;
entry = safe_emalloc(has_slash - save + dirlen, 1, 1);
memcpy(entry, save + dirlen + 1, has_slash - save - dirlen - 1);
keylen = has_slash - save - dirlen - 1;
entry[keylen] = '\0';
} else {
/* is file */
save -= dirlen + 1;
entry = safe_emalloc(keylen - dirlen, 1, 1);
memcpy(entry, save + dirlen + 1, keylen - dirlen - 1);
entry[keylen - dirlen - 1] = '\0';
keylen = keylen - dirlen - 1;
}
}
PHAR_ADD_ENTRY:

if (keylen) {
/**
* Add an empty element to avoid duplicates
Expand Down Expand Up @@ -450,7 +448,6 @@ int phar_wrapper_mkdir(php_stream_wrapper *wrapper, const char *url_from, int mo

if (NULL == zend_hash_add_mem(&phar->manifest, entry.filename, &entry, sizeof(phar_entry_info))) {
php_stream_wrapper_log_error(wrapper, options, "phar error: cannot create directory \"%s\" in phar \"%s\", adding to manifest failed", ZSTR_VAL(entry.filename), phar->fname);
efree(error);
zend_string_efree(entry.filename);
return 0;
}
Expand Down
Loading