Skip to content

Commit 32bca83

Browse files
committed
fix(proto): fix notification parser
1 parent 2681d6d commit 32bca83

File tree

2 files changed

+56
-13
lines changed

2 files changed

+56
-13
lines changed

internal/proto/peek_push_notification_test.go

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package proto
33
import (
44
"bytes"
55
"fmt"
6+
"math/rand"
67
"strings"
78
"testing"
89
)
@@ -215,9 +216,9 @@ func TestPeekPushNotificationName(t *testing.T) {
215216
// This is acceptable behavior for malformed input
216217
name, err := reader.PeekPushNotificationName()
217218
if err != nil {
218-
t.Logf("PeekPushNotificationName errored for corrupted data %s: %v", tc.name, err)
219+
t.Logf("PeekPushNotificationName errored for corrupted data %s: %v (DATA: %s)", tc.name, err, tc.data)
219220
} else {
220-
t.Logf("PeekPushNotificationName returned '%s' for corrupted data %s", name, tc.name)
221+
t.Logf("PeekPushNotificationName returned '%s' for corrupted data NAME: %s, DATA: %s", name, tc.name, tc.data)
221222
}
222223
})
223224
}
@@ -293,15 +294,27 @@ func TestPeekPushNotificationName(t *testing.T) {
293294
func createValidPushNotification(notificationName, data string) *bytes.Buffer {
294295
buf := &bytes.Buffer{}
295296

297+
simpleOrString := rand.Intn(2) == 0
298+
296299
if data == "" {
300+
297301
// Single element notification
298302
buf.WriteString(">1\r\n")
299-
buf.WriteString(fmt.Sprintf("$%d\r\n%s\r\n", len(notificationName), notificationName))
303+
if simpleOrString {
304+
buf.WriteString(fmt.Sprintf("+%s\r\n", notificationName))
305+
} else {
306+
buf.WriteString(fmt.Sprintf("$%d\r\n%s\r\n", len(notificationName), notificationName))
307+
}
300308
} else {
301309
// Two element notification
302310
buf.WriteString(">2\r\n")
303-
buf.WriteString(fmt.Sprintf("$%d\r\n%s\r\n", len(notificationName), notificationName))
304-
buf.WriteString(fmt.Sprintf("$%d\r\n%s\r\n", len(data), data))
311+
if simpleOrString {
312+
buf.WriteString(fmt.Sprintf("+%s\r\n", notificationName))
313+
buf.WriteString(fmt.Sprintf("+%s\r\n", data))
314+
} else {
315+
buf.WriteString(fmt.Sprintf("$%d\r\n%s\r\n", len(notificationName), notificationName))
316+
buf.WriteString(fmt.Sprintf("$%d\r\n%s\r\n", len(notificationName), notificationName))
317+
}
305318
}
306319

307320
return buf

internal/proto/reader.go

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -116,33 +116,63 @@ func (r *Reader) PeekPushNotificationName() (string, error) {
116116
if buf[0] != RespPush {
117117
return "", fmt.Errorf("redis: can't parse push notification: %q", buf)
118118
}
119-
// remove push notification type and length
120-
buf = buf[2:]
119+
120+
if len(buf) < 3 {
121+
return "", fmt.Errorf("redis: can't parse push notification: %q", buf)
122+
}
123+
124+
// remove push notification type
125+
buf = buf[1:]
126+
// remove first line - e.g. >2\r\n
121127
for i := 0; i < len(buf)-1; i++ {
122128
if buf[i] == '\r' && buf[i+1] == '\n' {
123129
buf = buf[i+2:]
124130
break
131+
} else {
132+
if buf[i] < '0' || buf[i] > '9' {
133+
return "", fmt.Errorf("redis: can't parse push notification: %q", buf)
134+
}
125135
}
126136
}
137+
if len(buf) < 2 {
138+
return "", fmt.Errorf("redis: can't parse push notification: %q", buf)
139+
}
140+
// next line should be $<length><string>\r\n or +<length><string>\r\n
127141
// should have the type of the push notification name and it's length
128-
if buf[0] != RespString {
142+
if buf[0] != RespString && buf[0] != RespStatus {
129143
return "", fmt.Errorf("redis: can't parse push notification name: %q", buf)
130144
}
131-
// skip the length of the string
132-
for i := 0; i < len(buf)-1; i++ {
133-
if buf[i] == '\r' && buf[i+1] == '\n' {
134-
buf = buf[i+2:]
135-
break
145+
typeOfName := buf[0]
146+
// remove the type of the push notification name
147+
buf = buf[1:]
148+
if typeOfName == RespString {
149+
// remove the length of the string
150+
if len(buf) < 2 {
151+
return "", fmt.Errorf("redis: can't parse push notification name: %q", buf)
152+
}
153+
for i := 0; i < len(buf)-1; i++ {
154+
if buf[i] == '\r' && buf[i+1] == '\n' {
155+
buf = buf[i+2:]
156+
break
157+
} else {
158+
if buf[i] < '0' || buf[i] > '9' {
159+
return "", fmt.Errorf("redis: can't parse push notification name: %q", buf)
160+
}
161+
}
136162
}
137163
}
138164

165+
if len(buf) < 2 {
166+
return "", fmt.Errorf("redis: can't parse push notification name: %q", buf)
167+
}
139168
// keep only the notification name
140169
for i := 0; i < len(buf)-1; i++ {
141170
if buf[i] == '\r' && buf[i+1] == '\n' {
142171
buf = buf[:i]
143172
break
144173
}
145174
}
175+
146176
return util.BytesToString(buf), nil
147177
}
148178

0 commit comments

Comments
 (0)