Skip to content

Fix grant_immediate overwriting active read grants#78

Merged
MathiasKoch merged 1 commit into
masterfrom
fix/grant-immediate-read-protection
Feb 25, 2026
Merged

Fix grant_immediate overwriting active read grants#78
MathiasKoch merged 1 commit into
masterfrom
fix/grant-immediate-read-protection

Conversation

@MathiasKoch

Copy link
Copy Markdown
Member

Summary

  • grant_immediate() forcibly evicts front messages from the ring buffer without checking read_in_progress. When a subscriber holds a FrameGrantR (raw pointer into the buffer), the evicted region gets overwritten by the new message, causing data corruption. This manifests as intermittent hash mismatches in rustot's OTA integration test.
  • Now checks read_in_progress on the front message before evicting. Returns Err(InsufficientSize) when the front is held by a reader. The caller (stack.rs:238-254) already handles this error by discarding the incoming publish and skipping PUBACK — the broker redelivers for QoS 1.
  • Fixes off-by-one in free_space() and grant_with_context(): when back_end == front.start (buffer wraps to exactly touch the front), this was incorrectly treated as non-inverted, returning a wildly inflated free space value.

Test plan

  • New regression test: grant_immediate_refuses_to_evict_read_in_progress
  • All 34 existing mqttrust unit tests pass
  • rustot OTA integration test passes with 4096-byte buffer (previously failed intermittently with hash mismatches)

grant_immediate() forcibly evicts front messages from the ring buffer
without checking read_in_progress. When a subscriber holds a FrameGrantR
(raw pointer into the buffer), the evicted region gets overwritten by
the new message, causing data corruption.

Changes:
- grant_immediate: check read_in_progress on front message before
  evicting; return Err(InsufficientSize) when the front is held by a
  reader. The caller (stack.rs) already handles this by discarding
  the incoming publish and skipping PUBACK, so the broker redelivers.
- free_space / grant_with_context: fix off-by-one in inverted check
  (< to <=). When back_end == front.start the buffer is full, not
  empty.
- Add regression test: grant_immediate_refuses_to_evict_read_in_progress
@MathiasKoch
MathiasKoch merged commit cc55012 into master Feb 25, 2026
6 checks passed
@MathiasKoch
MathiasKoch deleted the fix/grant-immediate-read-protection branch February 25, 2026 09:38
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