Skip to content

Add ASan/TSan/Valgrind configs and GitHub Actions CI#21

Merged
dallison merged 4 commits intomainfrom
sanitizers-and-ci
May 4, 2026
Merged

Add ASan/TSan/Valgrind configs and GitHub Actions CI#21
dallison merged 4 commits intomainfrom
sanitizers-and-ci

Conversation

@dallison
Copy link
Copy Markdown
Owner

@dallison dallison commented May 3, 2026

Summary

  • Add --config=asan, --config=tsan, and --config=valgrind to .bazelrc, mirroring the configuration used by the dallison/co coroutines repository.
  • Add a GitHub Actions CI workflow that:
    • Builds and tests on ubuntu-latest, ubuntu-24.04-arm, and macos-latest (with --config=apple_silicon).
    • Runs the test suite under ASan and TSan on ubuntu-latest.
    • Runs the test suite under Valgrind Memcheck on ubuntu-latest.
    • Uploads bazel-testlogs on failure.
  • Bump coroutines to 3.3.1 to pick up the matching sanitizer / fiber-cooperation hooks.
  • Fix a heap-buffer-overflow caught by ASan in sockets_test: the UDP unicast and broadcast tests called std::strcmp on a Receive_buffer sized exactly TEST_DATA.size() (no NUL terminator). The preceding ASSERT_EQ on a string_view already validates the bytes fully, so the redundant strcmp calls were removed.

Test plan

Locally on macOS arm64 with the new configs:

  • bazel test //... --config=apple_silicon — all 6 tests pass
  • bazel test //... --config=apple_silicon --config=asan — all 6 tests pass (previously caught the unicast strcmp overflow now fixed)
  • bazel test //... --config=tsan on Linux (CI) — TSan on macOS arm64 hits a known runtime CHECK in sanitizer_allocator_secondary.h when freeing coroutine fiber stacks; restricting TSan to Linux in CI mirrors what the coroutines repo does.
  • bazel test //... --config=valgrind on Linux (CI) — Valgrind is not available on macOS arm64.

CI on this PR will exercise the Linux paths (TSan, Valgrind, plus the plain build/test on Ubuntu x86, Ubuntu arm, and macOS).

dallison and others added 4 commits May 3, 2026 16:55
Add `--config=asan`, `--config=tsan` and `--config=valgrind` to
.bazelrc, mirroring the configuration used by the dallison/co
coroutines repository.

Add a GitHub Actions workflow that builds and tests on
ubuntu-latest, ubuntu-24.04-arm and macos-latest, plus dedicated
sanitizer and Valgrind jobs on Linux.

Bump coroutines to 3.3.1 to pick up the matching sanitizer / fiber
cooperation hooks.

Fix a heap-buffer-overflow in sockets_test caught by ASan: the UDP
unicast and broadcast tests called std::strcmp on a Receive_buffer
sized exactly TEST_DATA.size(), which has no NUL terminator. The
preceding ASSERT_EQ on a string_view already validates the bytes
fully, so the strcmp calls are redundant and have been removed.
- payload_buffer_test: zero backing storage with calloc so Hexdump does not
  read uninitialized padding under Memcheck.  Tear down the resizable-buffer
  test with an explicit destructor plus free() after realloc, fixing ASan
  alloc-dealloc-mismatch from operator delete on malloc/realloc storage.
- pipe_test: compare fixed-length pipe reads with std::string_view instead of
  ASSERT_STREQ/strcmp on non-NUL-terminated buffers.  Skip the high-iteration
  OverFull stress tests under TSan where the sanitizer hits nested DEADLYSIGNAL
  on many fiber switches.
- sockets_test: skip UDP broadcast and multicast loopback tests on Apple
  platforms where GitHub Actions macOS runners reject or drop those packets.
SmallBlockAllocSimple, SmallBlockAlloc, and SmallBlockAllocFree used
placement-new into calloc storage but never destroyed the object or
released the block, which Valgrind reported as definitely lost.  Tear
down with an explicit destructor and free().
PayloadBuffer's VectorPush, VectorReserve, VectorResize, Realloc,
PrimeBitmapAllocator, and BitMapRun::Allocate all dereferenced pointers
into the buffer (hdr, p) after Allocate/Realloc/AllocateBitMapRun calls
that may have relocated the underlying buffer, leaving those pointers
dangling. Save the offset before any allocation and re-derive the
pointer afterward across all six call sites.

Also drop a leftover write through the dangling hdr in VectorPush that
slipped through a previous partial fix.

Add VectorPushWithResize, VectorReserveWithResize, and
VectorResizeWithResize regression tests that drive the resizer with a
small (256-byte) resizable buffer and verify data integrity afterward.
The existing tests all used fixed-size buffers and could not trigger
the bug.

Original fix by Damian Stulich <damjan.stulic@getcruise.com>.
@dallison dallison merged commit f7b3e20 into main May 4, 2026
12 checks passed
dallison added a commit that referenced this pull request May 4, 2026
* Add ASan/TSan/Valgrind configs and GitHub Actions CI

Add `--config=asan`, `--config=tsan` and `--config=valgrind` to
.bazelrc, mirroring the configuration used by the dallison/co
coroutines repository.

Add a GitHub Actions workflow that builds and tests on
ubuntu-latest, ubuntu-24.04-arm and macos-latest, plus dedicated
sanitizer and Valgrind jobs on Linux.

Bump coroutines to 3.3.1 to pick up the matching sanitizer / fiber
cooperation hooks.

Fix a heap-buffer-overflow in sockets_test caught by ASan: the UDP
unicast and broadcast tests called std::strcmp on a Receive_buffer
sized exactly TEST_DATA.size(), which has no NUL terminator. The
preceding ASSERT_EQ on a string_view already validates the bytes
fully, so the strcmp calls are redundant and have been removed.

* Fix CI failures for ASan, TSan, Valgrind and macOS sockets

- payload_buffer_test: zero backing storage with calloc so Hexdump does not
  read uninitialized padding under Memcheck.  Tear down the resizable-buffer
  test with an explicit destructor plus free() after realloc, fixing ASan
  alloc-dealloc-mismatch from operator delete on malloc/realloc storage.
- pipe_test: compare fixed-length pipe reads with std::string_view instead of
  ASSERT_STREQ/strcmp on non-NUL-terminated buffers.  Skip the high-iteration
  OverFull stress tests under TSan where the sanitizer hits nested DEADLYSIGNAL
  on many fiber switches.
- sockets_test: skip UDP broadcast and multicast loopback tests on Apple
  platforms where GitHub Actions macOS runners reject or drop those packets.

* Free backing storage in small-block PayloadBuffer tests

SmallBlockAllocSimple, SmallBlockAlloc, and SmallBlockAllocFree used
placement-new into calloc storage but never destroyed the object or
released the block, which Valgrind reported as definitely lost.  Tear
down with an explicit destructor and free().

* Fix VectorHeader/pointer invalidation after buffer relocation

PayloadBuffer's VectorPush, VectorReserve, VectorResize, Realloc,
PrimeBitmapAllocator, and BitMapRun::Allocate all dereferenced pointers
into the buffer (hdr, p) after Allocate/Realloc/AllocateBitMapRun calls
that may have relocated the underlying buffer, leaving those pointers
dangling. Save the offset before any allocation and re-derive the
pointer afterward across all six call sites.

Also drop a leftover write through the dangling hdr in VectorPush that
slipped through a previous partial fix.

Add VectorPushWithResize, VectorReserveWithResize, and
VectorResizeWithResize regression tests that drive the resizer with a
small (256-byte) resizable buffer and verify data integrity afterward.
The existing tests all used fixed-size buffers and could not trigger
the bug.

Original fix by Damian Stulich <damjan.stulic@getcruise.com>.
dallison added a commit that referenced this pull request May 4, 2026
* Add ASan/TSan/Valgrind configs and GitHub Actions CI

Add `--config=asan`, `--config=tsan` and `--config=valgrind` to
.bazelrc, mirroring the configuration used by the dallison/co
coroutines repository.

Add a GitHub Actions workflow that builds and tests on
ubuntu-latest, ubuntu-24.04-arm and macos-latest, plus dedicated
sanitizer and Valgrind jobs on Linux.

Bump coroutines to 3.3.1 to pick up the matching sanitizer / fiber
cooperation hooks.

Fix a heap-buffer-overflow in sockets_test caught by ASan: the UDP
unicast and broadcast tests called std::strcmp on a Receive_buffer
sized exactly TEST_DATA.size(), which has no NUL terminator. The
preceding ASSERT_EQ on a string_view already validates the bytes
fully, so the strcmp calls are redundant and have been removed.

* Fix CI failures for ASan, TSan, Valgrind and macOS sockets

- payload_buffer_test: zero backing storage with calloc so Hexdump does not
  read uninitialized padding under Memcheck.  Tear down the resizable-buffer
  test with an explicit destructor plus free() after realloc, fixing ASan
  alloc-dealloc-mismatch from operator delete on malloc/realloc storage.
- pipe_test: compare fixed-length pipe reads with std::string_view instead of
  ASSERT_STREQ/strcmp on non-NUL-terminated buffers.  Skip the high-iteration
  OverFull stress tests under TSan where the sanitizer hits nested DEADLYSIGNAL
  on many fiber switches.
- sockets_test: skip UDP broadcast and multicast loopback tests on Apple
  platforms where GitHub Actions macOS runners reject or drop those packets.

* Free backing storage in small-block PayloadBuffer tests

SmallBlockAllocSimple, SmallBlockAlloc, and SmallBlockAllocFree used
placement-new into calloc storage but never destroyed the object or
released the block, which Valgrind reported as definitely lost.  Tear
down with an explicit destructor and free().

* Fix VectorHeader/pointer invalidation after buffer relocation

PayloadBuffer's VectorPush, VectorReserve, VectorResize, Realloc,
PrimeBitmapAllocator, and BitMapRun::Allocate all dereferenced pointers
into the buffer (hdr, p) after Allocate/Realloc/AllocateBitMapRun calls
that may have relocated the underlying buffer, leaving those pointers
dangling. Save the offset before any allocation and re-derive the
pointer afterward across all six call sites.

Also drop a leftover write through the dangling hdr in VectorPush that
slipped through a previous partial fix.

Add VectorPushWithResize, VectorReserveWithResize, and
VectorResizeWithResize regression tests that drive the resizer with a
small (256-byte) resizable buffer and verify data integrity afterward.
The existing tests all used fixed-size buffers and could not trigger
the bug.

Original fix by Damian Stulich <damjan.stulic@getcruise.com>.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant