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>
32 lines
1.7 KiB
Bash
Executable File
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"
|