Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
2f8b2ce
fix(portability): K1 — src/main.cpp:439:33: error: call to deleted fu…
joyful-ii-V-I Aug 1, 2026
bc4d5c7
fix(portability): K2 — src/mcpindex.h:28:10: fatal error: sys/event.h…
joyful-ii-V-I Aug 1, 2026
303eacc
fix(portability): K3 — profileScope.h:333/336 'pthread_threadid_np'/'…
joyful-ii-V-I Aug 1, 2026
e53a6b3
fix(portability): K4 — cc: error: unrecognized argument to '-fsanitiz…
joyful-ii-V-I Aug 1, 2026
50279da
fix(portability): K5 — link Threads::Threads explicitly (std::thread …
joyful-ii-V-I Aug 1, 2026
c6ca9e3
test(g1config): follow K4 — assert the G1 set as a filtered LIST, not…
joyful-ii-V-I Aug 1, 2026
b3f3b6b
fix(portability): clear the two quality-delta findings K1/K2 introduced
joyful-ii-V-I Aug 1, 2026
41ec669
fix(portability): L1 — `--cache=<existing directory>` → std::bad_allo…
joyful-ii-V-I Aug 1, 2026
0bf2f88
fix(portability): L2 — kqueue degrade alert fires unconditionally on …
joyful-ii-V-I Aug 1, 2026
bc33d36
test(portability): L3 — GNU stat trap breaks 12 gate scripts' inode/m…
joyful-ii-V-I Aug 1, 2026
33919e0
ci(portability): L4 — CI shallow clone: add fetch-depth: 0 to all thr…
joyful-ii-V-I Aug 1, 2026
03407ce
fix(portability): L5 — regex divergence: /\Q\E/ accepted on Linux (li…
joyful-ii-V-I Aug 1, 2026
84e7f21
test(portability): L6 — NFD unicode churn join: an NFD-named file get…
joyful-ii-V-I Aug 1, 2026
0fe4d71
docs(portability): L7 — a "Building on Linux" note in CONTRIBUTING §1
joyful-ii-V-I Aug 1, 2026
d16aa07
test(portability): M3 — GNU grep does not expand '\t' in -E patterns
joyful-ii-V-I Aug 1, 2026
5d0eae4
build(portability): M1 — exempt libstdc++'s string_view.tcc from unsi…
joyful-ii-V-I Aug 1, 2026
7450464
fix(portability): M2 — a catastrophic --regex hangs forever on libstd…
joyful-ii-V-I Aug 1, 2026
1c09462
test(portability): M1b — audit the libstdc++ string_view exemption in…
joyful-ii-V-I Aug 1, 2026
cff49a6
fix(grep): M2 follow-up — refusal wording no longer claims valid patt…
joyful-ii-V-I Aug 2, 2026
41e0e0f
build(portability): N1 — complete the libstdc++ deliberate-wrap ignor…
joyful-ii-V-I Aug 2, 2026
a7aa85a
fix(ingest): N2 — the compiled tags-query cache now OWNS its TSQuery …
joyful-ii-V-I Aug 2, 2026
9916e7a
fix(grep): N3/M2-b — bounded-inner quantifiers under an unbounded out…
joyful-ii-V-I Aug 2, 2026
6a23fea
test(cochange): O1 — re-anchor the surprise gate onto a deterministic…
joyful-ii-V-I Aug 2, 2026
089bdbc
test(paging): O2 — re-anchor the --mentions/--stray-content paging ar…
joyful-ii-V-I Aug 2, 2026
6e6c4b1
test(degrade): O3 — NDEBUG-unobservable degrade arms SKIP with a name…
joyful-ii-V-I Aug 2, 2026
5950db4
fix(g1): N2 follow-up — lsan_suppressions covers ONLY interned gramma…
joyful-ii-V-I Aug 2, 2026
1065cf1
test(floormark): O4 residue — arm (8) chooses a pr-context base with …
joyful-ii-V-I Aug 2, 2026
420a4a7
test(regression): P1 — the absorb loop echoes the failing gate's own …
joyful-ii-V-I Aug 2, 2026
acfcfce
test(cachefuzz): P2 — the ASan sweeps SKIP with a named reason where …
joyful-ii-V-I Aug 2, 2026
738868d
build(portability): P3 — the 7 hand-rolled harness compiles ask the f…
joyful-ii-V-I Aug 2, 2026
f54705d
test(packtask): P4 — the --for-parity arm keeps rc/stderr/bytes, so i…
joyful-ii-V-I Aug 2, 2026
b2cbbda
fix(lint): Q2 — query predicates were a NO-OP on x86-64 gcc (unspecif…
joyful-ii-V-I Aug 2, 2026
48f1f21
fix(hash): Q1 — --for aborted the G1 build on x86-64: implicit char→u…
joyful-ii-V-I Aug 2, 2026
a269c76
docs(showcase): re-derive the top-100 --pack-signatures figure the FN…
joyful-ii-V-I Aug 2, 2026
a3f0039
test+ci: arm (g) preserves rc/stderr; sanitizer log_path + failure ar…
joyful-ii-V-I Aug 2, 2026
484b001
scrub: the detector no longer spells the identifiers it hunts
joyful-ii-V-I Aug 2, 2026
c3f5cb4
fix(clones): the 9th site of the char->unsigned-char sign-change clas…
joyful-ii-V-I Aug 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 76 additions & 9 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,13 @@ jobs:
env:
CLANG_VERSION: "22"
steps:
# L4 (Linux probe): checkout@v4 defaults to a --depth 1 clone, which leaves ONE commit of history
# in the tree. The churn / co-change / ownership gates (churnjoincheck, hotspots, --owners, the
# quality short-horizon-churn kind) mine `git log` for real, so on a shallow checkout they do not
# error — they measure zero and fail, or worse, pass while measuring nothing. Full history it is.
- uses: actions/checkout@v4
with:
fetch-depth: 0 # churn/co-change gates read real git history — a shallow clone reddens them
Comment on lines 71 to +73

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Restrict the workflow token permissions.

This workflow has no permissions block. It runs checked-out repository code with the repository-default GITHUB_TOKEN scope, which can be broader than this read-only CI workflow requires.

Set top-level permissions to contents: read. Add another scope only when a step requires it.

Proposed fix
+permissions:
+  contents: read
+
 jobs:
🧰 Tools
🪛 zizmor (1.28.0)

[warning] 71-73: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/ci.yml around lines 71 - 73, Add a top-level permissions
block in the CI workflow granting only contents: read, and leave other token
scopes unset unless an existing step explicitly requires them. Keep the checkout
configuration and workflow steps unchanged.

Source: Linters/SAST tools


- name: Install clang-format / clang-tidy (PINNED major — see the job comment)
run: |
Expand Down Expand Up @@ -104,7 +110,13 @@ jobs:
os: [macos-14, ubuntu-24.04]
runs-on: ${{ matrix.os }}
steps:
# L4 (Linux probe): checkout@v4 defaults to a --depth 1 clone, which leaves ONE commit of history
# in the tree. The churn / co-change / ownership gates (churnjoincheck, hotspots, --owners, the
# quality short-horizon-churn kind) mine `git log` for real, so on a shallow checkout they do not
# error — they measure zero and fail, or worse, pass while measuring nothing. Full history it is.
- uses: actions/checkout@v4
with:
fetch-depth: 0 # churn/co-change gates read real git history — a shallow clone reddens them

- name: Install tooling (Linux)
if: runner.os == 'Linux'
Expand All @@ -126,12 +138,20 @@ jobs:
- name: "test/regression.sh (170+ gates: determinism, cache transparency, G4 XML, quality, …)"
run: RIPWIRE_BIN=build/ripwire bash test/regression.sh

# The Release build above defines NDEBUG, which compiles DEGRADED_PATH_ALERT out — so every
# degrade-path gate above passed for the WRONG REASON: it could not observe the alert it asserts.
# The e7405e7 qsnap fix was invisible to CI before it landed, and the 2026-07-27 round added several
# more degrade gates (shallow-clone v="unknown", the pr-context ref refusal, the doc-drift VERIFY
# demotion). Build a SECOND time with the plain local flavour and re-run the suite against it, so both
# the optimizer-visible Release behaviour and the degrade paths are covered — neither alone is enough.
# The Release build above defines NDEBUG, which compiles DEGRADED_PATH_ALERT out — so a degrade-path
# gate run against it cannot observe the alert it asserts. The e7405e7 qsnap fix was invisible to CI
# before it landed, and the 2026-07-27 round added several more degrade gates (shallow-clone
# v="unknown", the pr-context ref refusal, the doc-drift VERIFY demotion). Build a SECOND time with
# the plain local flavour and re-run the suite against it, so both the optimizer-visible Release
# behaviour and the degrade paths are covered — neither alone is enough.
#
# 2026-08-01: the two gates that assert an alert directly (estchargecheck #14, qualitystalecheck
# arms 7/8c) no longer pass — or fail — silently on the Release leg. Each probes the flavour with
# TWO independent readings (an unrelated already-gated degrade path, plus --version's build-type
# token) and, only when both agree the binary is NDEBUG, prints a SKIP naming what is unobservable
# and pointing at THIS second leg as where it is proven. If the alert is missing on a flavour that
# should see it, they still FAIL. So the Release leg is honestly green rather than either
# vacuously green (the 2026-07-27 trap) or unconditionally red (the same trap inverted).
- name: Configure (plain — NDEBUG off, so DEGRADED_PATH_ALERT compiles in)
run: cmake -S . -B build-debugalerts

Expand Down Expand Up @@ -163,24 +183,49 @@ jobs:
# matrix.os, not runner.os: the runner context does not exist at job-level env — GitHub's
# parser rejects the whole workflow (found by the first real Actions run; local YAML lint
# cannot see it). Step-level `if: runner.os` below is legal and stays.
ASAN_OPTIONS: ${{ matrix.os == 'macos-14' && 'detect_leaks=0:halt_on_error=1:abort_on_error=1' || 'detect_leaks=1:halt_on_error=1:abort_on_error=1' }}
UBSAN_OPTIONS: halt_on_error=1:print_stacktrace=1
# log_path: a sanitizer abort inside a gate that pipes 2>/dev/null leaves NO report in the log
# (CI round 3: an asan/x86-64 abort read as "pin no longer resolves"). With log_path the report
# lands in a file the failure artifact below preserves.
ASAN_OPTIONS: ${{ matrix.os == 'macos-14' && 'detect_leaks=0:halt_on_error=1:abort_on_error=1:log_path=/tmp/asanlog' || 'detect_leaks=1:halt_on_error=1:abort_on_error=1:log_path=/tmp/asanlog' }}
UBSAN_OPTIONS: halt_on_error=1:print_stacktrace=1:log_path=/tmp/asanlog
LSAN_OPTIONS: suppressions=${{ github.workspace }}/lsan_suppressions.txt
steps:
# L4 (Linux probe): checkout@v4 defaults to a --depth 1 clone, which leaves ONE commit of history
# in the tree. The churn / co-change / ownership gates (churnjoincheck, hotspots, --owners, the
# quality short-horizon-churn kind) mine `git log` for real, so on a shallow checkout they do not
# error — they measure zero and fail, or worse, pass while measuring nothing. Full history it is.
- uses: actions/checkout@v4
with:
fetch-depth: 0 # churn/co-change gates read real git history — a shallow clone reddens them

- name: Install tooling (Linux)
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends libxml2-utils ripgrep bc
sudo apt-get install -y --no-install-recommends libxml2-utils ripgrep bc clang

- name: Install tooling (macOS)
if: runner.os == 'macOS'
run: brew install ripgrep


# CLANG, not the default cc. G1's `integer` group is Clang-only and gcc rejects the whole option
# ("unrecognized argument to '-fsanitize=' option: 'integer'" — the first public CI run). CMakeLists.txt
# now filters the Clang-only members out under GCC, but that is the HONEST-DEGRADE path for a
# contributor, not something public CI should be running: pinning clang here keeps the COMPLETE G1
# stack on Linux, so the gates below mean the same thing on both matrix legs.
#
# Deliberately NOT applied to the release job: gcc there is a FEATURE. It is a second front end over
# the same tree and it found three real portability bugs on its first run.
- name: Configure (G1 sanitizer stack — clang, see the step comment)
if: runner.os == 'Linux'
env:
CC: clang
CXX: clang++
run: cmake -S . -B asan -DRIPWIRE_ASAN=ON

- name: Configure (G1 sanitizer stack)
if: runner.os == 'macOS'
run: cmake -S . -B asan -DRIPWIRE_ASAN=ON

- name: Build
Expand All @@ -204,6 +249,18 @@ jobs:
- name: Heavy verb — --edit-check (test/editcheckcheck.sh)
run: RIPWIRE_BIN=asan/ripwire bash test/editcheckcheck.sh

# cachefuzzcheck's two mutation tables ARE sanitizer sweeps: they drive corrupt/truncated/hostile cache
# blobs and corrupt qsnap blobs through the readers and assert that no sanitizer report fires. That needs
# an instrumented binary — RIPWIRE_ASAN_BIN is the whole point of the gate — and the `release` jobs, which
# configure only build/, cannot supply one. Until now the gate hard-FAILED there for the missing binary
# (PR #1, run 30732976779: "absorb gate (cachefuzzcheck.sh failed)" on BOTH release legs, that one line
# its only failure) while NO job anywhere ran the sweeps it exists for. The gate now skips those two arms
# with a named reason on a leg that has no ASan build, and this step is where they actually run: both
# variables point at the instrumented binary, so the ground-truth arms and the sanitizer arms agree by
# construction. Adding it here is what makes that skip reason true rather than an excuse.
- name: Sanitizer sweep — corrupt cache / qsnap blobs (test/cachefuzzcheck.sh)
run: RIPWIRE_BIN=asan/ripwire RIPWIRE_ASAN_BIN=asan/ripwire bash test/cachefuzzcheck.sh

# NOT a heavy verb — here because it is the ONLY gate whose subject is an integer-overflow class that
# a plain binary cannot observe. cppqualcheck §9 drives an unbalanced `operator>` frame through
# --from-trace; before the H4 W2b fixup that aborted the G1 build (rc=134) while the plain build ran
Expand Down Expand Up @@ -244,3 +301,13 @@ jobs:
# fixed and the review notes carry a self-date: at that point drift= can be gated at 0.
- name: Self-report (non-gating) — --doc-drift on our own docs
run: ./asan/ripwire . --doc-drift --with-history || true

# Sanitizer reports written via log_path survive gates that swallow stderr; keep them when a
# step failed so the log tells us WHICH abort happened, not just that one did.
- name: Upload sanitizer reports on failure
if: failure()
uses: actions/upload-artifact@v4
with:
name: sanitizer-reports-${{ matrix.os }}
path: /tmp/asanlog*
if-no-files-found: ignore
92 changes: 82 additions & 10 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -302,12 +302,21 @@ set(RIPWIRE_TS_OBJECTS
$<TARGET_OBJECTS:ts_c>
)

# ---- threading: std::thread / std::mutex need an explicit link on most Unixes ----
# The parallel ingest and the MCP qsnap-prefetch worker are std::thread; on Apple platforms the pthread
# runtime is inside libSystem and nothing extra is needed, which is why this was never noticed here. On
# Linux it depends on the glibc version — merged into libc from 2.34 (so ubuntu-24.04 happens to link
# without it), a separate -lpthread before that, and -pthread also changes CODEGEN, not just the link
# line. Threads::Threads asks CMake for whatever this platform actually requires; on macOS it resolves
# to nothing, so the dev build is untouched.
find_package(Threads REQUIRED)

# ---- probe target: the Phase-1/2 proof binary ----
add_executable(ripwire_probe
src/tsprobe.cpp
${RIPWIRE_SRCS}
${RIPWIRE_TS_OBJECTS})
target_link_libraries(ripwire_probe PRIVATE tree-sitter)
target_link_libraries(ripwire_probe PRIVATE tree-sitter Threads::Threads)
target_include_directories(ripwire_probe PRIVATE
${tree_sitter_SOURCE_DIR}/lib/include
${_ripwire_generated_dir}
Expand All @@ -321,7 +330,7 @@ add_executable(ripwire
src/main.cpp
${RIPWIRE_SRCS}
${RIPWIRE_TS_OBJECTS})
target_link_libraries(ripwire PRIVATE tree-sitter)
target_link_libraries(ripwire PRIVATE tree-sitter Threads::Threads)
target_include_directories(ripwire PRIVATE
${tree_sitter_SOURCE_DIR}/lib/include
${_ripwire_generated_dir}
Expand Down Expand Up @@ -393,14 +402,41 @@ set(RIPWIRE_GRAMMAR_TARGETS
ts_javascript ts_bash ts_java ts_ruby ts_json ts_csharp ts_c)
set(RIPWIRE_RUNTIME_COMPILE_TARGETS ripwire_probe ripwire tree-sitter ${RIPWIRE_GRAMMAR_TARGETS})
set(RIPWIRE_RUNTIME_LINK_TARGETS ripwire_probe ripwire)
# The C++ subset of the compile list — the only targets that include a C++ standard library at all, and so
# the only ones the libstdc++ header exemption below has anything to say about (the grammars are C).
set(RIPWIRE_OWNED_CXX_TARGETS ripwire_probe ripwire)
if(RIPWIRE_TESTS)
list(APPEND RIPWIRE_RUNTIME_COMPILE_TARGETS ripwire_test_csr ripwire_test_pagerank ripwire_test_radix)
list(APPEND RIPWIRE_RUNTIME_LINK_TARGETS ripwire_test_csr ripwire_test_pagerank ripwire_test_radix)
list(APPEND RIPWIRE_OWNED_CXX_TARGETS ripwire_test_csr ripwire_test_pagerank ripwire_test_radix)
endif()
# G1's `integer` is a CLANG-ONLY UBSan group (unsigned-integer-overflow, implicit-*-truncation,
# implicit-integer-sign-change — the defined-but-suspicious conversions, not UB). GCC has no such group
# and rejects the whole option: "cc: error: unrecognized argument to '-fsanitize=' option: 'integer'",
# which is where the ubuntu asan leg of the first public CI run died (default cc there is gcc). The three
# `-fno-sanitize=` names and `-fsanitize-ignorelist=` below are members/features of that same Clang-only
# group, so they are dropped together — under GCC there is nothing for them to switch off.
#
# address / undefined / float-divide-by-zero / float-cast-overflow ARE all supported by GCC and stay.
# The result is a REAL but reduced stack on gcc, announced at configure time so nobody reads a green gcc
# asan run as full-G1 evidence. Public CI does not rely on this path: ci.yml pins the Linux asan job to
# clang and keeps the complete stack (see the job comment there). This branch is for a contributor who
# builds -DRIPWIRE_ASAN=ON with gcc — it must degrade honestly rather than fail to configure.
set(RIPWIRE_G1_SANITIZER_CHECKS address undefined integer float-divide-by-zero float-cast-overflow)
set(RIPWIRE_HAS_CLANG_INTEGER_SANITIZER ON)
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
list(REMOVE_ITEM RIPWIRE_G1_SANITIZER_CHECKS integer)
set(RIPWIRE_HAS_CLANG_INTEGER_SANITIZER OFF)
message(STATUS "G1 sanitizers: dropped 'integer' (+ its -fno-sanitize= members and -fsanitize-ignorelist=) "
"— Clang-only, GCC ${CMAKE_CXX_COMPILER_VERSION} rejects the option. Remaining: "
"${RIPWIRE_G1_SANITIZER_CHECKS}. Build with clang for the complete G1 stack.")
endif()
set(RIPWIRE_G1_SANITIZERS "-fsanitize=address,undefined,integer,float-divide-by-zero,float-cast-overflow")
list(JOIN RIPWIRE_G1_SANITIZER_CHECKS "," _ripwire_g1_check_list)
set(RIPWIRE_G1_SANITIZERS "-fsanitize=${_ripwire_g1_check_list}")
set(_ripwire_tree_sitter_ignorelist "${_ripwire_generated_dir}/tree_sitter_sanitizer_ignorelist.txt")
set(_ripwire_swift_ignorelist "${_ripwire_generated_dir}/swift_sanitizer_ignorelist.txt")
set(_ripwire_bash_ignorelist "${_ripwire_generated_dir}/bash_sanitizer_ignorelist.txt")
set(_ripwire_libstdcxx_ignorelist "${_ripwire_generated_dir}/libstdcxx_sanitizer_ignorelist.txt")
# Full G1 remains enabled on ripwire and every grammar. Pinned tree-sitter v0.26.9 intentionally uses
# defined C unsigned wrap throughout reverse loops and erase-at-zero iteration, so only that non-UB check
# is disabled target-wide for the pinned core. All other integer/undefined/conversion checks remain on.
Expand All @@ -417,6 +453,34 @@ file(WRITE "${_ripwire_swift_ignorelist}"
# Bash's scanner decrements zero-valued nesting depths after marking the scan complete; uint32 wrap is intentional.
file(WRITE "${_ripwire_bash_ignorelist}"
"[unsigned-integer-overflow]\nfun:scan\n")
# libstdc++'s std::basic_string_view::find/rfind scan loops are written `for (++__size; __size-- > 0;)`, so
# the counter wraps past zero BY DESIGN on the iteration that ends the loop. Under G1's Clang-only
# `integer` group that is a hard stop, because G1 is -fno-sanitize-recover=all: the first real Linux run
# (Ubuntu 24.04, clang 18 + libstdc++, full G1) aborted with
# string_view.tcc:124:25: runtime error: unsigned integer overflow: 0 - 1
# reached from rw::lowerExtensionOf (src/ingest.cpp:160) via string_view::rfind, and again at :109 (the
# find twin) partway through cachefuzzcheck's qsnap ASan sweep. This is library-internal, intentional, and
# not UB — nothing in ripwire can avoid it short of not calling find/rfind. libc++ has no such wrap, which
# is why macOS never saw it and why this entry is inert (but must still parse) on the Apple leg.
# Scoped as narrowly as the mechanism allows: these THREE libstdc++ headers' code, this ONE check. Every
# other integer and conversion check stays on for our own code, including in the same translation units.
#
# The re-smoke on the same Ubuntu 24.04 / clang 18 / libstdc++ image found std::basic_string carrying the
# identical deliberate-wrap idiom in two more headers, so all three entries share the one section:
# * bits/basic_string.h:490 — `_S_compare` returns `__n1 - __n2` computed in size_type, so any comparison
# whose left operand is the shorter string wraps by design. Reached from a plain `std::string`
# `operator<=`/`operator<` inside a sort comparator, i.e. from ordinary ripwire code that cannot avoid
# it short of not comparing strings.
# * bits/basic_string.tcc:689 — the basic_string twin of the string_view find/rfind loop above, same
# `for (++__size; __size-- > 0;)` shape, same wrap on the iteration that ends the loop.
# Both are library-internal, intentional and not UB; both abort the run under -fno-sanitize-recover=all;
# both are absent on libc++, which is why the Apple leg never saw them and why these entries are inert
# (but must still parse) on macOS. With the three entries in place the Linux ASan self-run exits 0 with
# empty stderr and cachefuzzcheck's 13 UBSan arms go green.
file(WRITE "${_ripwire_libstdcxx_ignorelist}"
"[unsigned-integer-overflow]\nsrc:*/bits/string_view.tcc\n"
"src:*/bits/basic_string.h\n"
"src:*/bits/basic_string.tcc\n")

if(RIPWIRE_ASAN)
foreach(_t IN LISTS RIPWIRE_RUNTIME_COMPILE_TARGETS)
Expand All @@ -426,13 +490,21 @@ if(RIPWIRE_ASAN)
foreach(_t IN LISTS RIPWIRE_RUNTIME_LINK_TARGETS)
target_link_options(${_t} PRIVATE ${RIPWIRE_G1_SANITIZERS})
endforeach()
target_compile_options(tree-sitter PRIVATE
-fno-sanitize=unsigned-integer-overflow
-fno-sanitize=implicit-signed-integer-truncation
-fno-sanitize=implicit-integer-sign-change
"-fsanitize-ignorelist=${_ripwire_tree_sitter_ignorelist}")
target_compile_options(ts_swift PRIVATE "-fsanitize-ignorelist=${_ripwire_swift_ignorelist}")
target_compile_options(ts_bash PRIVATE "-fsanitize-ignorelist=${_ripwire_bash_ignorelist}")
# Every exemption below names a check inside the Clang-only `integer` group, or uses
# -fsanitize-ignorelist=, which GCC does not implement. With `integer` absent there is nothing to
# exempt, and passing them anyway is the same "unrecognized argument" failure one level down.
if(RIPWIRE_HAS_CLANG_INTEGER_SANITIZER)
target_compile_options(tree-sitter PRIVATE
-fno-sanitize=unsigned-integer-overflow
-fno-sanitize=implicit-signed-integer-truncation
-fno-sanitize=implicit-integer-sign-change
"-fsanitize-ignorelist=${_ripwire_tree_sitter_ignorelist}")
target_compile_options(ts_swift PRIVATE "-fsanitize-ignorelist=${_ripwire_swift_ignorelist}")
target_compile_options(ts_bash PRIVATE "-fsanitize-ignorelist=${_ripwire_bash_ignorelist}")
foreach(_t IN LISTS RIPWIRE_OWNED_CXX_TARGETS)
target_compile_options(${_t} PRIVATE "-fsanitize-ignorelist=${_ripwire_libstdcxx_ignorelist}")
endforeach()
endif()

# Xcode's arm64 Darwin runtime rejects both the standalone leak sanitizer and detect_leaks=1 at startup.
# Keep the local ASan/UBSan gate executable and explicit; LeakSanitizer remains a Linux/upstream-runtime
Expand Down
Loading
Loading