The AST sandbox whitelisted ** and << with no magnitude bound, so a hostile
profile formula (9**9**9, 1<<10**9) computed a multi-hundred-MB integer on the
scheduler thread -> CPU pin + OOM. The scheduler except clause never catches a
runaway/OOM (not a raised exception), and a derived PID with empty deps fires
every tick on connect.
- _apply() guards each BinOp: shift amount <= 256, exponent <= 64, and any int
result bit_length > 512 raises FormulaError (caught by the scheduler -> sample
dropped, thread survives).
- compile-time caps: expr length <= 500, AST depth <= 60; parse also catches
RecursionError.
- test_formula_dos_bounded: giant-int payloads rejected in <0.5s; legit bit ops
and scaling still work.
Closes#6
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016yT89n4zR4qbrySoSiEyZs
Vehicle data is now DATA, not code. PIDs/scaling/DTCs/presets live in
profiles/*.json; the app loads them at runtime, so it works across vehicles
and others can contribute profiles (open source).
Core:
- obdcore/formula.py: safe AST evaluator for scaling formulas (A/B/... byte
vars, Torque/FORScan convention). Only arithmetic/bitwise + min/max/abs/
round/int/float; names/attrs/arbitrary calls rejected at load -> a community
profile CANNOT execute code.
- obdcore/profile.py: load/save/list profiles; compiles each formula into a
decode callable. registry.py now profile-backed (PidRegistry/DtcDatabase
take a Profile); hardcoded Ford table removed.
- store.py: clear()/snapshot()/export_csv() for capture management.
Profiles:
- profiles/ford-6.0-powerstroke.json (27 PIDs, verified formulas, DTCs)
- profiles/generic-obd2.json (standard SAE Mode-01 base, any vehicle)
- profiles/README.md (schema + formula language + contributing)
GUI:
- Menu bar: File (new/record/export/replay capture, quit), Profile (switch/
load/import/reload/edit-JSON/export, live profile list), View (Graph/Table
views, gauges P2, toggle PID dock, normalize, light/dark theme), Help
(about/confidence legend/profile info).
- PID browser + presets rebuild on profile switch; added Table view; raw-JSON
profile editor dialog (validates schema+formulas before saving).
Tests: profiles load+compile, formula sandbox rejects hostile input, decoders
still match real truck bytes, crank/derived/dead-PID/replay -- all pass.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016yT89n4zR4qbrySoSiEyZs