fix: v0.4.0 — RELAY ecosystem audit fixes - #12
Merged
Conversation
Spec-conformance fixes:
- Add lin::Errc::invalid_frame error category, distinct from
ErrPayloadTooLarge, for out-of-range LIN frame IDs per spec §5.3
("ErrInvalidFrame and ErrPayloadTooLarge are distinct ... ValidateFrame
MUST NOT return ErrPayloadTooLarge"). Applied to virtual::Bus::do_publish()/
send_header(), master::Node::set_schedule()/run(), and slave::Node::
set_response() (same mis-mapping, found during the fix).
- convert now writes the correct "ErrInvalidFrame" sentinel name to stderr
instead of the nonexistent "ErrInvalidInput" (spec §11.2).
- capabilities now reports an actual transport backend ("virtual") instead
of the protocol name ("LIN") in the transports array (spec §12.2).
- version/capabilities/status "tool" field lowercased to "cpp-lin" to match
the CLI-binary-name convention used by peers (go-can, cpp-rcp) (spec §13.2).
- version/status now support --format text|json, exiting 2 on an
unrecognized format or any other unrecognized argument (spec §11.1).
- Add lin::mock (aliasing lin::virt::Bus), the RELAY spec §13.7.1 canonical
"mock" module, plus "mock" in the capabilities features list.
Bug fixes:
- Fix a use-after-free: Adapt()'s subscription thread captured the adapter's
`this` by raw pointer and dereferenced it via ++seq_ for the thread's
lifetime, with nothing joining the (detached) thread on adapter
destruction. The Seq counter is now owned by a shared_ptr captured into
the thread, which also brings it in line with spec §10.5.2 point 7 (the
Seq counter belongs to the subscription, not the adapter).
- version/capabilities/status self-reported version is now driven by
PROJECT_VERSION via a generated header (cli/version.hpp.in) instead of a
second hard-coded "0.1.0" literal that had drifted three releases behind
the actual v0.3.0 tag.
Also fixes the same stale-0.1.0 pattern in .fusa.json and the two
`cpfusa init --project-version` invocations in ci.yml (--force would have
overwritten .fusa.json with 0.1.0 on every CI run), and brings ROADMAP.md
in line with what v0.1.0-v0.3.0 actually shipped (it still described
unshipped v0.2.0/v0.3.0 plans for content that shipped differently).
Closes #4
Closes #5
Closes #6
Closes #7
Closes #8
Closes #9
Closes #10
Closes #11
Signed-off-by: Matt Jones <47545907+SoundMatt@users.noreply.github.com>
The MSVC/Windows CI leg failed: ctest discovers test names via one process invocation and filters by name in another, and the "§" character in the new mock-features TEST_CASE name round-tripped differently across that boundary on the Windows runner's console codepage, so the filter matched zero tests and ctest treated it as a failure. No other TEST_CASE name in this repo uses non-ASCII characters; drop the "§" from this one to match. Signed-off-by: Matt Jones <47545907+SoundMatt@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes all 8 open issues filed by the RELAY ecosystem audit (2026-07-27).
Issues fixed
Spec-conformance:
version/capabilities/statusnow reportPROJECT_VERSIONvia a generated header (cli/version.hpp.in) instead of a second hard-coded literal, andCMakeLists.txt'sproject(... VERSION ...)is bumped to0.4.0for this release. Also fixes the same stale-0.1.0pattern in.fusa.jsonand the twocpfusa init --project-versioninvocations inci.yml(which run--force, so they'd have silently overwritten.fusa.jsonback to0.1.0on every CI run).capabilitieslisted the protocol name ("LIN") as a transport instead of an actual transport backend. Now reports"transports":["virtual"].convertwrote the nonexistent sentinel nameErrInvalidInputto stderr instead ofErrInvalidFrame(the actually-thrown type). Fixed to match spec §11.2/§5."tool"field used mixed-case"cpp-LIN"instead of the lowercase CLI-binary-name convention (cpp-lin, matchinggo-can/cpp-rcp).mockper spec §13.7.1. Addedlin::mock(include/lin/mock/mock.hpp) aliasing the existinglin::virt::Bus, plus"mock"in the capabilitiesfeatureslist.version/statussilently ignored--formatand never validated arguments. Both now support--format text|json, with a human-readable text rendering, and exit2on an unrecognized format value or any other unrecognized argument.Bug fixes:
Adapt()'s subscription thread captured the adapter'sthisby raw pointer and dereferenced it (++seq_) for the thread's lifetime; nothing joined the detached thread on adapter destruction, so dropping the adapter (while the bus stayed open) was a use-after-free on the next inbound frame. Fixed by moving the seq counter into ashared_ptr<atomic<uint64_t>>captured into the thread instead ofthis— the thread now never touches the adapter, and as a side effect this also brings seq-counter ownership in line with spec §10.5.2 point 7 (owned per-subscription, not shared acrossAdapt()calls).ErrPayloadTooLargeinstead of a structural-violation error, at 5 call sites (spec §5.3: "ErrInvalidFrameandErrPayloadTooLargeare distinct ...ValidateFrameMUST NOT returnErrPayloadTooLarge"). Addedlin::Errc::invalid_frame(a LIN-specificstd::error_category, not mapped to anyrelay::Errc, matching the CANErrInvalidFramepattern in spec §5.4) and applied it tovirtual::Bus::do_publish()/send_header(),master::Node::set_schedule()/run(), and — found during the fix, same mis-mapping, not in the original issue evidence —slave::Node::set_response().LinAdapter::send()(therelay::INodeinterface, constrained to the four documented relay sentinels per §10.1) now delegates to the existingfrom_message()instead of duplicating ID-parsing logic, but still approximates withErrPayloadTooLargeas the issue itself notes is unavoidable there.Docs
ROADMAP.mdwas rewritten to reflect whatv0.1.0–v0.3.0actually shipped (it still described unshippedv0.2.0/v0.3.0plans — "Enhanced Bus Features"/"Diagnostics" — for content that in reality shipped as the Full Safety & Cyber Pack and RELAY v1.11 conformance releases). Future unshipped plans renumbered to start atv0.5.0so they don't collide with real tags again.README.mdarchitecture section and features list updated for the newmockmodule.Issues closed as already-resolved
None — all 8 open issues were live gaps in the current code, verified against the actual current source before fixing.
Issues left open
None.
Test plan
cmake -B build -DCMAKE_BUILD_TYPE=Release -DRELAY_BUILD_CLI=ON -G Ninja && cmake --build build --parallel— clean buildctest --test-dir build -j1— 171/171 tests pass (addedtests/test_mock.cpp, plus new cases intest_lin.cpp/test_cli.cppfor the sentinel and--formatfixes)-Werrorunder-Wall -Wextra -Wpedantic -Wshadow ...(this repo's own flag set) — clean, no warningsversion/version --format text/version --format bogus/status/status --format text/capabilities/convert(invalid frame) against the built CLI binary to confirm exit codes and output match the fixes