Skip to content

Commit 1af22a7

Browse files
committed
fix(sdk_common): TimelineEvent::from_bundled_latest_event can remove session_id
What's more, this is saved into the event cache and sometimes it overrides another instance of the same event that actually contains the right info. This results in unresolvables UTDs. This change tries to fetch the session id from the existing event content. It's fixed these kind of UTDs when tested in a real client.
1 parent 504d15f commit 1af22a7

2 files changed

Lines changed: 60 additions & 8 deletions

File tree

crates/matrix-sdk-common/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ All notable changes to this project will be documented in this file.
66

77
## [Unreleased] - ReleaseDate
88

9+
### Bug Fixes
10+
11+
- Fix `TimelineEvent::from_bundled_latest_event` sometimes removing the `session_id` of UTDs. This broken event could later be saved to the event cache and become an unresolvable UTD. ([#5970](https://github.com/matrix-org/matrix-rust-sdk/pull/5970)).
12+
913
## [0.16.0] - 2025-12-04
1014

1115
### Features

crates/matrix-sdk-common/src/deserialized_responses.rs

Lines changed: 56 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use ruma::{
1818
DeviceKeyAlgorithm, MilliSecondsSinceUnixEpoch, OwnedDeviceId, OwnedEventId, OwnedUserId,
1919
events::{
2020
AnySyncMessageLikeEvent, AnySyncTimelineEvent, AnyTimelineEvent, AnyToDeviceEvent,
21-
MessageLikeEventType,
21+
MessageLikeEventType, room::encrypted::EncryptedEventScheme,
2222
},
2323
push::Action,
2424
serde::{
@@ -713,14 +713,21 @@ impl TimelineEvent {
713713

714714
Ok(Some(MessageLikeEventType::RoomEncrypted)) => {
715715
// The bundled latest thread event is encrypted, but we didn't have any
716-
// information about it in the unsigned map. Provide some dummy
717-
// UTD info, since we can't really do much better.
716+
// information about it in the unsigned map. Try to fetch the information from
717+
// the content instead.
718+
let session_id = if let Some(content) =
719+
latest_event.get_field::<EncryptedEventScheme>("content").ok().flatten()
720+
{
721+
match content {
722+
EncryptedEventScheme::MegolmV1AesSha2(content) => Some(content.session_id),
723+
_ => None,
724+
}
725+
} else {
726+
None
727+
};
718728
Some(Box::new(TimelineEvent::from_utd_with_max_timestamp(
719729
latest_event.cast(),
720-
UnableToDecryptInfo {
721-
session_id: None,
722-
reason: UnableToDecryptReason::Unknown,
723-
},
730+
UnableToDecryptInfo { session_id, reason: UnableToDecryptReason::Unknown },
724731
max_timestamp,
725732
)))
726733
}
@@ -1457,7 +1464,9 @@ mod tests {
14571464
use insta::{assert_json_snapshot, with_settings};
14581465
use ruma::{
14591466
DeviceKeyAlgorithm, MilliSecondsSinceUnixEpoch, UInt, device_id, event_id,
1460-
events::room::message::RoomMessageEventContent, serde::Raw, user_id,
1467+
events::{AnySyncTimelineEvent, room::message::RoomMessageEventContent},
1468+
serde::Raw,
1469+
user_id,
14611470
};
14621471
use serde::Deserialize;
14631472
use serde_json::json;
@@ -2096,4 +2105,43 @@ mod tests {
20962105
}
20972106
});
20982107
}
2108+
2109+
#[test]
2110+
fn test_from_bundled_latest_event_keeps_session_id() {
2111+
let session_id = "hgLyeSqXfb8vc5AjQLsg6TSHVu0HJ7HZ4B6jgMvxkrs";
2112+
let serialized = json!({
2113+
"content": {
2114+
"algorithm": "m.megolm.v1.aes-sha2",
2115+
"ciphertext": "AwgAEoABzL1JYhqhjW9jXrlT3M6H8mJ4qffYtOQOnPuAPNxsuG20oiD/Fnpv6jnQGhU6YbV9pNM+1mRnTvxW3CbWOPjLKqCWTJTc7Q0vDEVtYePg38ncXNcwMmfhgnNAoW9S7vNs8C003x3yUl6NeZ8bH+ci870BZL+kWM/lMl10tn6U7snNmSjnE3ckvRdO+11/R4//5VzFQpZdf4j036lNSls/WIiI67Fk9iFpinz9xdRVWJFVdrAiPFwb8L5xRZ8aX+e2JDMlc1eW8gk",
2116+
"device_id": "SKCGPNUWAU",
2117+
"sender_key": "Gim/c7uQdSXyrrUbmUOrBT6sMC0gO7QSLmOK6B7NOm0",
2118+
"session_id": session_id,
2119+
},
2120+
"event_id": "$xxxxx:example.org",
2121+
"origin_server_ts": 2189,
2122+
"room_id": "!someroom:example.com",
2123+
"sender": "@carl:example.com",
2124+
"type": "m.room.encrypted"
2125+
});
2126+
let json = serialized.to_string();
2127+
let value = Raw::<AnySyncTimelineEvent>::from_json_string(json).unwrap();
2128+
2129+
let kind = TimelineEventKind::UnableToDecrypt {
2130+
event: value.clone(),
2131+
utd_info: UnableToDecryptInfo {
2132+
session_id: None,
2133+
reason: UnableToDecryptReason::Unknown,
2134+
},
2135+
};
2136+
let result = TimelineEvent::from_bundled_latest_event(
2137+
&kind,
2138+
Some(value.cast_unchecked()),
2139+
MilliSecondsSinceUnixEpoch::now(),
2140+
)
2141+
.expect("Could not get bundled latest event");
2142+
2143+
assert_let!(TimelineEventKind::UnableToDecrypt { utd_info, .. } = result.kind);
2144+
assert!(utd_info.session_id.is_some());
2145+
assert_eq!(utd_info.session_id.unwrap(), session_id);
2146+
}
20992147
}

0 commit comments

Comments
 (0)