From b34d3ff2f05d4bc320c0e9b89beab981175b19c7 Mon Sep 17 00:00:00 2001 From: Evan Typanski Date: Thu, 26 Jun 2025 09:56:17 -0400 Subject: [PATCH] Stringify all Redis-RESP serialized data --- src/analyzer/protocol/redis/redis.spicy | 76 ++++++++++++++----- src/analyzer/protocol/redis/resp.spicy | 5 +- .../output | 4 +- .../output | 4 +- .../redis.log | 4 +- 5 files changed, 67 insertions(+), 26 deletions(-) diff --git a/src/analyzer/protocol/redis/redis.spicy b/src/analyzer/protocol/redis/redis.spicy index 777857f81d..0f2c958e98 100644 --- a/src/analyzer/protocol/redis/redis.spicy +++ b/src/analyzer/protocol/redis/redis.spicy @@ -430,36 +430,78 @@ function bulk_string_content(bulk: RESP::BulkString): bytes { } # Returns the bytes string value of this, or Null if it cannot. -function stringify(data: RESP::Data): optional { - if (data?.simple_error) - return data.simple_error.content; - else if (data?.bulk_error) - return bulk_string_content(data.bulk_error); - else if (data?.simple_string) +function stringify(data: RESP::Data): bytes { + if (data?.simple_string) return data.simple_string.content; + else if (data?.simple_error) + return data.simple_error.content; + else if (data?.integer) + return data.integer.val; else if (data?.bulk_string) return bulk_string_content(data.bulk_string); - else if (data?.verbatim_string) - return bulk_string_content(data.verbatim_string); - else if (data?.boolean) - return data.boolean.val ? b"T" : b"F"; - else if (data?.array || data?.push) { + else if (data?.array) { local res = b"["; local first = True; - for (ele in data?.array ? data.array.elements : data.push.elements) { + for (ele in data.array.elements) { if (!first) res += b", "; - local ele_stringified = stringify(ele); - if (!ele_stringified) - return Null; - res += *ele_stringified; + res += stringify(ele); + first = False; + } + res += b"]"; + return res; + } else if (data?.null) + return b"null"; + else if (data?.boolean) + return data.boolean.val ? b"T" : b"F"; + else if (data?.double) + return data.double.val; + else if (data?.big_num) + return data.big_num.val; + else if (data?.bulk_error) + return bulk_string_content(data.bulk_error); + else if (data?.verbatim_string) + return bulk_string_content(data.verbatim_string); + else if (data?.map_) { + local res = b"{"; + local first = True; + local i = 0; + while (i < data.map_.num_elements) { + if (!first) + res += b", "; + res += stringify(data.map_.raw_data[i]); + res += b": "; + res += stringify(data.map_.raw_data[i + 1]); + i += 2; + first = False; + } + res += b"}"; + return res; + } else if (data?.set_) { + local res = b"("; + local first = True; + for (ele in data.set_.elements) { + if (!first) + res += b", "; + res += stringify(ele); + first = False; + } + res += b")"; + return res; + } else if (data?.push) { + local res = b"["; + local first = True; + for (ele in data.push.elements) { + if (!first) + res += b", "; + res += stringify(ele); first = False; } res += b"]"; return res; } - return Null; + throw "unknown RESP type"; } # Gets the server reply in a simpler form diff --git a/src/analyzer/protocol/redis/resp.spicy b/src/analyzer/protocol/redis/resp.spicy index 2fb73277dc..dfc7d990bb 100644 --- a/src/analyzer/protocol/redis/resp.spicy +++ b/src/analyzer/protocol/redis/resp.spicy @@ -149,7 +149,7 @@ type SimpleString = unit(is_error: bool) { }; type Integer = unit { - int: RedisBytes &convert=$$.to_int(10); + val: RedisBytes; }; type BulkString = unit(is_error: bool) { @@ -178,11 +178,10 @@ type Boolean = unit { }; type Double = unit { - val: RedisBytes &convert=$$.to_real(); + val: RedisBytes; }; type BigNum = unit { - # Big num can be very big so leave it in bytes. val: RedisBytes; }; diff --git a/testing/btest/Baseline/scripts.base.protocols.redis.pubsub-resp3/output b/testing/btest/Baseline/scripts.base.protocols.redis.pubsub-resp3/output index 60f704875f..6458393b86 100644 --- a/testing/btest/Baseline/scripts.base.protocols.redis.pubsub-resp3/output +++ b/testing/btest/Baseline/scripts.base.protocols.redis.pubsub-resp3/output @@ -1,6 +1,6 @@ ### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. -Got published data!, [value=] -Got published data!, [value=] +Got published data!, [value=[subscribe, Foo, 1]] +Got published data!, [value=[psubscribe, F*, 2]] Got published data!, [value=[message, Foo, Hi:)]] Got published data!, [value=[pmessage, F*, Foo, Hi:)]] Got published data!, [value=[pmessage, F*, Foobar, Hello!]] diff --git a/testing/btest/Baseline/scripts.base.protocols.redis.pubsub/output b/testing/btest/Baseline/scripts.base.protocols.redis.pubsub/output index 460df0d529..a086e7d7cc 100644 --- a/testing/btest/Baseline/scripts.base.protocols.redis.pubsub/output +++ b/testing/btest/Baseline/scripts.base.protocols.redis.pubsub/output @@ -1,6 +1,6 @@ ### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. -Got published data!, [value=] -Got published data!, [value=] +Got published data!, [value=[subscribe, Foo, 1]] +Got published data!, [value=[psubscribe, F*, 2]] Got published data!, [value=[message, Foo, Hi there :)]] Got published data!, [value=[pmessage, F*, Foo, Hi there :)]] Got published data!, [value=[pmessage, F*, FeeFooFiiFum, Hello! :)]] diff --git a/testing/btest/Baseline/scripts.base.protocols.redis.pubsub/redis.log b/testing/btest/Baseline/scripts.base.protocols.redis.pubsub/redis.log index 11ed195257..e604657317 100644 --- a/testing/btest/Baseline/scripts.base.protocols.redis.pubsub/redis.log +++ b/testing/btest/Baseline/scripts.base.protocols.redis.pubsub/redis.log @@ -7,8 +7,8 @@ #open XXXX-XX-XX-XX-XX-XX #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p cmd.name cmd.key cmd.value success reply.value #types time string addr port addr port string string string bool string -XXXXXXXXXX.XXXXXX ClEkJM2Vm5giqnMf4h 127.0.0.1 60833 127.0.0.1 6379 PUBLISH - - T - -XXXXXXXXXX.XXXXXX C4J4Th3PJpwUYZZ6gc 127.0.0.1 60837 127.0.0.1 6379 PUBLISH - - T - +XXXXXXXXXX.XXXXXX ClEkJM2Vm5giqnMf4h 127.0.0.1 60833 127.0.0.1 6379 PUBLISH - - T 2 +XXXXXXXXXX.XXXXXX C4J4Th3PJpwUYZZ6gc 127.0.0.1 60837 127.0.0.1 6379 PUBLISH - - T 1 XXXXXXXXXX.XXXXXX CtPZjS20MLrsMUOJi2 127.0.0.1 60838 127.0.0.1 6379 SET sanity_check you_are_sane T OK XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 127.0.0.1 60831 127.0.0.1 6379 SUBSCRIBE - - - - XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 127.0.0.1 60831 127.0.0.1 6379 PSUBSCRIBE - - - -