mirror of
https://github.com/redis/go-redis.git
synced 2025-07-19 11:43:14 +03:00
fix(proto): fix notification parser
This commit is contained in:
@ -3,6 +3,7 @@ package proto
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
@ -215,9 +216,9 @@ func TestPeekPushNotificationName(t *testing.T) {
|
|||||||
// This is acceptable behavior for malformed input
|
// This is acceptable behavior for malformed input
|
||||||
name, err := reader.PeekPushNotificationName()
|
name, err := reader.PeekPushNotificationName()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Logf("PeekPushNotificationName errored for corrupted data %s: %v", tc.name, err)
|
t.Logf("PeekPushNotificationName errored for corrupted data %s: %v (DATA: %s)", tc.name, err, tc.data)
|
||||||
} else {
|
} else {
|
||||||
t.Logf("PeekPushNotificationName returned '%s' for corrupted data %s", name, tc.name)
|
t.Logf("PeekPushNotificationName returned '%s' for corrupted data NAME: %s, DATA: %s", name, tc.name, tc.data)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -293,15 +294,27 @@ func TestPeekPushNotificationName(t *testing.T) {
|
|||||||
func createValidPushNotification(notificationName, data string) *bytes.Buffer {
|
func createValidPushNotification(notificationName, data string) *bytes.Buffer {
|
||||||
buf := &bytes.Buffer{}
|
buf := &bytes.Buffer{}
|
||||||
|
|
||||||
|
simpleOrString := rand.Intn(2) == 0
|
||||||
|
|
||||||
if data == "" {
|
if data == "" {
|
||||||
|
|
||||||
// Single element notification
|
// Single element notification
|
||||||
buf.WriteString(">1\r\n")
|
buf.WriteString(">1\r\n")
|
||||||
buf.WriteString(fmt.Sprintf("$%d\r\n%s\r\n", len(notificationName), notificationName))
|
if simpleOrString {
|
||||||
|
buf.WriteString(fmt.Sprintf("+%s\r\n", notificationName))
|
||||||
|
} else {
|
||||||
|
buf.WriteString(fmt.Sprintf("$%d\r\n%s\r\n", len(notificationName), notificationName))
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Two element notification
|
// Two element notification
|
||||||
buf.WriteString(">2\r\n")
|
buf.WriteString(">2\r\n")
|
||||||
buf.WriteString(fmt.Sprintf("$%d\r\n%s\r\n", len(notificationName), notificationName))
|
if simpleOrString {
|
||||||
buf.WriteString(fmt.Sprintf("$%d\r\n%s\r\n", len(data), data))
|
buf.WriteString(fmt.Sprintf("+%s\r\n", notificationName))
|
||||||
|
buf.WriteString(fmt.Sprintf("+%s\r\n", data))
|
||||||
|
} else {
|
||||||
|
buf.WriteString(fmt.Sprintf("$%d\r\n%s\r\n", len(notificationName), notificationName))
|
||||||
|
buf.WriteString(fmt.Sprintf("$%d\r\n%s\r\n", len(notificationName), notificationName))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return buf
|
return buf
|
||||||
|
@ -116,26 +116,55 @@ func (r *Reader) PeekPushNotificationName() (string, error) {
|
|||||||
if buf[0] != RespPush {
|
if buf[0] != RespPush {
|
||||||
return "", fmt.Errorf("redis: can't parse push notification: %q", buf)
|
return "", fmt.Errorf("redis: can't parse push notification: %q", buf)
|
||||||
}
|
}
|
||||||
// remove push notification type and length
|
|
||||||
buf = buf[2:]
|
if len(buf) < 3 {
|
||||||
|
return "", fmt.Errorf("redis: can't parse push notification: %q", buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove push notification type
|
||||||
|
buf = buf[1:]
|
||||||
|
// remove first line - e.g. >2\r\n
|
||||||
for i := 0; i < len(buf)-1; i++ {
|
for i := 0; i < len(buf)-1; i++ {
|
||||||
if buf[i] == '\r' && buf[i+1] == '\n' {
|
if buf[i] == '\r' && buf[i+1] == '\n' {
|
||||||
buf = buf[i+2:]
|
buf = buf[i+2:]
|
||||||
break
|
break
|
||||||
|
} else {
|
||||||
|
if buf[i] < '0' || buf[i] > '9' {
|
||||||
|
return "", fmt.Errorf("redis: can't parse push notification: %q", buf)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if len(buf) < 2 {
|
||||||
|
return "", fmt.Errorf("redis: can't parse push notification: %q", buf)
|
||||||
|
}
|
||||||
|
// next line should be $<length><string>\r\n or +<length><string>\r\n
|
||||||
// should have the type of the push notification name and it's length
|
// should have the type of the push notification name and it's length
|
||||||
if buf[0] != RespString {
|
if buf[0] != RespString && buf[0] != RespStatus {
|
||||||
return "", fmt.Errorf("redis: can't parse push notification name: %q", buf)
|
return "", fmt.Errorf("redis: can't parse push notification name: %q", buf)
|
||||||
}
|
}
|
||||||
// skip the length of the string
|
typeOfName := buf[0]
|
||||||
for i := 0; i < len(buf)-1; i++ {
|
// remove the type of the push notification name
|
||||||
if buf[i] == '\r' && buf[i+1] == '\n' {
|
buf = buf[1:]
|
||||||
buf = buf[i+2:]
|
if typeOfName == RespString {
|
||||||
break
|
// remove the length of the string
|
||||||
|
if len(buf) < 2 {
|
||||||
|
return "", fmt.Errorf("redis: can't parse push notification name: %q", buf)
|
||||||
|
}
|
||||||
|
for i := 0; i < len(buf)-1; i++ {
|
||||||
|
if buf[i] == '\r' && buf[i+1] == '\n' {
|
||||||
|
buf = buf[i+2:]
|
||||||
|
break
|
||||||
|
} else {
|
||||||
|
if buf[i] < '0' || buf[i] > '9' {
|
||||||
|
return "", fmt.Errorf("redis: can't parse push notification name: %q", buf)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(buf) < 2 {
|
||||||
|
return "", fmt.Errorf("redis: can't parse push notification name: %q", buf)
|
||||||
|
}
|
||||||
// keep only the notification name
|
// keep only the notification name
|
||||||
for i := 0; i < len(buf)-1; i++ {
|
for i := 0; i < len(buf)-1; i++ {
|
||||||
if buf[i] == '\r' && buf[i+1] == '\n' {
|
if buf[i] == '\r' && buf[i+1] == '\n' {
|
||||||
@ -143,6 +172,7 @@ func (r *Reader) PeekPushNotificationName() (string, error) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return util.BytesToString(buf), nil
|
return util.BytesToString(buf), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user