Skip to content

Commit b037d41

Browse files
committed
JSON encode replication keys
Instead of encoding them using a brittle, custom scheme. Avoids errors where the device ID or user ID contains a comma.
1 parent a096967 commit b037d41

File tree

2 files changed

+23
-14
lines changed

2 files changed

+23
-14
lines changed

synapse/storage/databases/main/cache.py

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222

2323
import itertools
24+
import json
2425
import logging
2526
from typing import TYPE_CHECKING, Any, Collection, Iterable, List, Optional, Tuple
2627

@@ -281,17 +282,20 @@ def process_replication_rows(
281282
== GET_E2E_CROSS_SIGNING_SIGNATURES_FOR_DEVICE_CACHE_NAME
282283
):
283284
# "keys" is a list of strings, where each string is a
284-
# stringified representation of the tuple keys, i.e.
285-
# keys: ['(@userid:domain,DEVICEID)','(@userid2:domain,DEVICEID2)']
285+
# JSON-encoded representation of the tuple keys, i.e.
286+
# keys: ['["@userid:domain", "DEVICEID"]','["@userid2:domain", "DEVICEID2"]']
286287
#
287-
# This is a side-effect of not being able to send nested information over replication.
288-
for tuple_key in row.keys:
289-
user_id, device_id = (
290-
# Remove the leading and following parantheses.
291-
tuple_key[1:-1]
292-
# Split by comma
293-
.split(",")
294-
)
288+
# This is a side-effect of not being able to send nested
289+
# information over replication.
290+
for json_str in row.keys:
291+
try:
292+
user_id, device_id = json.loads(json_str)
293+
except (json.JSONDecodeError, TypeError):
294+
logger.error(
295+
"Failed to deserialise cache key as valid JSON: %s",
296+
json_str,
297+
)
298+
continue
295299

296300
# Invalidate each key.
297301
#

synapse/storage/databases/main/end_to_end_keys.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#
2121
#
2222
import abc
23+
import json
2324
from typing import (
2425
TYPE_CHECKING,
2526
Any,
@@ -1854,10 +1855,14 @@ def _store_e2e_cross_signing_signatures(
18541855
)
18551856

18561857
to_invalidate = [
1857-
# Each entry is a tuple of arguments to
1858-
# `_get_e2e_cross_signing_signatures_for_device`, which
1859-
# itself takes a tuple. Hence the double-tuple.
1860-
((user_id, item.target_device_id),)
1858+
# We can only send primitives across replication.
1859+
# Encode the array of strings as a JSON string.
1860+
# We'll unpack it on the other side.
1861+
#
1862+
# Each entry is intended to be a tuple of arguments to the
1863+
# invalidation function, hence the need to wrap the string in a
1864+
# tuple.
1865+
(json.dumps([user_id, item.target_device_id]),)
18611866
for item in signatures
18621867
]
18631868

0 commit comments

Comments
 (0)