fix(push): fix peeking when push name is truncated#3842
Conversation
🛡️ Jit Security Scan Results✅ No security findings were detected in this PR
Security scan by Jit
|
There was a problem hiding this comment.
Pull request overview
Fixes RESP3 Pub/Sub message loss (issue #3839) by making push-notification name peeking robust when the push frame header is only partially buffered, preventing misclassification of truncated names (e.g. "messa") that previously caused frames to be consumed/dropped.
Changes:
- Update
Reader.PeekPushNotificationNameto iteratively peek more bytes (with an upper bound) and parse the push header without returning truncated names. - Add a small RESP3 push-header parser (
parsePushNotificationName+skipDigitsThenCRLF) to distinguish incomplete vs malformed headers. - Add regression tests reproducing the bufio boundary truncation scenario both at the proto layer and via
ProcessPendingNotifications.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
push/processor_unit_test.go |
Adds an end-to-end regression test reproducing #3839 through the push processor path. |
internal/proto/reader.go |
Reworks push-notification name peeking to grow peek windows and parse headers safely. |
internal/proto/peek_push_notification_test.go |
Adds chunk-boundary tests ensuring peeking never returns a truncated push name and surfaces EOF correctly. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 1329d10. Configure here.
This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---| | [github.com/redis/go-redis/v9](https://github.com/redis/go-redis) | `v9.20.0` → `v9.20.1` |  |  | --- ### Release Notes <details> <summary>redis/go-redis (github.com/redis/go-redis/v9)</summary> ### [`v9.20.1`](https://github.com/redis/go-redis/releases/tag/v9.20.1): 9.20.1 [Compare Source](redis/go-redis@v9.20.0...v9.20.1) This is a patch release containing bug fixes only. There are no new features or breaking changes; upgrading from 9.20.0 is a drop-in replacement. #### 🚀 Highlights ##### RESP3 pub/sub message loss fixed `PeekPushNotificationName` previously inspected only the bytes already buffered by `bufio`, so when a push frame header straddled a buffer fill boundary it could return a **truncated** notification name (e.g. `"messa"` instead of `"message"`). The push processor then mis-routed the frame and `ReadReply` silently dropped it, causing intermittent RESP3 pub/sub message loss. The peek now grows its window (36 bytes → up to 4 KiB) and reads more from the connection until the header is complete, cleanly separating incomplete prefixes from corrupt frames (including overflow-safe bulk-length handling). Fixes [#​3839](redis/go-redis#3839). ([#​3842](redis/go-redis#3842)) by [@​ndyakov](https://github.com/ndyakov) #### 🐛 Bug Fixes - **RESP3 push peeking**: `PeekPushNotificationName` no longer returns a truncated notification name when a push frame header spans a buffer boundary, preventing silent RESP3 pub/sub message loss (fixes [#​3839](redis/go-redis#3839)) ([#​3842](redis/go-redis#3842)) by [@​ndyakov](https://github.com/ndyakov) - **`FT.HYBRID` vector params**: Vector data is now always sent via `PARAMS` with auto-generated param names (`__vector_param_N`, with collision avoidance) when `VectorParamName` is omitted, since Redis no longer accepts inline vector blobs; the `FTHybridOptions.Params` map is no longer mutated, so the same options struct can be reused across calls ([#​3844](redis/go-redis#3844)) by [@​ndyakov](https://github.com/ndyakov) - **`CLUSTER SHARDS` forward compatibility**: Unknown shard- and node-level attributes in the `CLUSTER SHARDS` reply are now skipped via `DiscardNext()` instead of erroring, so clients keep working when the server introduces new fields ([#​3843](redis/go-redis#3843)) by [@​madolson](https://github.com/madolson) - **PubSub double reconnect**: `PubSub.releaseConn` no longer reconnects twice when a connection is both unusable (or pending handoff) and reports a bad-connection error, avoiding a wasted connection establish-then-close cycle ([#​3833](redis/go-redis#3833)) by [@​cxljs](https://github.com/cxljs) #### 👥 Contributors We'd like to thank all the contributors who worked on this release! [@​cxljs](https://github.com/cxljs), [@​madolson](https://github.com/madolson), [@​ndyakov](https://github.com/ndyakov) *** **Full Changelog**: <redis/go-redis@v9.20.0...v9.20.1> </details> --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - Between 12:00 AM and 03:59 AM (`* 0-3 * * *`) - Automerge - Between 12:00 AM and 03:59 AM (`* 0-3 * * *`) 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yMTQuNSIsInVwZGF0ZWRJblZlciI6IjQzLjIxNC41IiwidGFyZ2V0QnJhbmNoIjoiZm9yZ2VqbyIsImxhYmVscyI6WyJkZXBlbmRlbmN5LXVwZ3JhZGUiLCJ0ZXN0L25vdC1uZWVkZWQiXX0=--> Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/13061 Reviewed-by: Mathieu Fenniak <[email protected]>

fixes #3839
Note
Medium Risk
Changes low-level RESP3 read/peek behavior on live connections (may block briefly) on a path used by pub/sub and push draining; well-covered by regression tests but affects core protocol parsing.
Overview
Fixes #3839, where RESP3 pub/sub could lose messages because
PeekPushNotificationNameonly inspected already-buffered bytes and could return a truncated notification name (e.g."messa"). The push processor then mis-routed the frame andReadReplydropped it.PeekPushNotificationNamenow grows the peek window (36 → up to 4096) and reads more from the connection until the header is complete or the read fails, instead of capping atBuffered(). Parsing is refactored intoparsePushNotificationNameandskipDigitsThenCRLF, which separate incomplete prefixes from corrupt frames and avoid returning partial names; malformed cases include empty array length, EOF mid-header, and overflow-safe bulk length handling.Tests add chunked-read boundaries, malformed/overflow cases, and a
ProcessPendingNotificationsregression that delivers 1000 RESP3messageframes through the same drain-then-ReadReplypath asPubSub.ReceiveTimeout.Reviewed by Cursor Bugbot for commit 1329d10. Bugbot is set up for automated code reviews on this repo. Configure here.