mirror of
https://gitlab.computer.surgery/matrix/grapevine.git
synced 2025-12-17 15:51:23 +01:00
improve media key decoding logs
On my HS I observed 5 instances of keys with the following format: * MXC bytes. * A 0xFF byte. * 4 bytes where the width and height are supposed to be, which are supposed to be 8 bytes in length. * 3 consecutive 0xFF bytes. This means that the `content-type` and `content-disposition` sections both parse as the empty string, and there's an extra separator at the end too. * Extra bytes, all of which were `image/png`. The 4 bytes where the width and height are supposed to be were one of: * 003ED000 * 003EE000 * 003EF001 Which seems to have some kind of pattern to it... After much digging, we have absolutely no idea what could've caused this. Cursed.
This commit is contained in:
parent
d848e787d3
commit
cb3e0c620a
2 changed files with 23 additions and 7 deletions
|
|
@ -19,24 +19,28 @@ struct MediaFileKeyParts {
|
||||||
impl TryFrom<&MediaFileKey> for MediaFileKeyParts {
|
impl TryFrom<&MediaFileKey> for MediaFileKeyParts {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
|
#[tracing::instrument(
|
||||||
|
err,
|
||||||
|
fields(key = utils::u8_slice_to_hex(key.as_bytes())),
|
||||||
|
)]
|
||||||
fn try_from(key: &MediaFileKey) -> Result<MediaFileKeyParts> {
|
fn try_from(key: &MediaFileKey) -> Result<MediaFileKeyParts> {
|
||||||
let mut parts = key.as_bytes().split(|&b| b == 0xFF);
|
let mut parts = key.as_bytes().split(|&b| b == 0xFF);
|
||||||
|
|
||||||
let mxc_bytes = parts
|
let mxc_bytes = parts
|
||||||
.next()
|
.next()
|
||||||
.ok_or_else(|| Error::bad_database("Media ID in db is invalid."))?;
|
.ok_or_else(|| Error::BadDatabase("Media ID in db is invalid."))?;
|
||||||
let mxc = utils::string_from_bytes(mxc_bytes)
|
let mxc = utils::string_from_bytes(mxc_bytes)
|
||||||
.map_err(|_| {
|
.map_err(|_| {
|
||||||
Error::bad_database("Media MXC URI in db is invalid unicode.")
|
Error::BadDatabase("Media MXC URI in db is invalid unicode.")
|
||||||
})?
|
})?
|
||||||
.into();
|
.into();
|
||||||
|
|
||||||
let thumbnail_size_bytes = parts
|
let thumbnail_size_bytes = parts
|
||||||
.next()
|
.next()
|
||||||
.ok_or_else(|| Error::bad_database("Media ID in db is invalid."))?;
|
.ok_or_else(|| Error::BadDatabase("Media ID in db is invalid."))?;
|
||||||
let thumbnail_size_bytes: &[u8; 8] =
|
let thumbnail_size_bytes: &[u8; 8] =
|
||||||
thumbnail_size_bytes.try_into().map_err(|_| {
|
thumbnail_size_bytes.try_into().map_err(|_| {
|
||||||
Error::bad_database("Media ID thumbnail size in db is invalid")
|
Error::BadDatabase("Media ID thumbnail size in db is invalid")
|
||||||
})?;
|
})?;
|
||||||
let width = u32::from_be_bytes(
|
let width = u32::from_be_bytes(
|
||||||
thumbnail_size_bytes[..4].try_into().expect("should be 4 bytes"),
|
thumbnail_size_bytes[..4].try_into().expect("should be 4 bytes"),
|
||||||
|
|
@ -49,7 +53,7 @@ impl TryFrom<&MediaFileKey> for MediaFileKeyParts {
|
||||||
.next()
|
.next()
|
||||||
.map(|bytes| {
|
.map(|bytes| {
|
||||||
utils::string_from_bytes(bytes).map_err(|_| {
|
utils::string_from_bytes(bytes).map_err(|_| {
|
||||||
Error::bad_database(
|
Error::BadDatabase(
|
||||||
"Content type in mediaid_file is invalid unicode.",
|
"Content type in mediaid_file is invalid unicode.",
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
@ -58,14 +62,14 @@ impl TryFrom<&MediaFileKey> for MediaFileKeyParts {
|
||||||
|
|
||||||
let content_disposition_bytes = parts
|
let content_disposition_bytes = parts
|
||||||
.next()
|
.next()
|
||||||
.ok_or_else(|| Error::bad_database("Media ID in db is invalid."))?;
|
.ok_or_else(|| Error::BadDatabase("Media ID in db is invalid."))?;
|
||||||
|
|
||||||
let content_disposition = if content_disposition_bytes.is_empty() {
|
let content_disposition = if content_disposition_bytes.is_empty() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(utils::string_from_bytes(content_disposition_bytes).map_err(
|
Some(utils::string_from_bytes(content_disposition_bytes).map_err(
|
||||||
|_| {
|
|_| {
|
||||||
Error::bad_database(
|
Error::BadDatabase(
|
||||||
"Content Disposition in mediaid_file is invalid \
|
"Content Disposition in mediaid_file is invalid \
|
||||||
unicode.",
|
unicode.",
|
||||||
)
|
)
|
||||||
|
|
|
||||||
12
src/utils.rs
12
src/utils.rs
|
|
@ -4,6 +4,7 @@ pub(crate) mod on_demand_hashmap;
|
||||||
use std::{
|
use std::{
|
||||||
borrow::Cow,
|
borrow::Cow,
|
||||||
cmp, fmt,
|
cmp, fmt,
|
||||||
|
fmt::Write,
|
||||||
str::FromStr,
|
str::FromStr,
|
||||||
time::{SystemTime, UNIX_EPOCH},
|
time::{SystemTime, UNIX_EPOCH},
|
||||||
};
|
};
|
||||||
|
|
@ -366,6 +367,17 @@ pub(crate) fn curlify<T>(req: &http::Request<T>) -> Option<String> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Format a u8 slice as an uppercase hex string
|
||||||
|
///
|
||||||
|
/// The output does not contain a leading `0x` nor any non-hex characters (e.g.
|
||||||
|
/// whitespace or commas do not appear in the output).
|
||||||
|
pub(crate) fn u8_slice_to_hex(slice: &[u8]) -> String {
|
||||||
|
slice.iter().fold(String::new(), |mut acc, x| {
|
||||||
|
write!(acc, "{x:X}").expect("in-memory write should succeed");
|
||||||
|
acc
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::utils::dbg_truncate_str;
|
use crate::utils::dbg_truncate_str;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue