Skip to content

Fix the SpotBugs findings and gate the build on SpotBugs (#116) - #134

Merged
bertysentry merged 2 commits into
mainfrom
116-spotbugs-fix-the-227-findings-null-dereference-stale-thread-writes-default-charset-exposed-internal-arrays-constructors-that-throw
Oct 8, 2026
Merged

bertysentry merged 2 commits into
mainfrom
116-spotbugs-fix-the-227-findings-null-dereference-stale-thread-writes-default-charset-exposed-internal-arrays-constructors-that-throw

Conversation

@bertysentry

Copy link
Copy Markdown
Contributor

Closes #116.

SpotBugs 4.10.4 reported 196 bugs on main (the issue counted 227; DecoderRunner and a few others were already gone). It now reports 0, and spotbugs:check runs at verify, pinned to 4.10.4.1 in <build> and <reporting>. spotbugs-annotations 4.10.4 is a provided dependency.

Real fixes

Finding Fix
NP_GUARANTEED_DEREF ProtocolDecoder.decodePayload: an empty payload threw NullPointerException in the payload constructors; it now throws IllegalArgumentException("Empty payload")
DM_DEFAULT_ENCODING (RAKP, part of #90) The user name and password are encoded in UTF-8 whatever the platform charset. The BMC key (Kg) goes to the HMAC as raw bytes instead of through new String(key).getBytes(), which corrupted any byte of 80h or above into a wrong SIK. The user name length and its 16-byte limit count encoded bytes. AuthenticationAlgorithm takes the key and password as byte[]
DM_DEFAULT_ENCODING (others) SerialOverLan overloads documented as using the platform charset now pass Charset.defaultCharset(). ManagementAccessInfo decodes ISO-8859-1, like the other FRU 8-bit ASCII fields
AT_STALE_THREAD_WRITE_OF_PRIMITIVE, IS2_INCONSISTENT_SYNC (part of #96) volatile on the fields shared by the caller, UDP and timer threads in Connection, MessageQueue and UdpMessenger. MessageListener writes its tag under its lock
JLM_JSR166_UTILCONCURRENT_MONITORENTER, USO_UNSAFE_STATIC_METHOD_SYNCHRONIZATION ConnectionManager locks a dedicated object instead of an AtomicInteger. SessionManager uses an AtomicInteger instead of a static synchronized method
ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD, SSD_DO_NOT_USE_INSTANCE_LOCK_ON_SHARED_STATIC_DATA Removed the unused static debug counter UdpMessenger.getSentPackets(). setBufferSize() now sizes the receive buffer, which was hard-coded to 512 bytes
OBL_UNSATISFIED_OBLIGATION (part of #98) PropertiesManager closes its resource stream
BC_VACUOUS_INSTANCEOF, UC_USELESS_CONDITION, MS_PKGPROTECT Removed the always-true instanceof in IpmiCommandCoder and the dead condition in ChassisInfo. CONST1/CONST2 are private

Justified suppressions

  • core/package-info.java: CT_CONSTRUCTOR_THROW and EI_EXPOSE_REP for the whole protocol core. A package-level @SuppressFBWarnings also covers subpackages, and EI_EXPOSE_REP also matches EI_EXPOSE_REP2. Constructors reject invalid arguments and guard no security-sensitive state. Response data and records are mutable holders with public setters, so defensive copies would protect no invariant and add an allocation per packet.
  • IpmiClientConfiguration: the password char[] and BMC key are shared deliberately, so the caller can wipe them.
  • Fru, Sensor: result holders. PropertiesManager.getInstance(): singleton.

SpotBugs reports a suppression that matches nothing (US_USELESS_SUPPRESSION_*), so these can't go stale silently.

For reviewers

Testing

  • mvn verify site passes: 34 tests, 0 Checkstyle, PMD and CPD clean, SpotBugs 0.
  • New Rakp1Test computes the SIK independently from IPMI 2.0 §13.31 with a high-byte Kg and a non-ASCII user name and password. It fails on the old code.
  • Live, on a GIGABYTE BMC and a Lenovo IMM: login with cipher suites 3 and 17, then Get Chassis Status over the encrypted session. A wrong password is still rejected (Illegal connection state: Rakp1Waiting, as documented).

🤖 Generated with Claude Code

SpotBugs 4.10.4 reported 196 bugs on main (DecoderRunner and a few
others were already gone); it now reports 0 and spotbugs:check runs at
verify, pinned to 4.10.4.1 like the site report.

Real fixes:
- ProtocolDecoder.decodePayload: an empty payload threw a
  NullPointerException in the payload constructors; it now throws
  IllegalArgumentException("Empty payload") (NP_GUARANTEED_DEREF)
- Credentials (part of #90): the user name and password are encoded in
  UTF-8 whatever the platform charset, and the BMC key (Kg) is passed to
  the HMAC as raw bytes instead of going through new String(key) and
  getBytes(), which corrupted any byte of 80h or above into a wrong SIK.
  The user name length and its 16-byte limit are counted in encoded
  bytes. AuthenticationAlgorithm takes the key and password as byte[]
  (DM_DEFAULT_ENCODING). Rakp1Test checks the SIK against IPMI 2.0
  section 13.31 and fails on the old code.
- volatile on the fields shared by the caller, UDP and timer threads in
  Connection, MessageQueue and UdpMessenger; MessageListener writes its
  tag under its lock (AT_STALE_THREAD_WRITE_OF_PRIMITIVE, IS2, part of
  #96)
- ConnectionManager locks a dedicated object instead of an AtomicInteger,
  SessionManager uses an AtomicInteger instead of a static synchronized
  method (JLM, USO)
- UdpMessenger: remove the unused static getSentPackets() debug counter
  (ST, SSD); setBufferSize() now sizes the receive buffer, which was
  hard-coded to 512 bytes
- SerialOverLan: the overloads documented as using the platform charset
  say so with Charset.defaultCharset(); ManagementAccessInfo decodes
  ISO-8859-1 like the other FRU 8-bit ASCII fields
- PropertiesManager closes its resource stream (OBL, part of #98)
- Remove a vacuous instanceof (IpmiCommandCoder) and a useless condition
  (ChassisInfo); CONST1/CONST2 are private (MS_PKGPROTECT)

Justified suppressions (spotbugs-annotations, provided scope):
- core/package-info.java: CT_CONSTRUCTOR_THROW and EI_EXPOSE_REP (which
  also matches EI_EXPOSE_REP2) for the whole protocol core: constructors
  validate arguments and guard no security-sensitive state, and response
  data and records are mutable holders with public setters, so defensive
  copies would protect no invariant
- IpmiClientConfiguration (credentials shared so the caller can wipe
  them), Fru and Sensor (result holders), PropertiesManager singleton

Live-verified on the GIGABYTE and Lenovo IMM BMCs: login with cipher
suites 3 and 17 and an encrypted command; a wrong password is still
rejected.

Closes #116

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 8, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-08T12:50:06.269523Z d0e7e6d New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4e6d9ddff6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/main/java/org/metricshub/ipmi/core/transport/UdpMessenger.java Outdated
…116)

- UdpMessenger.run(): back to the fixed 512-byte receive buffer of main.
  Sizing it from setBufferSize() raced with the receive thread started by
  the constructor (the first datagram used the old size); making the
  setter effective is out of the scope of the SpotBugs clean-up, and the
  volatile field still fixes the stale write SpotBugs reported
- README: the 1.2.03 upgrade summary mentions the UTF-8 credentials, the
  byte[] AuthenticationAlgorithm methods, the removed
  UdpMessenger.getSentPackets() and the private CONST1/CONST2

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@bertysentry
bertysentry merged commit 1bf72a1 into main Oct 8, 2026
4 checks passed
@bertysentry
bertysentry deleted the 116-spotbugs-fix-the-227-findings-null-dereference-stale-thread-writes-default-charset-exposed-internal-arrays-constructors-that-throw branch October 8, 2026 17:42
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.

SpotBugs: fix the 227 findings (null dereference, stale thread writes, default charset, exposed internal arrays, constructors that throw)

1 participant