1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00

Merge branch 'PHP-8.3' into PHP-8.4

* PHP-8.3:
  Fix memory leaks when returning refcounted value from curl callback
This commit is contained in:
Niels Dossche
2025-06-21 00:37:51 +02:00
5 changed files with 52 additions and 6 deletions

4
NEWS
View File

@@ -6,6 +6,10 @@ PHP NEWS
. Fixed bug GH-18833 (Use after free with weakmaps dependent on destruction
order). (Daniil Gentili)
- Curl:
. Fix memory leaks when returning refcounted value from curl callback.
(nielsdos)
03 Jul 2025, PHP 8.4.9
- BcMath:

View File

@@ -139,6 +139,9 @@ void _php_curl_multi_cleanup_list(void *data);
void _php_curl_verify_handlers(php_curl *ch, bool reporterror);
void _php_setup_easy_copy_handlers(php_curl *ch, php_curl *source);
/* Consumes `zv` */
zend_long php_curl_get_long(zval *zv);
static inline php_curl *curl_from_obj(zend_object *obj) {
return (php_curl *)((char *)(obj) - XtOffsetOf(php_curl, std));
}

View File

@@ -600,7 +600,7 @@ static size_t curl_write(char *data, size_t size, size_t nmemb, void *ctx)
if (!Z_ISUNDEF(retval)) {
_php_curl_verify_handlers(ch, /* reporterror */ true);
/* TODO Check callback returns an int or something castable to int */
length = zval_get_long(&retval);
length = php_curl_get_long(&retval);
}
zval_ptr_dtor(&argv[0]);
@@ -633,7 +633,7 @@ static int curl_fnmatch(void *ctx, const char *pattern, const char *string)
if (!Z_ISUNDEF(retval)) {
_php_curl_verify_handlers(ch, /* reporterror */ true);
/* TODO Check callback returns an int or something castable to int */
rval = zval_get_long(&retval);
rval = php_curl_get_long(&retval);
}
zval_ptr_dtor(&argv[0]);
zval_ptr_dtor(&argv[1]);
@@ -670,7 +670,7 @@ static size_t curl_progress(void *clientp, double dltotal, double dlnow, double
if (!Z_ISUNDEF(retval)) {
_php_curl_verify_handlers(ch, /* reporterror */ true);
/* TODO Check callback returns an int or something castable to int */
if (0 != zval_get_long(&retval)) {
if (0 != php_curl_get_long(&retval)) {
rval = 1;
}
}
@@ -708,7 +708,7 @@ static size_t curl_xferinfo(void *clientp, curl_off_t dltotal, curl_off_t dlnow,
if (!Z_ISUNDEF(retval)) {
_php_curl_verify_handlers(ch, /* reporterror */ true);
/* TODO Check callback returns an int or something castable to int */
if (0 != zval_get_long(&retval)) {
if (0 != php_curl_get_long(&retval)) {
rval = 1;
}
}
@@ -807,6 +807,7 @@ static int curl_ssh_hostkeyfunction(void *clientp, int keytype, const char *key,
}
} else {
zend_throw_error(NULL, "The CURLOPT_SSH_HOSTKEYFUNCTION callback must return either CURLKHMATCH_OK or CURLKHMATCH_MISMATCH");
zval_ptr_dtor(&retval);
}
}
@@ -901,7 +902,7 @@ static size_t curl_write_header(char *data, size_t size, size_t nmemb, void *ctx
if (!Z_ISUNDEF(retval)) {
// TODO: Check for valid int type for return value
_php_curl_verify_handlers(ch, /* reporterror */ true);
length = zval_get_long(&retval);
length = php_curl_get_long(&retval);
}
zval_ptr_dtor(&argv[0]);
zval_ptr_dtor(&argv[1]);
@@ -1322,6 +1323,17 @@ void _php_setup_easy_copy_handlers(php_curl *ch, php_curl *source)
(*source->clone)++;
}
zend_long php_curl_get_long(zval *zv)
{
if (EXPECTED(Z_TYPE_P(zv) == IS_LONG)) {
return Z_LVAL_P(zv);
} else {
zend_long ret = zval_get_long(zv);
zval_ptr_dtor(zv);
return ret;
}
}
static size_t read_cb(char *buffer, size_t size, size_t nitems, void *arg) /* {{{ */
{
struct mime_data_cb_arg *cb_arg = (struct mime_data_cb_arg *) arg;

View File

@@ -410,7 +410,7 @@ static int _php_server_push_callback(CURL *parent_ch, CURL *easy, size_t num_hea
zval_ptr_dtor_nogc(&headers);
if (!Z_ISUNDEF(retval)) {
if (CURL_PUSH_DENY != zval_get_long(&retval)) {
if (CURL_PUSH_DENY != php_curl_get_long(&retval)) {
rval = CURL_PUSH_OK;
zend_llist_add_element(&mh->easyh, &pz_ch);
} else {

View File

@@ -0,0 +1,27 @@
--TEST--
Returning refcounted value from callback must not leak
--EXTENSIONS--
curl
--FILE--
<?php
include 'server.inc';
$host = curl_cli_server_start();
$url = "{$host}/get.inc";
$ch = curl_init($url);
function return_non_interned_string() {
return str_repeat('x', random_int(5, 5));
}
curl_setopt($ch, CURLOPT_NOPROGRESS, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_PROGRESSFUNCTION, 'return_non_interned_string');
curl_setopt($ch, CURLOPT_XFERINFOFUNCTION, 'return_non_interned_string');
curl_setopt($ch, CURLOPT_WRITEFUNCTION, 'return_non_interned_string');
curl_setopt($ch, CURLOPT_HEADERFUNCTION, 'return_non_interned_string');
echo curl_exec($ch), PHP_EOL;
echo "ok";
?>
--EXPECT--
ok