When curl opaque objects are cloned, the curl handle was only updated if
the callback function wasn't null. However, the C handler in PHP remains
attached even if the callback was set to NULL (*). So we must
unconditionally update the callback data pointer to the new curl handle.
(*) We can't set the C handler to NULL unconditionally on stable branches
because that invokes a behaviour change (e.g. built in progress bar).
Closes GH-24760.
_php_setup_easy_copy_handlers() copies the write, read and write_header
streams but not std_err. The clone never checks that stream is still
open, so libcurl keeps writing to a FILE* freed when the stream is
closed.
Copy std_err like the other handlers.
Closes GH-24427.
* Fix GH-24533: Accept z.lib from zlib 1.3.2 CMake builds on Windows
* Prefer static zs.lib and add NEWS entry
* Accept zlib 1.3.2 lib names in the other zlib lookups
- Replace bailout on OOM with UnwindExit
- Properly reset various globals that may be accessed during startup
Fix GHSA-w8hw-w9fx-j79w (CVE-2026-109618)
Fix GHSA-6wmf-4rv5-p3rp (CVE-2026-109619)
Co-authored-by: Ilija Tovilo <ilija.tovilo@me.com>
Co-authored-by: Jakub Zelenka <bukka@php.net>
Co-authored-by: Nora Dossche <7771979+ndossche@users.noreply.github.com>
Co-authored-by: Nicolas Grekas <nicolas.grekas@gmail.com>
* Zend: always populate error pointer on failure
Most of the code base expects an error to be set if a char* is provided, as this used to be always the case. It no longer was the case since the partially supported callables were deprecates as the deprecation could be promoted to an exception in which case we skipped allocating a char*.
The simple fix, allocate a char* even in case of an exception so callers don't need to check if it still NULL. This fixes some error messages at the same time.
* tree: simplify error handling for failed zend_is_callable() calls
* docs: clarify docs for zend_is_callable()
---------
Co-authored-by: Arnaud Le Blanc <365207+arnaud-lb@users.noreply.github.com>
By waiting shorter for the server to be ready.
The first check for output on stderr takes approximately 10ms, so we
wait 20ms to make sure its ready. The second check for the open port
typically succeeds immediately, so move the sleep to after we have
tried.
Change the numbers in curl_setopt_ssl.phpt for consistency.
Make it possible to post multiple files with the same name using cURL.
It was already possible to post files, and it was possible to post
multiple strings with the same name. This moves things around to combine
these two features.
Closes GH-15859
* PHP-8.6:
ext/curl/config.m4: include string.h for test using strncmp()
ext/soap/tests/bugs/bug62900.phpt: make use of TEST_PHP_ vars
sapi/cli/tests/php_cli_server_ipv6_error_message.phpt: use TEST_PHP_ vars
* PHP-8.5:
ext/curl/config.m4: include string.h for test using strncmp()
ext/soap/tests/bugs/bug62900.phpt: make use of TEST_PHP_ vars
sapi/cli/tests/php_cli_server_ipv6_error_message.phpt: use TEST_PHP_ vars
Commit 2ecafd41ba updates one of the curl ./configure tests to use
strncmp(), but that function may not be defined unless string.h is
included. We add it here.
Closes GH-23208
* PHP-8.5:
sapi/cli: Fix crash in the CLI server when a client is reset before being accepted
ext/curl: Preserve callback lifetime without rejecting callback changes (#23863)
# Conflicts:
# ext/curl/interface.c
* PHP-8.4:
sapi/cli: Fix crash in the CLI server when a client is reset before being accepted
ext/curl: Preserve callback lifetime without rejecting callback changes (#23863)
Keep callback receivers and closures alive until their calls return, allowing
callbacks to replace or clear themselves without freeing an active receiver.
This preserves existing usage such as Symfony HttpClient's write callback.
Use the helper for all callback entry points and retain the in_callback guard
while releasing the temporary references, as destructors may re-enter curl.
Add regression tests for replacement, clearing, trampolines, exceptions and
destructor re-entry.
Co-authored-by: Nicolas Grekas <nicolas.grekas@gmail.com>
Backport PR #23814 from master to PHP-8.4.
Original commit: 840625f266
php_curl_set_callable_handler() frees the previously registered callback with
zend_fcc_dtor() before installing the new one. The write/read/header/progress/
etc. callbacks run with ch->in_callback set, so calling curl_setopt() with one
of the callable options (CURLOPT_WRITEFUNCTION, CURLOPT_READFUNCTION, ...) from
inside such a callback destroys the fcc that is still executing. For a
non-closure callback such as [$obj, 'method'] whose object is only referenced
by the fcc, this releases $this while its method is still on the stack,
resulting in a use-after-free (closures are kept alive by the call frame,
method receivers are not).
Reject setting a callable option while inside a callback, matching the existing
in_callback guards on curl_close() and curl_reset().
Closes#23814
php_curl_set_callable_handler() frees the previously registered callback with
zend_fcc_dtor() before installing the new one. The write/read/header/progress/
etc. callbacks run with ch->in_callback set, so calling curl_setopt() with one
of the callable options (CURLOPT_WRITEFUNCTION, CURLOPT_READFUNCTION, ...) from
inside such a callback destroys the fcc that is still executing. For a
non-closure callback such as [$obj, 'method'] whose object is only referenced
by the fcc, this releases $this while its method is still on the stack,
resulting in a use-after-free (closures are kept alive by the call frame,
method receivers are not).
Reject setting a callable option while inside a callback, matching the existing
in_callback guards on curl_close() and curl_reset().
The server previously responded with a copy of the requested "Host" header in
the response, without any validation. That header, as defined in RFC 9110, is
intended for use in *requests*; remove it from the responses.
Headers required by the generated code (zend_attributes.h, zend_constants.h, zend_enum.h) are collected during generation and emitted as includes at the top of the arginfo file, with the same preprocessor conditions and PHP version guards as the code that needs them.
Removes the manual zend_attributes.h and zend_enum.h includes from sources that only needed them for the arginfo file they include.
Raise a value error when the callback registered with
CURLOPT_READFUNCTION returns an unexpected long.
The function registered with CURLOPT_READFUNCTION should return a
string. PHP then writes that string to a buffer and returns the
length, so that curl can read that many bytes from the buffer.
The function can also return CURL_READFUNC_ABORT and
CURL_READFUNC_PAUSE, so it also supports returning longs. However, when
it returns a long other than these two constants, it is interpreted as a
length. PHP does not update the buffer, but does instruct curl it can
read that many bytes from the buffer. It reads whatever uninitialized
data that is in the buffer and sends it over the line to the server.
This seems bad, so validate the return value of the read function and
raise an error.
Returning 0 is a bit of an edge case. It is not documented but does
results in correct behavior (i.e. end-of-file). So we accept that, but
don't advertise it as valid in the error message.
Related to https://github.com/php/php-src/issues/10270
Close GH-22757