Skip to content

Add ASan/UBSan CI job and a libFuzzer smoke test for decode - #36

Merged
gistrec merged 2 commits into
masterfrom
ci/asan-ubsan-fuzz
Jul 2, 2026
Merged

gistrec merged 2 commits into
masterfrom
ci/asan-ubsan-fuzz

Conversation

@gistrec

@gistrec gistrec commented Jul 2, 2026

Copy link
Copy Markdown
Owner

What

Two new Ubuntu/clang jobs in ci.yml:

  • sanitizers — the full test suite under ASan + UBSan (-fno-sanitize-recover=all: any UB report fails the job);
  • fuzz-smoke — a 60-second libFuzzer run over geo::decode, the only parser of untrusted input in the library.

The harness lives in tests/fuzz/ behind a new opt-in GEO_UTILS_CPP_BUILD_FUZZERS option (Clang only). Besides memory safety it checks a round-trip property: re-encoding decoded points always preserves the count, and reproduces the points exactly when all of them are plausible coordinates (is_valid) — malformed input can decode to coordinate jumps beyond the format's 32-bit delta range, which legitimately don't survive re-encoding.

Found (and fixed) by the harness before it even landed

The first commit fixes real UB the fuzzer immediately exposes: the per-point delta accumulator in decode is an int32, and each decoded delta can reach ±2³⁰ — a 24-byte ASCII string (}~~~~~@?}~~~~~@?}~~~~~@?) drives the sum past INT32_MAX:

encoding.hpp:105: runtime error: signed integer overflow: 2147483646 + 1073741823

The fix accumulates through uint32 with well-defined wrap-around — bit-for-bit the Java original's int semantics, so well-formed input decodes identically; malformed input keeps yielding unspecified (but now UB-free) coordinates, exactly as decode's docs promise. Regression test included.

Verification

  • 54/54 unit tests green, plain and under ASan/UBSan (macOS, AppleClang);
  • the harness compiled against the pre-fix header aborts on the adversarial seed; against the fixed header it runs clean on that seed and the reference polyline;
  • the real libFuzzer run happens in the new fuzz-smoke job on this PR (macOS Command Line Tools ship no libFuzzer runtime — noted in tests/fuzz/CMakeLists.txt).

gistrec added 2 commits July 2, 2026 07:13
The per-point delta accumulator is an int32, and each decoded delta can
be as large as +/-2^30 - so three adversarial max-size deltas (a 24-byte
ASCII string) push the sum past INT32_MAX, which is signed-overflow UB.
Found by the new fuzz harness before it even landed; UBSan reports
'signed integer overflow: 2147483646 + 1073741823' at the += line.

Accumulate through uint32 with well-defined wrap-around instead. This
matches the Java original's int semantics bit for bit, so well-formed
input decodes identically; malformed input keeps yielding unspecified
(but now UB-free) coordinates, as documented. Regression test decodes
exactly that adversarial input.
Two new Ubuntu/clang jobs in ci.yml:
- sanitizers: the full test suite built with
  -fsanitize=address,undefined -fno-sanitize-recover=all, so any UB
  report fails the job;
- fuzz-smoke: a 60-second libFuzzer run over geo::decode, the only
  parser of untrusted input in the library.

The fuzz harness (tests/fuzz/, opt-in via GEO_UTILS_CPP_BUILD_FUZZERS,
Clang only) checks memory safety plus a round-trip property: re-encoding
decoded points always preserves the count, and reproduces the points
exactly when they are plausible coordinates (malformed input can decode
to jumps beyond the format's 32-bit delta range, which legitimately
don't survive re-encoding - hence the is_valid gate).
@gistrec
gistrec merged commit 3928a6f into master Jul 2, 2026
12 checks passed
gistrec added a commit that referenced this pull request Jul 2, 2026
Bump the version in CMakeLists.txt, the build2 manifest,
include/geo/version.hpp, README, getting-started, and the api.md
version-macro examples; add the v1.2.0 changelog section covering
PRs #36-#40.
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