Skip to content

5.0 port: Fix IndexOutOfBoundsException in StompSubframeDecoder on heartbeat (#16539)#16552

Merged
chrisvest merged 1 commit into
netty:5.0from
chrisvest:5.0-stomp
Mar 27, 2026
Merged

5.0 port: Fix IndexOutOfBoundsException in StompSubframeDecoder on heartbeat (#16539)#16552
chrisvest merged 1 commit into
netty:5.0from
chrisvest:5.0-stomp

Conversation

@chrisvest

Copy link
Copy Markdown
Member

5.0 port of #16539

The code is already correct in the 5.0 branch, but it can't hurt to bring over the tests.


Problem

StompSubframeDecoder.skipControlCharacters() reads bytes in an infinite loop without checking if the buffer has readable bytes remaining. When a STOMP heartbeat frame (just a LF byte) arrives, the method consumes the control character and then attempts to read beyond the buffer, causing an IndexOutOfBoundsException.

Root Cause

The skipControlCharacters method has an unconditional buffer.readByte() call inside a for (;;) loop with no buffer.isReadable() guard. When the buffer contains only control characters (heartbeat), all bytes are consumed and the next readByte() fails.

Fix

Add a buffer.isReadable() check before each readByte() call. When the buffer is exhausted (heartbeat-only data), the method returns gracefully and the decoder waits for more data.

Tests Added

  • testHeartbeatOnlyDoesNotThrowException - Single LF heartbeat byte does not cause exception
  • testMultipleHeartbeatsDoNotThrowException - Multiple consecutive LF bytes handled correctly
  • testCarriageReturnLineFeedHeartbeat - CR+LF heartbeat handled correctly
  • testHeartbeatFollowedByFrame - Heartbeat before a real STOMP frame, frame decodes correctly
  • testHeartbeatBetweenFrames - Heartbeat between two frames, both decode correctly
  • testHeartbeatSentSeparatelyThenFrame - Heartbeat in separate write, then frame in second write

Impact

Minimal - only adds a single isReadable() guard. No behavioral change for normal STOMP frames.

Fixes #10678

(cherry picked from commit 6f6ac4b)

…etty#16539)

## Problem

`StompSubframeDecoder.skipControlCharacters()` reads bytes in an
infinite loop without checking if the buffer has readable bytes
remaining. When a STOMP heartbeat frame (just a LF byte) arrives, the
method consumes the control character and then attempts to read beyond
the buffer, causing an IndexOutOfBoundsException.

## Root Cause

The `skipControlCharacters` method has an unconditional
`buffer.readByte()` call inside a `for (;;)` loop with no
`buffer.isReadable()` guard. When the buffer contains only control
characters (heartbeat), all bytes are consumed and the next `readByte()`
fails.

## Fix

Add a `buffer.isReadable()` check before each `readByte()` call. When
the buffer is exhausted (heartbeat-only data), the method returns
gracefully and the decoder waits for more data.

## Tests Added

- `testHeartbeatOnlyDoesNotThrowException` - Single LF heartbeat byte
does not cause exception
- `testMultipleHeartbeatsDoNotThrowException` - Multiple consecutive LF
bytes handled correctly
- `testCarriageReturnLineFeedHeartbeat` - CR+LF heartbeat handled
correctly
- `testHeartbeatFollowedByFrame` - Heartbeat before a real STOMP frame,
frame decodes correctly
- `testHeartbeatBetweenFrames` - Heartbeat between two frames, both
decode correctly
- `testHeartbeatSentSeparatelyThenFrame` - Heartbeat in separate write,
then frame in second write

## Impact

Minimal - only adds a single `isReadable()` guard. No behavioral change
for normal STOMP frames.

Fixes netty#10678

(cherry picked from commit 6f6ac4b)
@chrisvest chrisvest added this to the 5.0.0.Final milestone Mar 25, 2026
@chrisvest chrisvest merged commit 28db032 into netty:5.0 Mar 27, 2026
18 of 23 checks passed
@chrisvest chrisvest deleted the 5.0-stomp branch March 27, 2026 00:21
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.

2 participants