Viktor Szakats [Wed, 11 Feb 2026 23:33:20 +0000 (00:33 +0100)]
windows: tidy up `wincrypt.h` / BoringSSL/AWS-LC coexist workaround
- openssl: move and expand explanatory comment.
- openssl: drop duplicate workaround.
- schannel: drop workaround. Unnecessary, because OpenSSL headers are
not included in or after schannel code.
- schannel: drop explicit `wincrypt.h` include. It's indirectly
included by system `<schannel.h>`.
- ldap: drop explicit `wincrypt.h` include.
It isn't used there, and also not required for the workaround.
`winldap.h` keeps including it indirectly.
Tested with BoringSSL and AWS-LC (MultiSSL with Schannel), also LDAP
enabled, and H3, unity and non-unity, and all tested cases build fine.
In lib in general, the point is to have the `#undef`s between the first
`wincrypt.h` include [1] and the first OpenSSL include [2], within a
single compilation unit. For non-unity builds the only such source is
`openssl.c`. For unity ones, depending on batch size, in theory we
should `#undef` after each `wincrypt.h` include. In practice this is
overkill and most cases are covered by `#undef`-fing _first_ in
`vtls/openssl.c`, and `#undef` in `ldap.c`. It's not impossible that we
need to add more undefs after further `wincrypt.h` includes to cover so
far undiscovered build cases [3]. Though I could not find more with the
current sources and source order.
It's also an option to include OpenSSL first, then `wincrypt.h`, as
done in libtests, but for lib and `vtls/openssl.c` it's more practical
to do the opposite.
[1] can be indirect, e.g. via `iphlpapi.h`, `schannel.h`, `winldap.h`.
[3] `lib/Makefile.inc` defines the order of unity sources.
For libtests, the case is simpler: There is always one compilation unit,
with a fixed order, and at the moment `cli_hx_download.c` is including
OpenSSL first, then wincrypt, and in this order they don't bother each
other. Also, at the moment `lib758.c` is the only other OpenSSL header
user, but it's compiled after `cli_hx_download.c` so the include is
skipped there. We may need to revisit this if either header gets
included before it.
All this said it'd be nice if BoringSSL/AWS-LC restored the built-in
workaround to behave like LibreSSL and OpenSSL and not require local
workarounds like these.
Viktor Szakats [Wed, 11 Feb 2026 12:54:27 +0000 (13:54 +0100)]
windows: tidy up includes, macros, document dependencies
- define `SECURITY_WIN32` globally in `curl_setup.h`.
To make sure it applies to all includes.
- document which Windows headers require `SECURITY_WIN32`.
- stop suppressing MSVC warning:
`C4201 is: nonstandard extension used : nameless struct/union`
The warning is no longer seen in supported build envs with the current
codebase.
Follow-up to 8beff4355956e3d18ceb3afc21c1f3edec82543c #8419
- document why `SCHANNEL_USE_BLACKLISTS` is needed.
- just define `SCHANNEL_USE_BLACKLISTS`, drop the unnecessary value `1`.
Viktor Szakats [Wed, 11 Feb 2026 03:10:00 +0000 (04:10 +0100)]
build: check `MSG_NOSIGNAL` directly, drop detection and interim macro
Drop detecting it at configure time, along with the interim macro
`HAVE_MSG_NOSIGNAL`. There is no longer a reason for this workaround,
and allows to save the work at configure time and simplify.
Also say in a comment that `sys/socket.h` is defining this macro.
Viktor Szakats [Wed, 11 Feb 2026 00:51:21 +0000 (01:51 +0100)]
curl_setup.h: merge back single-use internal header `curl_setup_once.h`
Originally split in 2006, but the issues cited are no longer present in
current code. As of now both `curl_setup.h` and `curl_setup_once.h` are
included once per compiler invocation, without recursion. The latter is
a sub-header of the former with no clear distinction in their contents.
Merge them to avoid having to decide where to put new global PP logic.
Also to make it easier to overview what gets defined/included globally
and in what order. (Perhaps even allowing some tidying up here.)
Jay Satiro [Thu, 5 Feb 2026 22:43:55 +0000 (17:43 -0500)]
vtls: use ALPN http/1.0 & http/1.1 for HTTP/1.0 requests
- For compatibility reasons send both ALPN ids http/1.0 and http/1.1 for
HTTP/1.0 requests.
Prior to this change for compatibility reasons curl would send ALPN
http/1.1 for HTTP/1.0 requests, since some servers do not recognize
ALPN http/1.0. However some servers may recognize only ALPN http/1.0 for
HTTP/1.0 requests. Therefore curl now sends both.
Viktor Szakats [Sat, 7 Feb 2026 16:57:39 +0000 (17:57 +0100)]
build: tidy up and simplify `setmode()` detection and use
- move macro to `curl_setup.h` (from curlx), and rename.
It's required by src, test servers, libtests. Also used by unit/tunit,
(which is fixable but this patch doesn't touch it.)
- special-case it for Windows/Cygwin/MS-DOS.
- build: drop `setmode()`/`_setmode()` detection.
This also avoids detecting the different `setmode()` on BSDs,
and a lot of complexity and overhead.
- use `CURL_O_BINARY`.
Viktor Szakats [Sun, 8 Feb 2026 02:36:45 +0000 (03:36 +0100)]
curl_setup.h: drop extra header guard for internal include
The included local header starts with this same guard. The original
commit added it for fixing VMS builds along with many other changes, but
without mention of this specific one in the commit message.
`curl_setup.h` is included once, which includes `curl_setup_once.h`
once, even if the latter wouldn't have it's own guard.
Stefan Eissing [Wed, 28 Jan 2026 16:20:57 +0000 (17:20 +0100)]
url.c: code/comment cleanup around conn creation
Several comments were outdated and parameters to create_conn() and
ConnectionExists() were not needed. Give functions better names and
consistently use terms `needle` and `conn`.
Stefan Eissing [Tue, 3 Feb 2026 09:18:13 +0000 (10:18 +0100)]
multi: update timer unconditionally in multi_remove_handle
When removing an easy handle from a multi, there was an optimization
to update the timer only when the removed handle had any timers.
With the introduction of the "dirty" bitset, easy handles can now cause
a timeout of 0 to be set without having anything in their timer list.
Removing such a handle needs to update the timer now always, so that
it may get cleared when there is nothing more to wait for.
The previous "not clearing a 0 timer" should not have any effect on
application's logic. Without clearing, the timer will fire and then
adjust itself to the proper value. But it would cause one more timer
fire than necessary.
Reported-by: Jan Macku
Fixes https://github.com/curl/curl/issues/20498
Closes https://github.com/curl/curl/pull/20502
Viktor Szakats [Mon, 2 Feb 2026 18:02:34 +0000 (19:02 +0100)]
build: require POSIX `strdup()`
Stop detecting this function and drop the local fallback.
Let us know if this update is causing an issue.
Notes:
- on Windows `_strdup()` is required instead.
- `strdup()/_strdup()` were required before this patch to build one of
the examples: `block_ip`.
- `strdup()/_strdup()` were required in 8.18.0 and earlier to build
tests.
Viktor Szakats [Mon, 2 Feb 2026 13:08:14 +0000 (14:08 +0100)]
build: tidy up and dedupe `strdup` functions
- de-dupe lib/src strdup/memdup functions into curlx.
- introduce `CURLX_STRDUP_LOW()` for mapping `strdup()`, and to do it at
one place within the code, in `curl_setup.h`.
- tests/server: use `curlx_strdup()`. (Also to fix building without
a system `strdup()`.)
- curlx/curlx.h: shorten and tidy up.
- adjust Windows build path to not need `HAVE_STRDUP`.
- build: stop detecting `HAVE_STRDUP` on Windows.
Stefan Eissing [Thu, 29 Jan 2026 10:59:05 +0000 (11:59 +0100)]
hostip.c: fix leak of addrinfo
When creating a dns entry, the addrinfo is passed into the entry on
success and needed deallocation by the caller on failure.
Change the signature to have Curl_dnscache_mk_entry() *always* take
ownership of the addrinfo, even on failure. Change parameter to address
of pointer so that call always clears it.
This makes the handling of failures to Curl_dnscache_mk_entry() simpler.
Viktor Szakats [Mon, 2 Feb 2026 12:14:30 +0000 (13:14 +0100)]
build: tidy up curl-specific fstat calls and stat struct type
To avoid redefining the `fstat` system symbol, and to clarify
`struct_stat` is a curl symbol.
- introduce `curlx_fstat()` macro and use it.
- rename `struct_stat` to `curl_struct_stat`.
Also:
- tests: replace direct `curlx_win32_stat()` call with `curlx_stat()`.
- checksrc: disallow direct `_fstati64` and `fstat()` calls, except in
examples.
Viktor Szakats [Sat, 31 Jan 2026 20:15:51 +0000 (21:15 +0100)]
cmake: skip binutils ld hack if zlib/openssl target is not `IMPORTED`
The binutils ld hack requires reading the targets' `LOCATION` property.
This property exists in `IMPORTED` targets. `ZLIB::ZLIB` and
`OpenSSL::Crypto` are normally `IMPORTED` targets defined by CMake's
built-in Find modules. However, in some cases (e.g. in "superbuilds"),
they may be regular targets, defined manually, without a `LOCATION`
property. To avoid a CMake warning in such case, verify if the target is
`IMPORTED` before reading this property.
This also mean that in such case the binutils/ld/gcc hack is not
enabled, and libcurl may fail linking in static mode.
Viktor Szakats [Sun, 1 Feb 2026 00:04:58 +0000 (01:04 +0100)]
build: tidy up local `lseek()` mappings
- stop redefining system symbol `lseek`, by introducing `curl_lseek()`.
- handle AmigaOS quirk within the macro mapping.
- add missing parenthesis to `LSEEK_ERROR` values.
- tool_util: use curl `lseek` macros in `tool_ftruncate64()`.
- move `LSEEK_ERROR` to right-hand side of if expressions.
- checksrc: disallow direct uses of `_lseeki64`, `llseek`, `lseek`.
dependabot[bot] [Sun, 1 Feb 2026 14:55:09 +0000 (14:55 +0000)]
GHA: bump GHA and pip dependencies
- update `actions/checkout` from 6.0.1 to 6.0.2
- update `ruff` from 0.14.11 to 0.14.14
- update `cryptography` from 46.0.3 to 46.0.4
- update `psutil` from 7.2.1 to 7.2.2
- update `websockets` from 15.0.1 to 16.0
Viktor Szakats [Thu, 29 Jan 2026 21:57:19 +0000 (22:57 +0100)]
tests/server/sockfilt: avoid possible endless loop on Windows
Seen to happen when run under WINE v10.0 on macOS.
```
$ CURL_TEST_EXE_EXT_SRV=.exe CURL_TEST_EXE_EXT_TOOL=.exe \
CURL_TEST_EXE_RUNNER=wine TFLAGS='951 -t' ninja tests
[...]
16:02:18.607002 [select_ws_wait_thread] PeekNamedPipe error: (0x00000032) - Request not supported.
[...endless repeat...]
```
Viktor Szakats [Thu, 29 Jan 2026 19:54:17 +0000 (20:54 +0100)]
tests/server: tidy-up error messages (Windows)
- show error description on `PeekNamedPipe()` error.
- show `GetLastError()` instead of socket error on non-socket failures
in the window handler.
- include full hex `GetLastError()` numbers in error messages, syncing
with Schannel code.
- drop internal `win32_perror()` function, in favor of direct
`curlx_*strerror()` calls.
Viktor Szakats [Wed, 28 Jan 2026 14:12:46 +0000 (15:12 +0100)]
GHA/windows: mark test 3001 flaky in native Windows jobs
It has been happening for a long time.
Example:
```
test 3001...[HTTPS localhost, last subject alt name matches, CN does not match]
3001: protocol FAILED!
There was no content at all in the file log/7/server.input.
Server glitch? Total curl failure? Returned: 56
== Contents of files in the log/7/ directory after test 3001
=== Start of file commands.log
../src/curl.exe -q --output log/7/curl3001.out --include --trace-ascii log/7/trace3001 --trace-time -4 --cacert ./certs/test-ca.crt https://localhost:64259/3001 > log/7/stdout3001 2> log/7/stderr3001
=== End of file commands.log
=== Start of file http_server.log
13:57:47.951283 Running HTTP IPv4 version on port 64256
=== End of file http_server.log
=== Start of file https_stunnel.log
2026.01.28 13:57:48 LOG5[ui]: stunnel 5.76 on x64-pc-mingw32-gnu platform
2026.01.28 13:57:48 LOG5[ui]: Compiled/running with OpenSSL 3.5.4 30 Sep 2025
[...]
2026.01.28 13:57:49 LOG5[0]: Service [curltest] accepted connection from 127.0.0.1:64281
2026.01.28 13:57:51 LOG3[0]: s_connect: connect 127.0.0.1:64256: Connection refused (WSAECONNREFUSED) (10061)
2026.01.28 13:57:51 LOG3[0]: No more addresses to connect
2026.01.28 13:57:51 LOG5[0]: Connection reset: 0 byte(s) sent to TLS, 0 byte(s) sent to socket
=== End of file https_stunnel.log
=== Start of file server.cmd
Testnum 3001
=== End of file server.cmd
=== Start of file stderr3001
curl: (56) Recv failure: Connection was reset
=== End of file stderr3001
[...]
RUN: Unknown server on our https port: 64259 (56)
```
Viktor Szakats [Wed, 21 Jan 2026 15:20:51 +0000 (16:20 +0100)]
build: assume `stdint.h`
curl requires `stdint.h` from C99, and no longer builds without it since
v8.18.0 (after dropping VS2008 support). Assume it's available, drop
feature checks.
Also:
- drop duplicate `stdint.h` includes.
- introduce internal `HAVE_UINTPTR_T`, enabled by default.
- OS400: disable `HAVE_UINTPTR_T`.
- build: keep cmake pre-fill and `cmp-config.pl` exception because cmake
and autotools both detect `stdint.h` implicitly.
Stefan Eissing [Wed, 28 Jan 2026 08:46:18 +0000 (09:46 +0100)]
pytest: remove 03_02
The test for restarting the server during ongoing transfers does not
work reliably for HTTP/3. This seems due to the nature of UDP/QUIC where
the client may learn about a closed connection at any time, not only
when starting a new request.
Stefan Eissing [Wed, 7 Jan 2026 14:07:13 +0000 (15:07 +0100)]
h2+h3: align stream close handling
For HTTP/2, add error code description to close failures.
For HTTP/3, add special handling like in HTTP/2 when streams
have been rejected or an error comes during the response body
and we are not interested in the body.
Viktor Szakats [Tue, 27 Jan 2026 22:53:05 +0000 (23:53 +0100)]
windows: `USE_WINSOCK` to guard winsock2 code (where missing)
Replacing `_WIN32`.
Also:
- tool_doswin: guard possibly non-portable socket code with
`USE_WINSOCK`. The socket is cast to `HANDLE` and passed to
win32 API `SetStdHandle(STD_INPUT_HANDLE, ...)`.
- lib/setup-win32.h: move `#undef`s before their `#define` pair.
Viktor Szakats [Tue, 27 Jan 2026 23:46:37 +0000 (00:46 +0100)]
tool_doswin: avoid Windowsisms in socket code (cont.)
For general readability. Also to match the rest of the source code.
- bump `send()` result type from `int` to `ssize_t`.
- fix an `int` to be `curl_socklen_t`.
- `.S_un.S_addr` -> `.s_addr`.
- `SD_RECEIVE` -> `SHUT_RD`.
- `SD_SEND` -> `SHUT_WR`.
Viktor Szakats [Tue, 27 Jan 2026 23:15:45 +0000 (00:15 +0100)]
GHA/windows: fix shell, fix GHA fail to share cache between arm and intel Windows
A cache entry created by windows-2022 is not picked up by
windows-11-arm. Also a cache created by windows-11-arm is not picked up
by windows-2022. Possibly related to this filed in 2025 June:
https://github.com/actions/cache/issues/1622. Also tried
`enableCrossOsArchive` to no avail. Unclear if these two runners count
as distinct operating systems, I'd guess not. Cache entries are
identical on the web UI. Via GH API they show up with the same cache key
bot different "version" (hash) and different sizes, possibly due to the
zstd vs. gzip bug above.
Fixing (identical error text on either runner):
```
Error: Failed to restore cache entry. Exiting as fail-on-cache-miss is set. Input key: Windows-stunnel-5.76-amd64
```
Daniel Stenberg [Tue, 27 Jan 2026 15:59:32 +0000 (16:59 +0100)]
tls: remove checks for DEFAULT
Since 9d8998c99408e1adf, the setopt code changes input DEFAULT to an
actual more specific TLS version (1.2) for the backends to use and check
for.
This means that the default value (0L) cannot and should not actually be
used when the TLS backends run. This change adds asserts to verify that
and removes code that accepts the DEFAULT value as a valid version with
the TLS version functions' logic.
Applications can still set a specific lower version if they want (1, 1.0
or 1.1).