Files
tai/taicpp/tools/san-whatsapp.sh
T
retoorandClaude Opus 4.8 79ae6f27da cpp-safety: safe-C++ playbook, fix a second UB, and a sanitizer net
Response to incident WA-2026-10-27 (the std::vector max_size() crash). Deep
research archived under research/safe-cpp-practices (8 Tier 1, 37 Tier 2, 2
conclusions) on production-safe C++ that keeps development speed: OpenSSF
compiler hardening, the C++ Core Guidelines bounds profile, integer-overflow
practice, libFuzzer/sanitizer CI, the sanitizer overhead ladder, clang-tidy
ratchets.

The research prescribed an ASan+UBSan+_GLIBCXX_ASSERTIONS build of the parsers.
Standing it up immediately caught a second, independent undefined-behavior bug
that two manual reviews had missed: a protobuf varint loop that shifted by up
to 70 bits (shift >= 64 is UB) on malformed input. Fixed and guarded by a
deterministic test and the sanitizer net.

- src/whatsapp/wa_proto.cpp: guard the wire-0 varint shift (the UB).
- tests/whatsapp_test.cpp: add an overlong-varint hostile case.
- tools/san-whatsapp.sh: the standing sanitizer net for detz::wa parsers.
- WaClient frame capture: a frame that fails to decode/dispatch has its exact
  bytes recorded to <home>/whatsapp/last-error.log (bounded), so the still
  unreproduced live <iq> failure becomes a one-paste deterministic fix. Wired
  from the wizard and the whatsapp_send tool.
- docs/cpp-safety.md: the project-wide playbook and design decisions (four
  layers: overflow-safe checked-reader parsing, cheap release hardening, the
  sanitizer test net, capture). docs/whatsapp.md section 13.6 records the
  follow-up and the honest open item. AGENTS.md makes it a standing rule;
  cap.md and mcp.md inherit it for their wire parsers.

Verified: build, whatsapp_test (incl. hostile+fuzz), make lint, and
tools/san-whatsapp.sh all green; research audit PASS.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-10-27 19:03:32 +01:00

32 lines
1.7 KiB
Bash
Executable File

#!/usr/bin/env bash
# san-whatsapp.sh: build and run the WhatsApp wire parsers under AddressSanitizer
# + UndefinedBehaviorSanitizer + _GLIBCXX_ASSERTIONS. This is the standing net
# for detz::wa's parsing layer: a malformed frame that overflows a length check,
# over-reads a buffer, or over-allocates a vector aborts here at the exact line,
# instead of slipping past a bounds check in a release build. Run it in CI and
# before any change to a parser (WaBinary, WaProto, WaNoise, WaSignal). See
# docs/cpp-safety.md.
#
# The vendored ed25519 ref10 (third_party/ed25519) is built WITHOUT UBSan on
# purpose: it uses intentional, portable signed-shift idioms that UBSan flags
# but that are not bugs. Everything we wrote is fully sanitized.
set -euo pipefail
cd "$(dirname "$0")/.."
OUT=$(mktemp -d)
trap 'rm -rf "$OUT"' EXIT
SAN="-fsanitize=address,undefined -fno-sanitize-recover=all -D_GLIBCXX_ASSERTIONS -g -O1 -std=c++23 -Wall -Wextra"
INC="-Isrc/whatsapp -Isrc/llm -Ithird_party/ed25519"
# only the parser TUs the hostile/golden test exercises
for f in wa_crypto wa_binary wa_proto wa_noise wa_signal wa_device; do
g++ $SAN $INC -c "src/whatsapp/$f.cpp" -o "$OUT/$f.o"
done
g++ $SAN $INC -c src/llm/json.cpp -o "$OUT/json.o"
# ref10 C without UBSan (intentional portable shift idioms), still ASan for memory
for f in third_party/ed25519/*.c; do
cc -fsanitize=address -D_GLIBCXX_ASSERTIONS -g -O2 -Ithird_party/ed25519 -c "$f" -o "$OUT/$(basename "$f" .c).o"
done
g++ $SAN $INC tests/whatsapp_test.cpp "$OUT"/*.o -lssl -lcrypto -lz -o "$OUT/whatsapp_test_san"
echo "running whatsapp_test under ASan+UBSan+_GLIBCXX_ASSERTIONS ..."
"$OUT/whatsapp_test_san" tests/whatsapp_data
echo "san-whatsapp: OK"