Skip to content
This repository was archived by the owner on Apr 26, 2024. It is now read-only.

Commit 9356656

Browse files
authored
Do not try to store invalid data in the stats table (#8226)
1 parent d250521 commit 9356656

File tree

2 files changed

+27
-8
lines changed

2 files changed

+27
-8
lines changed

changelog.d/8226.bugfix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix a longstanding bug where stats updates could break when unexpected profile data was included in events.

synapse/storage/databases/main/stats.py

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -224,14 +224,32 @@ async def get_stats_positions(self) -> int:
224224
)
225225

226226
async def update_room_state(self, room_id: str, fields: Dict[str, Any]) -> None:
227-
"""
227+
"""Update the state of a room.
228+
229+
fields can contain the following keys with string values:
230+
* join_rules
231+
* history_visibility
232+
* encryption
233+
* name
234+
* topic
235+
* avatar
236+
* canonical_alias
237+
238+
A is_federatable key can also be included with a boolean value.
239+
228240
Args:
229-
room_id
230-
fields
241+
room_id: The room ID to update the state of.
242+
fields: The fields to update. This can include a partial list of the
243+
above fields to only update some room information.
231244
"""
232-
233-
# For whatever reason some of the fields may contain null bytes, which
234-
# postgres isn't a fan of, so we replace those fields with null.
245+
# Ensure that the values to update are valid, they should be strings and
246+
# not contain any null bytes.
247+
#
248+
# Invalid data gets overwritten with null.
249+
#
250+
# Note that a missing value should not be overwritten (it keeps the
251+
# previous value).
252+
sentinel = object()
235253
for col in (
236254
"join_rules",
237255
"history_visibility",
@@ -241,8 +259,8 @@ async def update_room_state(self, room_id: str, fields: Dict[str, Any]) -> None:
241259
"avatar",
242260
"canonical_alias",
243261
):
244-
field = fields.get(col)
245-
if field and "\0" in field:
262+
field = fields.get(col, sentinel)
263+
if field is not sentinel and (not isinstance(field, str) or "\0" in field):
246264
fields[col] = None
247265

248266
await self.db_pool.simple_upsert(

0 commit comments

Comments
 (0)