[php-src] PR #25000: ext/curl: Fix curl_reset() and CURLOPT_POSTFIELDS keeping old request data
| From: | binaryfire | 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.