Skip to content

Fix audit findings: compile-time guards, denormal thresholds, discrete fit, decodePosterior#57

Merged
OldCrow merged 3 commits into
mainfrom
fix/uaf-guards-and-lows
Jul 4, 2026
Merged

Fix audit findings: compile-time guards, denormal thresholds, discrete fit, decodePosterior#57
OldCrow merged 3 commits into
mainfrom
fix/uaf-guards-and-lows

Conversation

@OldCrow

@OldCrow OldCrow commented Jul 4, 2026

Copy link
Copy Markdown
Owner

Summary

Addresses findings 3, 6, 7, 8, 11 from the 2026-07-04 audit, plus pre-existing tool build warnings and a benchmark CMake correctness fix. This is the libhmm half of the fix; the pylibhmm half (Finding 1 — UAF Holder pattern) follows in a separate PR against that repo.

Changes

Finding 3 — Compile-time guard against temporary observation sequences
Add deleted SeqType&& constructor overloads to BasicForwardBackwardCalculator and BasicViterbiCalculator. The base-class deletion was ineffective: a temporary bound to const SeqType& in a derived constructor reached the base as a named lvalue, bypassing the deleted overload. The new derived-class overloads close the gap and will cause the pylibhmm _core.cpp bindings to fail to compile at the exact UAF sites (Finding 1), making them self-announcing.

Finding 6 — Denormal guard inconsistency in M-step
m_step_transitions (BW trainer) used > 0.0 where m_step_pi correctly uses >= precision::ZERO. Same hazard in m_step_pi_map and m_step_transitions_map (MAP trainer). All three aligned to >= precision::ZERO.

Finding 7 — DiscreteDistribution weighted fit under-normalises
fit(data, weights) divided by sumW (total weight, including out-of-range observations), leaving the pmf summing to < 1 when any observation fell outside the symbol range. Now accumulates binnedW (weight that landed in bins) and divides by that. Removes the compensating renormalisation pass from apply_discrete_smoothing in the MAP trainer.

Finding 8 — decodePosterior silent failure on zero-probability sequences
When logP = -inf, the logAlpha + logBeta - logP scores were NaN; all comparisons were false, silently returning all-state-0. Now throws std::runtime_error when !isfinite(logProbability_).

Finding 11 — Hygiene
Add install/ to .gitignore.

Benchmark CMake — HMMLib Boost detection
The previous version incorrectly claimed HMMLib has no Boost dependency and set HMMLIB_READY ON unconditionally when hmm.hpp existed. HMMLib uses boost::shared_ptr internally. Now guards with find_package(Boost QUIET) and propagates ${Boost_INCLUDE_DIRS} through enable_hmmlib().

Tool warnings
Fix 5 instances of deprecated compound assignment on volatile-qualified types (C++20) in hotspot_breakdown, bw_hotspot, and fb_contour_sweep.

Verification

  • Clean release build: zero errors, zero warnings
  • 47/47 ctest binaries pass (932 GTest cases)

Related

  • Finding 1 (UAF in pylibhmm bindings): pylibhmm PR to follow — these guard changes will produce compile errors at the UAF sites in _core.cpp
  • Findings 4 & 5 (E-step deduplication and memory): deferred to a separate refactor/estep-dedup branch

Warp conversation

C-1 (critical): Fix cache-fill data race in DistributionBase
- Add mutable std::mutex cacheMutex_ to DistributionBase<Derived,Obs>
- Add ensureCache() CRTP helper: lock-free atomic fast path, mutex-
  serialized fill path, double-checked locking under the lock
- Add friend class DistributionBase<Derived> to all 16 scalar
  distributions so ensureCache() can call private updateCache()
- Replace every if (!isCacheValid()) updateCache() call site in scalar
  distributions with ensureCache() (~50 sites across 23 files)
- DiagonalGaussian and FullCovGaussian already had their own per-class
  mutex inside updateCache(); left unchanged
- Update distribution_base.h comment and STYLE_GUIDE.md to accurately
  reflect the now-correct thread-safety guarantee

H-1 (high): Guard Weibull MLE solver against exponent overflow
- Clamp k*log_x[i] to [-700, 700] before std::exp in both the
  Newton-Raphson loop and the final lambda computation
- Extend the break condition to !isfinite(s0) || s0 <= 0
- Add init_k fallback when k diverges to non-finite or non-positive

H-2 (high): Remove stale Boost dependency from installed CMake config
- Delete find_dependency(Boost REQUIRED) from libhmmConfig.cmake.in;
  Boost was removed in Phase 8.3 but the install config was not updated,
  breaking find_package(libhmm) on machines without Boost

M-2 (medium): Add ThreadSanitizer CI job
- New tsan job on ubuntu-latest/GCC with -fsanitize=thread -g -O1
- Would have caught C-1 directly; prevents future regressions

Co-Authored-By: Oz <oz-agent@warp.dev>
OldCrow and others added 2 commits July 4, 2026 17:44
Co-Authored-By: Oz <oz-agent@warp.dev>
Co-Authored-By: Oz <oz-agent@warp.dev>
@OldCrow OldCrow merged commit e0d79b7 into main Jul 4, 2026
7 checks passed
@OldCrow OldCrow deleted the fix/uaf-guards-and-lows branch July 4, 2026 21:46
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