These tests reach out to external services (httpbin, YouTube, ...) and
flake on CI runners whenever those services are slow or unreachable.
The previous shard runner script silently masked these failures; now
that runs report them faithfully, default the filter to -*_Online.
Override via workflow_dispatch + the gtest_filter input to include
them when explicitly desired.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Skip SSLTest.ResponseBodyTerminatedByConnectionClose under
CPPHTTPLIB_MBEDTLS_SUPPORT until the close_notify-mid-response handling
is brought into parity with the OpenSSL and wolfSSL backends. The test
verifies a successful read past the server's close, which mbedTLS
currently reports as an I/O error.
Mark the mbedTLS matrix legs (ubuntu and macos) as
continue-on-error: true. Several timing-sensitive ServerTest cases
(PostMethod2, GetStreamed, Brotli, ...) flake under ASAN+mbedTLS in
ways unrelated to cpp-httplib code; isolating these into a non-blocking
slot keeps master green while the flakiness is investigated separately.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add a libwolfssl entry to lsan_suppressions.txt to mirror the existing
libcrypto rule: the wolfSSL ECC subsystem caches per-handshake buffers
that are only freed at library shutdown, which the test binaries do
not perform. These are not leaks in cpp-httplib code.
Disable fail-fast on the ubuntu / macos / windows matrices so a failure
in one TLS backend does not cancel the others; with the runner now
detecting failures correctly, we want to see the full picture per run.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The previous logic considered a shard "passed" if its log contained any
[ PASSED ] line, missing the case where some tests pass and some fail
(both [ PASSED ] N tests. and [ FAILED ] M tests, listed below:
appear in the gtest summary). Exit codes from the test binaries were
also ignored.
Now require both: an [ PASSED ] line, no [ FAILED ] line, and a
zero exit code. Track each shard's PID so wait can surface non-zero
exits.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Add reproducer for #2431 (getaddrinfo_a use-after-free)
On Linux/glibc, getaddrinfo_with_timeout() runs DNS asynchronously via
getaddrinfo_a(GAI_NOWAIT) using a stack-local gaicb. When gai_suspend()
hits the connection timeout, gai_cancel() is called and the function
returns immediately — but gai_cancel() is non-blocking and can return
EAI_NOTCANCELED, leaving the resolver worker thread alive and still
referencing the destroyed stack frame.
Adds three opt-in gtest cases (GetAddrInfoAsyncCancelTest.*) that
exercise the cancel path repeatedly. They are gated on Linux/glibc +
CPPHTTPLIB_USE_NON_BLOCKING_GETADDRINFO at compile time, and on the
CPPHTTPLIB_TEST_ISSUE_2431=1 env var at runtime, so a normal `make
test` run is unaffected.
Also adds a dedicated CI job (issue-2431-repro) and a Docker-based
local runner (test/run_issue_2431_repro.sh) that sinkhole UDP/53 so
the timeout branch is taken, and run the test under ASAN/LSAN. With
the bug present these runs are expected to fail; with a fix applied
they should pass.
Refs: https://github.com/yhirose/cpp-httplib/issues/2431
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Fix split build for #2431 reproducer tests
The new GetAddrInfoAsyncCancelTest cases call detail::getaddrinfo_with_timeout
directly. In split builds (make test_split) split.py moves the definition into
httplib.cc and strips `inline`, so the symbol is not declared in the public
httplib.h and test.cc fails to compile -- breaking the ubuntu/test-no-exceptions
CI jobs that the PR description says should be unaffected.
Add a forward declaration in test.cc, gated by the same #if as the tests
themselves, so it links against the split-build symbol without changing the
header-only build.
* Cap issue-2431 repro job at 5 minutes
The bug manifests as orphan getaddrinfo_a resolver workers that keep the
runner from completing job teardown -- the previous run had all steps
succeed in ~1m37s but then hung in "Cleaning up orphan processes" for
~57m before GitHub force-killed the job.
A job-level timeout-minutes makes the failure signal fast and predictable:
bug present -> killed at 5 min, bug fixed -> ~2 min pass. Step-level timeout
isn't enough since the hang is in post-job cleanup, not the test step.
* Enable ASAN detect_stack_use_after_return for #2431 repro
The bug is a textbook stack-use-after-return: a stack-local struct gaicb
is destroyed when getaddrinfo_with_timeout returns after gai_cancel()
yields EAI_NOTCANCELED, then the still-live resolver worker thread writes
back into the freed frame. ASAN's detect_stack_use_after_return is the
direct detector for exactly this pattern -- enabling it lets the failure
surface as a clear ASAN diagnostic during the test run instead of as an
orphan-process hang at job teardown.
* Revert ASAN detect_stack_use_after_return for #2431 repro
The option did not detect the bug in CI -- the resolver worker write
likely lands on the heap (via the gaicb's pai pointer) or happens after
the test process exits, neither of which stack-use-after-return can
catch. Roll back to relying on the job-level timeout: bug present ->
post-cleanup hangs ~8min then job-level timeout cancels at 10min total;
bug fixed -> job completes in ~2min.
* Switch issue-2431 repro to a delayed loopback DNS test fixture
The previous repro setup dropped UDP/53 outright, which made glibc's
resolver hang forever on every lookup -- the worker never actually
received a response and so never reached the buggy write-back path
that #2431 is about. As a result, neither the broken HEAD nor the
fix made any visible difference in CI: both produced "tests pass +
post-cleanup hangs ~10min" because the orphan resolver thread is a
structural property of *any* getaddrinfo path on a hung resolver,
not a property of the bug.
Replace the sinkhole with a small loopback test fixture
(test/dns_test_fixture.py, ~50 lines, stdlib only) that answers DNS
queries after a 3s delay -- longer than the test's 1s timeout. An
iptables NAT rule routes the test job's lookups to the fixture
without touching /etc/resolv.conf, so the rest of the runner's DNS
behaviour is unaffected.
With ASAN's detect_stack_use_after_return enabled, the worker's
late write-back into the destroyed gaicb stack frame is now caught
as a stack-use-after-return diagnostic, so the broken HEAD fails
fast at the test step (clear red) and the fix turns the same job
green in well under a minute.
Same fixture is wired into both the GitHub Actions job and the
docker-based test/run_issue_2431_repro.sh script, so local repro on
macOS and CI repro on Linux exercise the identical path.
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Remove 32-bit limitation
* Fix build problems
* Add 32-bit disclaimer and fix MSVC x86 warnings
- Move 32-bit warning to top of README with strong disclaimer
- Add static_cast<size_t> to fix truncation warnings on 32-bit MSVC
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* WebSocket support
* Validate selected subprotocol in WebSocket handshake
* Fix problem with a Unit test
* Dynamic Thread Pool support
* Fix race condition in new Dynamic ThreadPool
* Fix problem with 'windows without SSL`
* Fix payload limit enforcement for requests without Content-Length on Windows
- Enable MSG_PEEK on Windows (non-SSL builds) to detect payloads without Content-Length
- Only use MSG_PEEK when payload_max_length is set to a finite value to avoid blocking
- Use read_content_without_length for actual size checking to support any payload limit
- Set 413 Payload Too Large status before rejecting oversized requests
This fixes three test cases on Windows:
- RequestWithoutContentLengthOrTransferEncoding (no payload limit)
- NoContentLengthPayloadLimit (8-byte limit)
- NoContentLengthExceeds10MB (10MB limit)
* clang-format
* Add zstd support
* Add zstd to CI tests
* Use use zstd cmake target instead of ZSTD. Use cmake variable for found packages
* Add missing comment for HTTPLIB_REQUIRE_ZSTD
* Fix test.yaml rebase error
* Use zstd::libzstd target
* Add include and library paths to ZSTD args
* Run clang-format
* Add zstd to httplibConfig.cmake.in
* Wrap poll()/WSAPoll() in a function
Instead of using a macro for poll() on Windows, which breaks when the
implementation is compiled separately, add a detail::poll_wrapper()
function that dispatches to either ::poll() or ::WSAPoll().
* Build compiled library on Windows
* Revert "Fix typo in meson.build (#2070)"
This reverts commit 5c0135fa5d.
* Revert "build(meson): automatically use poll or select as needed (#2067)"
This reverts commit 2b5d1eea8d.
* Revert "Make poll() the default (#2065)"
This reverts commit 6e73a63153.
* Remove select() and use poll()
* Add workflow_dispatch with Google Test filter
Add the workflow_dispatch trigger to the test.yaml workflow. Includes an
input for an optional Google Test filter pattern.
* Add OS selection to workflow_dispatch
* Fix wording
This integrates the "main" test suite (test/test.cc) in Meson.
This allows to run the tests in the CI with the Meson-built version of
the library to ensure that nothing breaks unexpectedly.
It also simplifies life of downstream packagers, that do not have to
write a custom build script to split the library and run tests but can
instead just let Meson do that for them.
In order to test the split version (.h + .cc via split.py):
- Added a test_split program in the test directory whose main purpose is
to verify that it works to compile and link the test case code against
the split httplib.h version.
- Moved types needed for test cases to the “header part” of httplib.h.
Also added forward declarations of functions needed by test cases.
- Added an include_httplib.cc file which is linked together with test.cc
to verify that inline keywords have not been forgotten.
The changes to httplib.h just move code around (or add forward
declarations), with one exception: detail::split and
detail::process_client_socket have been converted to non-template
functions (taking an std::function instead of using a type parameter for
the function) and forward-declared instead. This avoids having to move
the templates to the “header part”.
* *Add server fuzzer target and seed corpus
* Add fuzz_test option to Makefile
* Fix#685
* Try to fix Github actions on Ubuntu
* Added ReadTimeoutSSL test
* Comment out `-fsanitize=address`
* Rebase upstream changes
* remove address sanitizer temporarily
* Add separate Makefile for fuzzing
* 1. Remove special char from dictionary
2. Clean fuzzing/Makefile
* Use specific path to avoid accidently linking openssl version brought in by oss-fuzz
* remove addition of flags
* Refactor Makefile
* Add missing newline
* Add fuzztest to github workflow
* Fix
Co-authored-by: yhirose <yuji.hirose.bug@gmail.com>