Skip to content

Correctness and CI hardening: BAR parse, cap sizing, check exit code, --from-json validation, barmodel panics, lint in CI - #96

Closed
NetVar1337 wants to merge 6 commits into
sercanarga:mainfrom
NetVar1337:fix/correctness-and-ci-hardening
Closed

NetVar1337 wants to merge 6 commits into
sercanarga:mainfrom
NetVar1337:fix/correctness-and-ci-hardening

Conversation

@NetVar1337

Copy link
Copy Markdown
Contributor

Six focused correctness/hardening fixes, each with a test where it adds behavior. Full go test ./..., go vet, and gofmt are clean.

Fixes

  • fix(pci): treat malformed sysfs BAR lines as disabled — ParseBARsFromSysfsResource discarded the retry Sscanf result and computed Size = end - start + 1 with no end >= start guard, so a partially parsed or inverted resource line produced a uint64 underflow (~1.8e19-byte BAR) that flowed into aperture/clamp math. Now rejected as a disabled BAR.
  • fix(scrub): size capabilities by their parsed chain extent — capSizeAt recomputed cap size from a static map defaulting to 8 bytes, so zeroVendorRegisters zeroed bytes belonging to unrecognized caps larger than 8B (SATA idx/data, HyperTransport, AF…) and findFreeCapSpace could overlap-inject. New capSize uses the exact inter-cap extent from cap.Data for linked caps, keeping the conservative floor for the terminal cap (whose Data runs to end-of-space, so it must not claim the trailing gap).
  • fix(check): exit non-zero when donor checks find issues — check always returned nil, so scripted check && build pipelines could never gate on a bad donor. It now returns an error (with the cobra usage dump silenced) when issues are found.
  • fix(donor): validate untrusted config_space_size on --from-json — device_context.json is an untrusted boundary; UnmarshalJSON copied config_space_size straight into ConfigSpace.Size, and an out-of-range value made Bytes() / size-bounded consumers read past the fixed 4096-byte array. The declared size must now match the hex-word count and fit the backing array; NewConfigSpaceFromBytes also clamps Size.
  • fix(barmodel): return error instead of panicking on invalid model — validateModel panicked on the normal build path, aborting the whole CLI on a misaligned/duplicate offset or overlapping mask. It now returns an error: BuildBARModels propagates it, and BuildBARModel / SynthesizeBARModel log and return nil (callers already handle nil) so a bad spec table or hostile donor-derived probe degrades gracefully. Signatures unchanged.
  • ci: run golangci-lint and migrate config to v2 — the configured linters never ran in CI, so PRs merged unlinted. Adds a lint job and migrates .golangci.yml to the v2 schema required by the go 1.26 toolchain (gosimple is now folded into staticcheck); max-issues limits set to 0 so findings are no longer silently capped.

Tests

  • TestParseBARsFromSysfsResourceMalformed — inverted / truncated / unparsable resource lines are disabled.
  • TestCapSizePrefersChainExtentButFloorsTerminalCap — inner cap reports its full 16-byte extent; terminal cap falls back to the static floor.
  • TestDeviceContext_RejectsBadConfigSpaceSize — mismatched / negative / oversized config_space_size are rejected; a consistent in-range size round-trips.

Notes

  • The new lint job pins the action by tag with a TODO to convert to a commit SHA (matching the other actions in ci.yml) once a golangci-lint v2 release is chosen. First run may surface pre-existing findings the old 50/5 caps hid; no new linters (gosec etc.) were added here to avoid a red gate on day one.

The retry Sscanf discarded its result and Size = end - start + 1 ran with no
end >= start guard, so a partially parsed or inverted resource line produced a
uint64 underflow (~1.8e19-byte BAR) that flowed into aperture/clamp math.
Reject lines that don't parse to three fields or have end < start.
capSizeAt recomputed cap size from a static map defaulting to 8 bytes, so
zeroVendorRegisters zeroed bytes belonging to unrecognized caps >8B and
findFreeCapSpace could overlap-inject. capSize now uses the exact inter-cap
extent recorded in cap.Data for linked caps, keeping the conservative floor
for the terminal cap (whose Data runs to end-of-space).
run() always returned nil, so scripted 'check && build' pipelines could never
gate on a bad donor. Return an error (and silence the cobra usage dump) when
issues are found.
device_context.json is an untrusted boundary. UnmarshalJSON copied
config_space_size straight into ConfigSpace.Size; an out-of-range value made
Bytes() and Size-bounded consumers read past the fixed 4096-byte array. Require
the declared size to match the hex-word count and fit the backing array, and
clamp Size in NewConfigSpaceFromBytes.
validateModel panicked on the normal build path, aborting the whole CLI on a
misaligned/duplicate offset or overlapping mask. It now returns an error:
BuildBARModels propagates it, and BuildBARModel/SynthesizeBARModel log and
return nil (callers already handle nil) so a bad spec table or hostile
donor-derived probe degrades gracefully.
The configured linters never ran in CI, so PRs merged unlinted. Add a lint job
and migrate .golangci.yml to the v2 schema required by the go 1.26 toolchain
(gosimple is now folded into staticcheck); set max-issues limits to 0 so
findings are no longer silently capped.
@NetVar1337 NetVar1337 closed this by deleting the head repository Oct 6, 2026
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