From 292241f420dfc1efa8834bafa71fd566bd09814d Mon Sep 17 00:00:00 2001 From: Evan Typanski Date: Thu, 5 Dec 2024 15:28:09 -0500 Subject: [PATCH] spicy-redis: Make client data only accept bulk strings --- src/analyzer/protocol/redis/redis.spicy | 5 +---- src/analyzer/protocol/redis/resp.spicy | 21 ++++++++++++++++++++- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/analyzer/protocol/redis/redis.spicy b/src/analyzer/protocol/redis/redis.spicy index 96cd222068..a0f950139f 100644 --- a/src/analyzer/protocol/redis/redis.spicy +++ b/src/analyzer/protocol/redis/redis.spicy @@ -67,10 +67,7 @@ public function make_command(command: RESP::ClientData): Command { public function bulk_command(command: RESP::ClientData): Command { local v: vector; for (ele in command.multibulk.elements) { - # TODO: Stringify the other data too. Apparently commands *can* have other stuff - # such as SUBSCRIBE, which will magically put an integer after it. - if (ele?.bulk_string) - v.push_back(ele.bulk_string.content); + v.push_back(ele.content); } return parse_command(v); } diff --git a/src/analyzer/protocol/redis/resp.spicy b/src/analyzer/protocol/redis/resp.spicy index 1396a65b2a..1eab54438d 100644 --- a/src/analyzer/protocol/redis/resp.spicy +++ b/src/analyzer/protocol/redis/resp.spicy @@ -27,7 +27,7 @@ public type ClientData = unit { } } if (self.ty == DataType::ARRAY) { - multibulk: Array; + multibulk: BulkStringArray; } else { inline: RedisBytes &max-size=1024; }; @@ -40,6 +40,25 @@ public type ClientData = unit { } }; +type BulkStringArray = unit { + num_elements: RedisBytes &convert=$$.to_int(10) &requires=self.num_elements <= int64(MAX_SIZE); + # Null array is an array with elements unset. This is different from an empty array + elements: BulkStringWithTy[uint64(self.num_elements)]; +}; + +type BulkStringWithTy = unit { + # Need to consume the type here + : uint8 &requires=$$=='$'; + + length: RedisBytes &convert=$$.to_int(10) &requires=self.length <= int64(MAX_SIZE); + # NullBulkString is a BulkString with content unset + content: bytes &size=uint64(self.length) if(self.length >= 0); + + # Consume last CLRF + : skip RedisBytes; +}; + + public type ServerData = unit { %synchronize-after = b"\x0d\x0a"; data: Data;