Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Segmentation fault with RESP3 map inside set #188

Closed
gerzse opened this issue Jun 10, 2024 · 0 comments · Fixed by #189
Closed

Segmentation fault with RESP3 map inside set #188

gerzse opened this issue Jun 10, 2024 · 0 comments · Fixed by #189

Comments

@gerzse
Copy link
Contributor

gerzse commented Jun 10, 2024

This surfaced from redis-py tests with RESP3. After debugging, it turns out that the response to the COMMAND command contains maps nested into sets.

In Python it's not possible to store dict inside set, because it is not hashable. The visible effect is that the call results in a segmentation fault.

Here is a RESP3 fragment, that is part of the XREAD content in the response to COMMAND:

~1
%3
$5
flags
~2
+RO
+access
$12
begin_search
%2
$4
type
$7
keyword
$4
spec
%2
$7
keyword
$7
STREAMS
$9
startfrom
:1
$9
find_keys
%2
$4
type
$5
range
$4
spec
%3
$7
lastkey
:-1
$7
keystep
:1
$5
limit
:2

A better visualization is this:

1~ 1# "flags" => 1~ RO
                 2~ access
   2# "begin_search" => 1# "type" => "keyword"
                        2# "spec" => 1# "keyword" => "STREAMS"
                                     2# "startfrom" => (integer) 1
   3# "find_keys" => 1# "type" => "range"
                     2# "spec" => 1# "lastkey" => (integer) -1
                                  2# "keystep" => (integer) 1
                                  3# "limit" => (integer) 2

And two small unit tests, one with maps inside lists, which works, and one with maps inside sets, which gives segmentation fault.

def test_map_inside_list(reader):
  reader.feed(b"*1\r\n%1\r\n+a\r\n:1\r\n")
  assert [{b"a": 1}] == reader.gets()

def test_map_inside_set(reader):
  reader.feed(b"~1\r\n%1\r\n+a\r\n:1\r\n")
  assert reader.gets() is not None

In general I think it's not possible to store data like that into Redis, i.e. to have maps inside sets. It might well be that the COMMAND command is the only one returning such a structure in its response. Some code in redis-py relies on this however. I'm curious what are your thoughts on this. I don't see any elegant and easy solution.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant