Commit f7b9bcc5b57 for php
commit f7b9bcc5b57278156dfdc29b372859d545b7ad4e
Merge: 43c60146708 9e7117f20f5
Author: Weilin Du <weilindu@php.net>
Date: Thu Sep 24 11:56:31 2026 +0800
Merge branch 'PHP-8.4' into PHP-8.5
* PHP-8.4:
ext/curl: Preserve callback lifetime without rejecting callback changes (#23863)
diff --cc ext/curl/tests/curl_callback_lifetime_destructor.phpt
index 00000000000,6611cb90e00..3b941bf689e
mode 000000,100644..100644
--- a/ext/curl/tests/curl_callback_lifetime_destructor.phpt
+++ b/ext/curl/tests/curl_callback_lifetime_destructor.phpt
@@@ -1,0 -1,52 +1,53 @@@
+ --TEST--
+ GH-23814 (Curl callback receivers are destroyed with the callback guard still set)
+ --EXTENSIONS--
+ curl
+ --SKIPIF--
+ <?php
+ if (!in_array('file', curl_version()['protocols'], true)) {
+ die('skip file protocol not supported');
+ }
+ ?>
+ --FILE--
+ <?php
+ class Callback {
+ public function __construct(private CurlHandle $handle) {}
+
+ public function write(CurlHandle $handle, string $data): int {
+ curl_setopt($handle, CURLOPT_WRITEFUNCTION, null);
+ echo "Callback returning\n";
+ return strlen($data);
+ }
+
+ public function __destruct() {
+ foreach (['curl_reset', 'curl_close'] as $function) {
+ try {
- $function($this->handle);
++ // curl_close() is deprecated in PHP 8.5.
++ @$function($this->handle);
+ } catch (Error $e) {
+ echo $e->getMessage(), "\n";
+ }
+ }
+ curl_setopt($this->handle, CURLOPT_WRITEFUNCTION,
+ static function (CurlHandle $handle, string $data): int {
+ echo "Callback installed by destructor\n";
+ return strlen($data);
+ });
+ }
+ }
+
+ $handle = curl_init('file://' . __FILE__);
+ curl_setopt($handle, CURLOPT_WRITEFUNCTION, [new Callback($handle), 'write']);
+ var_dump(curl_exec($handle));
+ var_dump(curl_exec($handle));
+ curl_reset($handle);
+ echo "Reset outside callback succeeded\n";
+ ?>
+ --EXPECT--
+ Callback returning
+ curl_reset(): Attempt to reset cURL handle from a callback
+ curl_close(): Attempt to close cURL handle from a callback
+ bool(true)
+ Callback installed by destructor
+ bool(true)
+ Reset outside callback succeeded