You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
lin::ldf::DB::decode() has an unclamped bit-shift (UB, aborts under UBSan) for LDF signals with bit_width > 64 #18
Signal::bit_width is a plain int (include/lin/ldf/parser.hpp:46), and parse_signals() (src/ldf/parser.cpp:195) accepts any integer bit_width parsed from LDF text with no upper-bound check.
decode() (src/ldf/parser.cpp:51-74) then loops for (int i = 0; i < bit_width; ++i) ... val |= (uint64_t)1 << i with no clamp on i (line 69). If bit_width > 64, this is a shift-by->=64 on a 64-bit value, which is undefined behavior in C++.
Reproduced directly: a standalone UBSan-compiled repro confirms 1ULL << 64 triggers shift exponent 64 is too large for 64-bit type and SIGABRTs — matching the repo's own fusa-asil-b / UBSan CI job, which runs with halt_on_error=1 and would abort on this input.
Reaching the actual UB additionally requires decode()'s data argument to exceed 8 bytes (otherwise the loop's own byte_idx >= data.size() break fires first) — but decode() takes an arbitrary, unbounded std::vector<uint8_t>& with no internal length check, so this precondition is realistic via the public API, not just a theoretical corner case.
Evidence
include/lin/ldf/parser.hpp:46 — Signal::bit_width is unconstrained int
src/ldf/parser.cpp:195 — parse_signals(), no bound check on parsed bit_width
src/ldf/parser.cpp:51-74 — decode(), unclamped shift at line 69
tests/test_ldf.cpp:113 — the only bit_width assertion in the suite (bit_width == 8); no coverage of out-of-range values
Why it matters
A malformed or crafted .ldf file (an LDF is typically an external, semi-trusted config/description file supplied alongside a project) can crash any process that parses it and calls decode() on a >8-byte buffer. This is a straightforward DoS via untrusted input, and it also means the safety-relevant UBSan CI gate can be defeated/triggered by config content rather than code changes.
Suggested fix direction
Reject bit_width values outside [1, 64] (or the LIN-spec-appropriate range) in parse_signals() at LDF-parse time, and/or clamp the loop bound in decode() to std::min(bit_width, 64) as defense in depth.
Activity