From 60911d8c0157ff4c42db91f6b46a1d80af06ae94 Mon Sep 17 00:00:00 2001 From: xgzlucario <912156837@qq.com> Date: Tue, 30 Jul 2024 00:03:51 +0800 Subject: [PATCH] fix: set error type in object.SetData() --- Makefile | 3 +++ command_test.go | 14 ++++++++++++++ internal/dict/dict_test.go | 2 +- internal/dict/object.go | 2 +- resp.go | 12 ++++++------ resp_test.go | 10 ++++++++++ 6 files changed, 35 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index 1a322c3..2692315 100644 --- a/Makefile +++ b/Makefile @@ -10,6 +10,9 @@ test-cover: rm coverage.txt rm *.aof +fuzz-test: + go test -fuzz=FuzzRESPReader + pprof: go tool pprof -http=:18081 "http://192.168.1.6:6060/debug/pprof/profile?seconds=30" diff --git a/command_test.go b/command_test.go index 804a60e..92cca07 100644 --- a/command_test.go +++ b/command_test.go @@ -224,6 +224,20 @@ func TestCommand(t *testing.T) { assert.NotNil(err) }) + t.Run("trans-zipmap", func(t *testing.T) { + for i := 0; i <= 256; i++ { + k := fmt.Sprintf("%06x", i) + rdb.HSet(ctx, "zipmap", k, k) + } + }) + + t.Run("trans-zipset", func(t *testing.T) { + for i := 0; i <= 512; i++ { + k := fmt.Sprintf("%06x", i) + rdb.SAdd(ctx, "zipset", k) + } + }) + t.Run("client-closed", func(t *testing.T) { rdb.Close() }) diff --git a/internal/dict/dict_test.go b/internal/dict/dict_test.go index c555a82..7a3ef57 100644 --- a/internal/dict/dict_test.go +++ b/internal/dict/dict_test.go @@ -31,7 +31,7 @@ func TestDict(t *testing.T) { dict := New() dict.SetWithTTL("key", []byte("hello"), time.Now().Add(time.Minute).UnixNano()) - time.Sleep(time.Millisecond) + time.Sleep(time.Second / 10) object, ttl := dict.Get("key") assert.Equal(ttl, 59) diff --git a/internal/dict/object.go b/internal/dict/object.go index 50811d2..653c099 100644 --- a/internal/dict/object.go +++ b/internal/dict/object.go @@ -57,7 +57,7 @@ func typeOfData(data any) Type { case *hash.Set: return TypeSet case *hash.ZipSet: - return TypeSet + return TypeZipSet case *list.QuickList: return TypeList case *zset.ZSet: diff --git a/resp.go b/resp.go index 9183239..caf826d 100644 --- a/resp.go +++ b/resp.go @@ -15,6 +15,7 @@ const ( INTEGER = ':' BULK = '$' ARRAY = '*' + MAP = '%' // TODO: https://redis.io/docs/latest/develop/reference/protocol-spec/#maps ) var CRLF = []byte("\r\n") @@ -46,7 +47,7 @@ func cutByCRLF(buf []byte) (before, after []byte, found bool) { } // ReadNextCommand reads the next RESP command from the RESPReader. -// It parses both COMMAND_BULK and COMMAND_INLINE formats. +// It parses both `COMMAND_BULK` and `COMMAND_INLINE` formats. func (r *RESPReader) ReadNextCommand(argsBuf []RESP) (args []RESP, err error) { if len(r.b) == 0 { return nil, io.EOF @@ -66,11 +67,10 @@ func (r *RESPReader) ReadNextCommand(argsBuf []RESP) (args []RESP, err error) { } r.b = after + // read bulk strings for range for i := 0; i < count; i++ { - switch r.b[0] { - case BULK: - default: - return nil, fmt.Errorf("unsupport array-in type: '%c'", r.b[0]) + if len(r.b) == 0 || r.b[0] != BULK { + return nil, errInvalidArguments } // read CRLF @@ -85,7 +85,7 @@ func (r *RESPReader) ReadNextCommand(argsBuf []RESP) (args []RESP, err error) { r.b = after // bound check - if count > len(r.b) { + if count < 0 || count+2 > len(r.b) { return nil, errInvalidArguments } diff --git a/resp_test.go b/resp_test.go index b7ae4b0..9388f93 100644 --- a/resp_test.go +++ b/resp_test.go @@ -100,6 +100,10 @@ func TestReader(t *testing.T) { args, err = NewReader([]byte("*3\r\n$3ABC")).ReadNextCommand(nil) assert.Equal(len(args), 0) assert.NotNil(err) + + args, err = NewReader([]byte("*1\r\n")).ReadNextCommand(nil) + assert.Equal(len(args), 0) + assert.NotNil(err) }) t.Run("command-inline", func(t *testing.T) { @@ -108,3 +112,9 @@ func TestReader(t *testing.T) { assert.Nil(err) }) } + +func FuzzRESPReader(f *testing.F) { + f.Fuzz(func(t *testing.T, b []byte) { + NewReader(b).ReadNextCommand(nil) + }) +}