[php-src] PR #25000: ext/curl: Fix curl_reset() and CURLOPT_POSTFIELDS keeping old request data

From: Date: Wed, 28 Oct 2026 13:22:47 +0000
Subject: [php-src] PR #25000: ext/curl: Fix curl_reset() and CURLOPT_POSTFIELDS keeping old request data
Groups: php.git-pulls 
Request: Send a blank email to git-pulls+get-40024@lists.php.net to get a copy of this message
Pull Request: https://github.com/php/php-src/pull/25000 Author: binaryfire I ran into this while working on Swoole's copy of ext/curl, which we keep in line with php-src. The description below was written by Claude at my request, and I've reviewed it. > curl_reset() resets the write, header and read handlers but > doesn't release their callbacks. It also keeps the > CURLOPT_PRIVATE value and the CURLOPT_POSTFIELDS > array, so all of these stay referenced until the handle is freed: > > - Callback objects and closures, and anything they capture, stay alive while a reset handle is > pooled for reuse. > - curl_getinfo($ch, CURLINFO_PRIVATE) still returns the old > value after a reset. > - curl_copy_handle() and clone > of a reset handle rebuild the old file post fields. > > Guzzle's CurlFactory works around the first one by setting > each callback to null before it calls > curl_reset() on a handle it pools. Its code comment says the > callbacks "can hold onto references and are not cleaned up by curl_reset". > > Separately, when a CURLOPT_POSTFIELDS array containing a > CURLFile or CURLStringFile is > replaced with another value, the old array isn't released. The original handle sends the new > body, but curl_copy_handle() and > clone rebuild the old multipart body on the copy. > > This PR releases the three callbacks, the private value and the post fields array in > curl_reset(). It also drops the stored array when > CURLOPT_POSTFIELDS is set again. > > A destructor that calls curl_setopt() for the same option while > curl_reset() is releasing it can still cause a use-after-free. > That's already possible for the progress, xferinfo and other callbacks released there, so > I've left it to the general destructor work in #20001.

« previous php.git-pulls (#40024) next »