Skip to content

Commit 1329d10

Browse files
committed
protect agains potential panic
1 parent cb9ccaa commit 1329d10

2 files changed

Lines changed: 31 additions & 3 deletions

File tree

internal/proto/peek_push_notification_test.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ import (
44
"bytes"
55
"fmt"
66
"io"
7+
"math"
78
"math/rand"
9+
"strconv"
810
"strings"
911
"testing"
1012
)
@@ -758,3 +760,25 @@ func TestPeekPushNotificationName_EmptyArrayLength(t *testing.T) {
758760
t.Fatalf("PeekPushNotificationName: error should mention empty array length, got %v", err)
759761
}
760762
}
763+
764+
// TestPeekPushNotificationName_OverflowingNameLength asserts that a frame
765+
// advertising a name length near math.MaxInt does not panic. Computing
766+
// next+nameLen would overflow int and wrap negative, slipping past a naive
767+
// "end > len(buf)" guard and panicking the backing slice; the parser must
768+
// instead treat it as incomplete and surface an error without crashing.
769+
func TestPeekPushNotificationName_OverflowingNameLength(t *testing.T) {
770+
data := []byte(">1\r\n$" + strconv.Itoa(math.MaxInt) + "\r\n")
771+
rd := NewReader(bytes.NewReader(data))
772+
773+
if _, err := rd.PeekReplyType(); err != nil {
774+
t.Fatalf("PeekReplyType: %v", err)
775+
}
776+
777+
name, err := rd.PeekPushNotificationName()
778+
if err == nil {
779+
t.Fatalf("PeekPushNotificationName: want error for overflowing name length, got name=%q", name)
780+
}
781+
if name != "" {
782+
t.Fatalf("PeekPushNotificationName: want empty name on error, got %q", name)
783+
}
784+
}

internal/proto/reader.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -219,11 +219,15 @@ func parsePushNotificationName(buf []byte) (string, bool, error) {
219219
if nameLen < 0 {
220220
return "", false, fmt.Errorf("redis: negative push notification name length: %d", nameLen)
221221
}
222-
end := next + nameLen
223-
if end > len(buf) {
222+
// Compare against the remaining bytes instead of computing
223+
// next+nameLen: a hugely advertised length on malformed input could
224+
// overflow int, wrap negative, slip past an "end > len(buf)" guard and
225+
// panic the slice below. next <= len(buf) here, so the subtraction is
226+
// safe.
227+
if nameLen > len(buf)-next {
224228
return "", false, nil
225229
}
226-
return util.BytesToString(buf[next:end]), true, nil
230+
return util.BytesToString(buf[next : next+nameLen]), true, nil
227231
}
228232

229233
// RespStatus: scan for the terminating CRLF.

0 commit comments

Comments
 (0)