[php-src] PHP-8.5: Fix leak when cURL PREREQFUNCTION returns a type other than int (#22726)

Sjoerd Langkemper via Weilin Du <[email protected]> Mon, 27 Jul 2026 09:50:03 +0000
Newsgroups gmane.comp.php.cvs.general
Message-ID <[email protected]>
Author: Sjoerd Langkemper (Sjord)
Committer: Weilin Du (LamentXU123)
Date: 2026-07-27T17:42:01+08:00

Commit: https://github.com/php/php-src/commit/ad70bbdc4fd21e93a766ac82b46194a1293a1bb1
Raw diff: https://github.com/php/php-src/commit/ad70bbdc4fd21e93a766ac82b46194a1293a1bb1.diff

Fix leak when cURL PREREQFUNCTION returns a type other than int (#22726)

The return value of the function registered with CURLOPT_PREREQFUNCTION was
not cleaned up when it returned an invalid non-int type. Destroy the callback
return value before throwing a TypeError.

The test now returns a dynamically allocated array containing random_bytes(),
so leak detection exercises the zval cleanup path reliably.

Closes #22726

Changed paths:
  M  ext/curl/interface.c
  M  ext/curl/tests/curl_setopt_CURLOPT_PREREQFUNCTION.phpt


Diff:

diff --git a/ext/curl/interface.c b/ext/curl/interface.c
index 7fc1c77e9a9a..4e4da5503bbb 100644
--- a/ext/curl/interface.c
+++ b/ext/curl/interface.c
@@ -770,6 +770,7 @@ static int curl_prereqfunction(void *clientp, char *conn_primary_ip, char *conn_
 				zend_value_error("The CURLOPT_PREREQFUNCTION callback must return either CURL_PREREQFUNC_OK or CURL_PREREQFUNC_ABORT");
 			}
 		} else {
+			zval_ptr_dtor(&retval);
 			zend_type_error("The CURLOPT_PREREQFUNCTION callback must return either CURL_PREREQFUNC_OK or CURL_PREREQFUNC_ABORT");
 		}
 	}
diff --git a/ext/curl/tests/curl_setopt_CURLOPT_PREREQFUNCTION.phpt b/ext/curl/tests/curl_setopt_CURLOPT_PREREQFUNCTION.phpt
index d11e29f078c0..75d9324f15db 100644
--- a/ext/curl/tests/curl_setopt_CURLOPT_PREREQFUNCTION.phpt
+++ b/ext/curl/tests/curl_setopt_CURLOPT_PREREQFUNCTION.phpt
@@ -77,7 +77,7 @@ try {
 
 echo "\nTesting with invalid type\n";
 curl_setopt($ch, CURLOPT_PREREQFUNCTION, function() use ($port) {
-	return 'this should be an integer';
+	return ['this should be an integer' => random_bytes(64)];
 });
 try {
     curl_exec($ch);