Viktor Szakats [Fri, 28 Mar 2025 18:10:28 +0000 (19:10 +0100)]
test313: disable CRL test for Schannel due to lack of support and flakiness
The source code and documentation says that CRL is not supported by
curl's Schannel TLS backend.
It's also frequently flaky in CI with both MinGW and MSVC jobs, e.g.:
https://github.com/curl/curl/actions/runs/14134841988/job/39603994164 (Schannel)
https://github.com/curl/curl/actions/runs/14134841988/job/39606336445 (Schannel)
https://github.com/curl/curl/actions/runs/13981383629/job/39147183706 (LibreSSL)
```
curl returned 35, when expecting 60
```
This test was passing with Schannel because it misses the `--insecure`
option and thus always returns 60, regardless of passing `--crlfile` or
not:
```
curl: (60) schannel: CertGetCertificateChain trust error CERT_TRUST_REVOCATION_STATUS_UNKNOWN
More details here: https://curl.se/docs/sslcerts.html
curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the webpage mentioned above.
```
Viktor Szakats [Fri, 28 Mar 2025 00:41:28 +0000 (01:41 +0100)]
tests/server: make the signal handler signal-safe
Before this patch the signal handler called `logmsg()` which in turn
called `printf()` variants (internal implementations), and `FILE *`
functions, `localtime()`. Some of these called `malloc`/`free`, which
isn't supported in s signal handler. Replace them with `write` calls,
losing some logging functionality.
Also:
- De-dupe and move `STD*_FILENO` macros to `lib/curl_setup.h`. Revert
the `src` definition to point to `stderr`, instead of `tool_stderr`.
Follow-up to e5bb88b8f824ed87620bd923552534c83c2a516e #11958
POSIX specs with list of functions allowed in a signal handler:
2004: https://pubs.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html#tag_02_04_03
2017: https://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_04_03
2024: https://pubs.opengroup.org/onlinepubs/9799919799/functions/V2_chap02.html#tag_16_04_03
Linux CI run with the thread sanitizer going crazy when
hitting the signal handler in test 1238 and 1242 (TFTP):
```
WARNING: ThreadSanitizer: signal-unsafe call inside of a signal (pid=12582)
#0 malloc <null> (servers+0x5ed70)
#1 _IO_file_doallocate <null> (libc.so.6+0x851b4)
#2 formatf /home/runner/work/curl/curl/bld/tests/server/../../lib/../../lib/mprintf.c:886:9 (servers+0xdff77)
[...]
WARNING: ThreadSanitizer: signal-unsafe call inside of a signal (pid=12582)
#0 free <null> (servers+0x5f453)
#1 fclose <null> (libc.so.6+0x8532f)
#2 logmsg /home/runner/work/curl/curl/bld/tests/server/../../../tests/server/util.c:134:5 (servers+0xe684d)
```
Ref: https://github.com/curl/curl/actions/runs/14118903372/job/39555309490?pr=16851
Viktor Szakats [Thu, 27 Mar 2025 22:44:51 +0000 (23:44 +0100)]
GHA/linux: move pytests to non-valgrind job variants, drop 2 redundant runs
- move pytest from the valgrind variant of the mbedTLS and Rustls jobs
to their non-valgrind counterpart (they different in C compiler and
build tool respectively). To parallelize more and finish the workflow
faster.
- drop pytest from the valgrind variant of the two identical (other than
the build tool) 'libressl heimdal' jobs. Saves 1.5 minutes CI time.
- drop pytest from the longest valgrind job to make the workflow finish
almost 2 minutes faster. `sync-resolver` is its unique build propery.
It wasn't pytested on Azure.
- explicitly install `libnghttp2-dev` and `libldap-dev` to keep them in
jobs where pytest deps were installing them implicitly before this
patch.
Viktor Szakats [Mon, 24 Mar 2025 21:13:29 +0000 (22:13 +0100)]
runtests: generate certs dynamically, bump to EC-256, tidy up
Before this patch the curl repository and source tarball distribution
contained test certificates as binary blobs. Used by runtests.
Drop these certificates in favor of generating them dynamically as
part of the build process. Both via autotools and CMake.
As part of this, improve certificates, the generator script and process,
file layout, and fix any issue to make it work fast and smooth both in
CI and local builds.
Note, cert generator scripts require OpenSSL >=1.0.2
(or LibreSSL >=3.1.0). Generation requires POSIX shell, also with CMake.
Without a POSIX shell tests relying on TLS (and stunnel) will fail.
Details:
- build: generate certs as part of the test run process.
- build, tests: generate certs in the build directory.
- binarycheck: drop concept of known binary files with hashes.
- binarycheck: move binary check logic into spacecheck and drop this
separate checker tool.
- build: fix to clean all cert files.
- autotools: fix to not run leaf cert generators in parallel. To avoid
confusion when updating the revocation database and counter.
- scripts: drop `scripts` subdir, merge two scripts into one,
auto-generate root cert, allow generating multiple leafs at once.
- scripts: switch to EC-256 keys (was: RSA-2048). For key size and perf.
- scripts: drop `-x` echo, text dumps, most other output. To avoid log
noise and make it quicker in CI.
- scripts: make it non-RSA-specific.
- scripts: delete unused code.
- scripts: use POSIX shell shebang. Some envs don't have bash (Alpine).
- scripts: pass test pseudo-secrets via the command-line. To avoid:
```
+ openssl genrsa -out test-ca.key -passout fd:0 2048
Invalid password argument, starting with "fd:"
```
- cmake: fix to launch generator scripts via the detected POSIX shell.
- cmake: fix `build-certs` rule to not depend on `SRPFILES`
(`srp-verifier-*`).
- cmake: drop `EXCLUDE_FROM_ALL` for the cert subdir. It makes
the Visual Studio generator miss to create the `clean-certs`,
`build-certs` targets. No target depend on them, so they don't execute
implicitly anyway. Fixes:
```
MSBUILD : error MSB1009: Project file does not exist.
Switch: clean-certs.vcxproj
```
- cmake: add `VERBATIM USES_TERMINAL` to `build-certs` target.
- GHA/linux: install openssl on Alpine, for the cert generator scripts.
Yedaya Katsman [Mon, 21 Oct 2024 20:28:28 +0000 (23:28 +0300)]
rustls: Add support for SSLKEYLOGFILE
With rustls-ffi 0.15+ we can set up a callback for writing TLS secrets
hooked up to call Curl_tls_keylog_write. To make sure the associated
file is cleaned up we update the Curl_ssl struct for the rustls-ffi vtls
backend to have a cleanup callback.
Daniel McCarney [Sun, 16 Mar 2025 16:38:24 +0000 (12:38 -0400)]
docs: rework RUSTLS install instructions
Describes using a package manager or pre-built binaries and adopts the
0.15 installation from source instructions.
Previously the rustls docs described installing rustls-ffi from source
using the GNU Makefile. The upstream project has switched to using
cargo-c as a cross-platform solution that works well with the rust
toolchain, pkg-config, and Windows and so this needs an update.
Similarly, for folks that want to avoid the extra cargo-c tool
requirement, rustls-ffi provides binary releases for common platforms,
and some Linux distributions/package managers offer pre-built packages.
The install instructions are expanded to cover these options since
they're generally better for end users than building the dep. from
source (no `rustc` required).
Daniel Stenberg [Mon, 24 Mar 2025 13:41:41 +0000 (14:41 +0100)]
tests: remove base64 encoded sections
The base64 sections were added in a time when there was no other way to
do these tests. Now we remove them again to make less "hidden" data in
the test suite.
For several test cases we instead then provide a sequence of binary
octets which is not really better, but I have tried to minimize them.
Viktor Szakats [Sun, 23 Mar 2025 23:31:33 +0000 (00:31 +0100)]
test615: fix for Cygwin, unignore in CI
Setting a server-side file read-only by `chmod 0444` has does not
prevent overwriting it via SFTP upload (as tested in CI).
Fix it by setting its MS-DOS read-only attribute in addition. It
requires the Cygwin tool `chattr`.
Also unignore in CI.
Fixes:
```
test 0615...[SFTP put remote failure]
curl returned 0, when expecting 9
615: exit FAILED
=== Start of file stderr615
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
100 30 0 0 100 30 0 93 --:--:-- --:--:-- --:--:-- 95
100 30 0 0 100 30 0 92 --:--:-- --:--:-- --:--:-- 92
=== End of file stderr615
```
Ref: https://github.com/curl/curl/actions/runs/14037991918/job/39300723214#step:12:1269
Viktor Szakats [Sun, 23 Mar 2025 22:43:14 +0000 (23:43 +0100)]
GHA/windows: use a pure Cygwin environment
Use the `PATH` `/usr/bin` to avoid any Windows system or 3rd-party tool
installed on the runner machine that may interfere with or add undesired
dependencies to the builds and tests.
Viktor Szakats [Sun, 23 Mar 2025 15:49:06 +0000 (16:49 +0100)]
GHA/windows: install OpenSSH-Windows manually for transparency
To have the current latest version, and to avoid the stale, misleading
versions installed by Chocolatey. It also installs transparently, faster,
and making the source of the binaries clear. Install on drive `D:` for
best performance.
After much detective work it turns out that the OpenSSH Windows versions
installed by Chocolatey aren't what they seem:
- The latest pre-release named 9.5.0-beta20240403:
https://community.chocolatey.org/packages/openssh/9.5.0-beta20240403
is in reality 8.6.0.0p1-Beta from 2021-05-27:
https://github.com/PowerShell/Win32-OpenSSH/releases/download/V8.6.0.0p1-Beta/OpenSSH-Win64.zip
- The latest "stable" version 8.0.0.1 is in reality:
https://community.chocolatey.org/packages/openssh/8.0.0.1
is in reality 8.0.0.0p1-Beta:
https://github.com/PowerShell/Win32-OpenSSH/releases/download/v8.0.0.0p1-Beta/OpenSSH-Win64.zip
Stefan Eissing [Fri, 21 Mar 2025 12:45:37 +0000 (13:45 +0100)]
multi_ev: fixes regarding connection shutdowns
When handling connections (not transfers) related events, always use the
passed `conn` and not `data->conn` as the transfer does not need to have
the same connection.
Fix handling of conn pollset diffs to disregard the transfer.
Viktor Szakats [Wed, 19 Mar 2025 23:55:55 +0000 (00:55 +0100)]
tests: build non-debug unit tests with autotools, run them
Before this patch, autotools disabled building unit tests for
non-debug-enabled (`DEBUGBUILD`) builds. runtests skipped running this
combination, though they were built in cmake builds. There seems to be
no technical reason anymore for these restrictions. This patch removes
them, allowing to build and run unit tests for non-debug-enabled builds.
To improve unit test build and run coverage.
- autotools: do not disable building unit tests for non-debug-enabled
build. Bringing behavior closer to cmake builds. (There are still
exceptions in autotools, something for another PR)
- runtests: run unit tests for non-debug-enabled builds.
It extends coverage by 50 tests.
- `lib/altsvc.c`: fix to include `CURL_TIME` support in libcurlu, for
unit tests. It fixes test 1654, and syncs `CURL_TIME` behavior with
test 1660 and `lib/hsts.c`.
Viktor Szakats [Wed, 19 Mar 2025 17:58:56 +0000 (18:58 +0100)]
mbedtls: re-enable an error check
While adding support for key blobs, a check and error code update moved
after some logic, resulting in the updated code not checked anymore.
Detected by clang-tidy:
```
lib/vtls/mbedtls.c:768:7: error: Value stored to 'ret' is never read [clang-analyzer-deadcode.DeadStores,-warnings-as-errors]
768 | ret = MBEDTLS_ERR_PK_TYPE_MISMATCH;
| ^
```
Ref: https://github.com/curl/curl/actions/runs/13953249156/job/39057979349?pr=16764#step:12:178
Viktor Szakats [Mon, 17 Mar 2025 23:39:57 +0000 (00:39 +0100)]
cmake: fix clang-tidy builds to verify tests, fix fallouts
- cmake: disable test bundles for clang-tidy builds.
clang-tidy ignores #included .c sources, and incompatible with unity
and bundles. It caused clang-tidy ignoring all test sources. It also
means this is the first time tests sources are checked with
clang-tidy. (autotools doesn't run it on tests.)
- cmake: update description for `CURL_TEST_BUNDLES` option.
- fix tests using special `CURLE_*` enums that were missing from
`curl/curl.h`. Add them as reserved codes.
- fix about ~50 other issues detected by clang-tidy: unchecked results,
NULL derefs, memory leaks, casts to enums, unused assigments,
uninitialized `errno` uses, unchecked `open`, indent, and more.
- drop unnecessary casts (lib1533, lib3207).
- suppress a few impossible cases with detailed `NOLINT`s.
Viktor Szakats [Sat, 22 Mar 2025 09:41:44 +0000 (10:41 +0100)]
test613: make it pass on Windows, fix postprocess, unignore in CI
- on native Windows (also when using MSYS2 openssh), the group and other
permissions do not end up as requested by Perl's chmod:
```diff
--- log/8/check-expected
+++ log/8/check-generated
@@ -1,3 +1,3 @@
d????????? N U U N ??? N NN:NN asubdir[LF]
--rw?rw?rw? 1 U U 37 Jan 1 2000 plainfile.txt[LF]
+-rw?r-?r-? 1 U U 37 Jan 1 2000 plainfile.txt[LF]
-r-?r-?r-? 1 U U 47 Dec 31 2000 rofile.txt[LF]
```
Ref: https://github.com/curl/curl/actions/runs/14004029192/job/39215359241?pr=16781#step:15:1596
Fix it by ignoring group and other attributes.
- fix failing postprocess cleanup by making the read-only test file
writeable again before deleting it. Fixing:
```
Directory not empty at ../../tests/libtest/test613.pl line 83.
```
(seen on Windows with Git for Windows `perl.exe`)
Viktor Szakats [Mon, 24 Feb 2025 23:49:21 +0000 (00:49 +0100)]
runtests: use `setfacl` on Cygwin/MSYS, if present
To use a native Cygwin tool instead of the Windows `icacls`. It allows
running under Cygwin/MSYS without Windows system folders in the `PATH`.
Also: fix indentation and tidy up syntax of the `icacls` branch.
Note: As of this commit, these `setfacl` and `icacls` calls are not
necessary for a successful CI run. This includes OpenSSH for Windows
tests, that aren't run by default. Keep them anyway, because locally
they may be necessary depending on environment.
Reported-by: Brian Inglis
Fixes #16437
Ref: #16803
Closes #16465
Weng Xuetian [Sun, 23 Mar 2025 05:42:26 +0000 (22:42 -0700)]
asyn-thread: check thread_data->init in Curl_resolver_getsock
resolver may call destroy_async_data after the name is resolved and
corresponding socketpair is already closed at this point. Any following
call to Curl_resolver_getsock should not set the fd.
Viktor Szakats [Sun, 23 Mar 2025 20:53:49 +0000 (21:53 +0100)]
libssh2: fix to ignore `known_hosts` if SHA256 host public key is set
Syncing behavior with MD5 host public keys.
libcurl implemented to force a host key type for hosts is present in
`known_hosts`, and disabled this logic when an MD5 host public key is
explicitly set. libcurl later received support for SHA256 host public
keys. This update missed to extend the `known_hosts` logic with the new
key type.
This caused test 3022 to fail if a pre-existing `known_hosts` listed
the test server IP (127.0.0.1) with a non-RSA host key algo.
Viktor Szakats [Sat, 22 Mar 2025 21:35:33 +0000 (22:35 +0100)]
test612: SCP `rm` the uploaded remote file (not the local source), unignore in CI
It accidentally worked on all CI-tested operating systems, except on
native Windows.
Fixing:
```
=== Start of file stderr612
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
[...]
curl: (21) rm command failed: Operation failed
```
Ref: https://github.com/curl/curl/actions/runs/14004029192/job/39215359241?pr=16781#step:15:1424
Also remove this test from the ignore list in GHA/windows.
Viktor Szakats [Fri, 21 Mar 2025 13:39:55 +0000 (14:39 +0100)]
runtests: support running tests under wine or qemu
To run curl, tests and servers via `wine`:
```shell
export CURL_TEST_EXE_RUNNER=wine
```
runtests prefixes commands with the specified runner. For systems where
this isn't automatic or supported, e.g. macOS.
Yedaya Katsman [Sat, 15 Mar 2025 21:02:27 +0000 (23:02 +0200)]
secureserver.pl, genserv.sh: cleanups
stunnel: print configuration actually in file
Instead of duplicating all the logic of writing the stunnel
configuration, and having to keep it up to date, when running in verbose
mode print the actual contents of the file after writing it.
Viktor Szakats [Fri, 21 Mar 2025 10:48:27 +0000 (11:48 +0100)]
runtests: fix test key format for libssh2 WinCNG (and others)
SFTP/SCP tests were failing in CI with WinCNG libssh2 since we first
added such job. With `curl: (67) Authentication failure`.
The reason is that the default `ssh-keygen` RSA private key format
changed to OpenSSH (RFC4716) in 2018. libssh2 does not support this
format with some of its crypto backends.
Fix it by generating keys explicitly in PEM format as necessary via
the `-m` option. This format is universally recognized for RSA keys.
2018-08-24: https://www.openssh.com/txt/release-7.8: OpenSSH format becomes default
2010-08-23: https://www.openssh.com/txt/release-5.6: `-m` option first supported
This fixed the auth issue, just to reveal a known flakiness issue in
libssh2 + WinCNG, causing:
```
curl: (2) Failure establishing ssh session: -8, Unable to exchange encryption keys
```
Ref: https://github.com/curl/curl/actions/runs/14000494428/job/39205633258?pr=16781#step:15:1796
Tracked here: https://github.com/libssh2/libssh2/issues/804
Mitigated in libssh2 tests by retrying them.
Due to this, keep ignoring these test results.
Also:
- add an env to customize key format: `CURL_TEST_SSH_KEY_FORMAT`
- display the generated format in the log.
- GHA/linux: document the wolfSSH error code causing it to fail tests:
```
curl: (79) wolfssh SFTP connect error -1051 / WS_MATCH_KEY_ALGO_E / cannot match key algo with peer
```
Peter Kokot [Thu, 20 Mar 2025 23:37:42 +0000 (00:37 +0100)]
cmake: replace exec_program() with execute_process()
The `exec_program()` is deprecated as of CMake 3.0.
This also removes the `rm_out` variable as it isn't used in the output.
In `execute_process()` the `ERROR_QUIET` and `OUTPUT_QUIET` resemble
the behavior of `exec_program(OUTPUT_VARIABLE)` behavior in this case.
Viktor Szakats [Thu, 20 Mar 2025 01:03:38 +0000 (02:03 +0100)]
configure: fix ECH detection with MultiSSL
Detect OpenSSL and wolfSSL support independently. Pass detection if
either of them has support. Before this patch wolfSSL results overwrote
OpenSSL detection results when both backends were enabled.
Also fix output message when both of them support ECH.
Viktor Szakats [Tue, 25 Feb 2025 17:13:38 +0000 (18:13 +0100)]
runtests: drop logic calling the `handle` tool (Windows)
In the cases observed throughout the last year, `handle64` run once per
test run, but with no action (match or task kill). It did not help with
flakiness and seems redundant.
runtests launched it (if present) in Cygwin/MSYS jobs too, where it
probably shouldn't have, because we have seen no flakiness there. In CI
the tool was present and launched in MSYS2 jobs, but not in Cygwin.
After this patch the "clearlocks" warning remain in the log. They are
consistently appearing once in every MSVC CI log, early in the tests:
```
test 3207 SKIPPED: curl lacks OpenSSL support
[...START-OF-TESTS...]
test 0003...[HTTP POST with auth and contents but with content-length set to 0]
--pd---e--- OK (3 out of 1596, remaining: 17:50, took 1.423s, duration: 00:02)
test 0007...[HTTP with cookie parser and header recording]
--pd--oe--- OK (7 out of 1596, remaining: 07:51, took 1.485s, duration: 00:02)
test 0006...[HTTP with simple cookie send]
--pd---e--- OK (6 out of 1596, remaining: 09:11, took 1.488s, duration: 00:02)
test 0005...[HTTP over proxy]
--pd---e--- OK (5 out of 1596, remaining: 11:03, took 1.491s, duration: 00:02)
CUSTOMBUILD : error : 169: cleardir(log/8/lock) failed [D:\a\curl\curl\bld\tests\test-ci.vcxproj]
test 0001...[HTTP GET]
--pd---e--- OK (1 out of 1596, remaining: 55:34, took 1.466s, duration: 00:02)
test 0004...[Replaced internal and added custom HTTP headers]
```
Ref: https://github.com/curl/curl/actions/runs/13546192228/job/37858323380?pr=16484#step:14:167
Viktor Szakats [Mon, 17 Mar 2025 17:46:42 +0000 (18:46 +0100)]
runtests: auto-detect test bundle builds
If libtests, units and servers binaries are all present, auto-enable
bundle mode.
Drop manual runtests option.
Note: Make sure to "make clean" before changing the test bundle build
setting.
Also fix to append executable extension to all libtest and unit test
executables when launching them. This should make it a tiny bit faster
on Windows.
Aquila Macedo [Fri, 7 Mar 2025 21:40:34 +0000 (18:40 -0300)]
runtests: add feature-based filtering
This commit introduces support for features in the test selection
process by adding them to the keywords list with the `feat:` prefix. It
allows users to specify features to run only tests with them, or exclude
tests using `!feat:<feature>`, similar to how keywords are handled.
Viktor Szakats [Mon, 17 Mar 2025 13:05:12 +0000 (14:05 +0100)]
GHA/windows: skip flaky test 498
On suspect of strain on the runtime env/pipes, disable this test, which
is flaky due to `runtests` detecting a 2009 result code from curl, while
curl is returning the expected 56:
```
test 0498...[Reject too large HTTP response headers on endless redirects]
curl returned 2009, when expecting 56
498: exit FAILED
== Contents of files in the log/5/ dir after test 498
[...]
0 0 0 0 0 0 0 0 --:--:-- 0:00:10 --:--:-- 0
curl: (56) Too large response headers: 6144086 > 6144000
```
In such cases the number of log lines for this single test is 4800. In
comparison the total number of log lines for a clear test run is 3800.
These attributes were causing unexplained warnings while playing with
PR #16738: In `CURLDEBUG` builds with mingw, gcc (14.2.0), and `-O3`,
while building `libcurlu`. `-O3` is required. May be related to having
the `CURLDEBUG` allocators in the same source file as their callers
(unity mode). PR #16738 moves `memdebug.c` into the main unity unit.
Unclear why it doesn't affect `libcurl`.
E.g. CI job `mingw, CM ucrt-x86_64 schannel R TrackMemory` CI job:
https://github.com/curl/curl/actions/runs/13888662354/job/38856868429
Viktor Szakats [Sun, 8 Sep 2024 22:33:04 +0000 (00:33 +0200)]
tests/server: support bundle binary
Extend existing `--enable-test-bundles` and `-DCURL_TEST_BUNDLES=ON`
options to also bundle test server programs into a single binary. With
autotools, also bundle auxiliary libcurl sources for a "unity"-style
build.
It saves almost 10 minutes per run, across all CI jobs.
On average it makes `build tests` steps 25% faster.
With CMake, it brings down `testdeps` build steps to 32 to 37, from
45 to 64 before this patch, with unity. Without unity it brings it down
from 400-420 to 280-300. For comparison, without unity and bundles,
the number of build steps is around 1850.
With autotools the gain is possibly larger because this patch does unity
and bundle for test servers.
The total reduction of build steps / log lines is 12000. It's 44% of
reduction on average across all CI jobs.
Viktor Szakats [Sat, 15 Mar 2025 11:03:56 +0000 (12:03 +0100)]
GHA/windows: unignore 2310, disable SCP/FTP for vcpkg `libssh2[core]`
Skipping these tests saves time and reduces test logs from 11500 lines
to 3800.
Tests are permanently broken due to `curl: (67) Authentication failure`.
This libssh2 is built with WinCNG. Builds using libcrypto from OpenSSL
work fine.
Viktor Szakats [Sat, 15 Mar 2025 01:39:05 +0000 (02:39 +0100)]
asyn-thread: drop `free()` on non-heap address
seen with mingw-w64 gcc 14.2.0 while playing with other modifications:
```
lib/asyn-thread.c: In function 'init_resolve_thread':
lib/asyn-thread.c:447:5: warning: 'free' called on pointer 'data' with nonzero offset 3264 [-Wfree-nonheap-object]
447 | free(td);
| ^~~~~~~~
```
Where `td` is:
```c
struct thread_data *td = &data->state.async.thdata;
```