From ad896bb091c6eb976b0006f6dc685e36ebf4bfb0 Mon Sep 17 00:00:00 2001 From: Donjuanplatinum Date: Sun, 8 Mar 2026 12:23:02 +0800 Subject: [PATCH] cllipy fix --- src/api/client/media.rs | 22 +++++++++++--------- src/core/config/mod.rs | 8 ++++---- src/service/media/data.rs | 42 +++++++++++++++++++++------------------ src/service/media/mod.rs | 22 ++++++++++---------- 4 files changed, 52 insertions(+), 42 deletions(-) diff --git a/src/api/client/media.rs b/src/api/client/media.rs index d63df14f..53898b00 100644 --- a/src/api/client/media.rs +++ b/src/api/client/media.rs @@ -100,17 +100,21 @@ pub(crate) async fn create_mxc_uri_route( media_id: &utils::random_string(MXC_LENGTH), }; - let unused_expires_at = (std::time::SystemTime::now() - .duration_since(std::time::UNIX_EPOCH) - .expect("Time went backwards") - .as_millis() as u64) - .saturating_add( - services + let unused_expires_at = u64::try_from( + std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .expect("Time went backwards") + .as_millis(), + )? + .saturating_add( + services .server .config - .media_create_unused_expiration_time - * 1000, - ); + .media_create_unused_expiration_time + // safe because even if it overflows, it will be greater than the current time + // and the unused media will be deleted anyway + .saturating_mul(1000), + ); services .media .create_pending(&mxc, user, unused_expires_at) diff --git a/src/core/config/mod.rs b/src/core/config/mod.rs index 2ff20575..06d162ee 100644 --- a/src/core/config/mod.rs +++ b/src/core/config/mod.rs @@ -427,13 +427,13 @@ pub struct Config { /// /// default: 10 #[serde(default = "default_rc_media_create_per_second")] - pub rc_media_create_per_second: u64, + pub rc_media_create_per_second: u32, /// The maximum burst count for media create requests from a single user. /// /// default: 50 #[serde(default = "default_rc_media_create_burst_count")] - pub rc_media_create_burst_count: u64, + pub rc_media_create_burst_count: u32, /// default: 192 #[serde(default = "default_max_fetch_prev_events")] @@ -3274,8 +3274,8 @@ fn default_ip_lookup_strategy() -> u8 { 5 } fn default_max_request_size() -> usize { 24 * 1024 * 1024 } fn default_max_pending_media_uploads() -> usize { 5 } fn default_media_create_unused_expiration_time() -> u64 { 86400 } -fn default_rc_media_create_per_second() -> u64 { 10 } -fn default_rc_media_create_burst_count() -> u64 { 50 } +fn default_rc_media_create_per_second() -> u32 { 10 } +fn default_rc_media_create_burst_count() -> u32 { 50 } fn default_request_conn_timeout() -> u64 { 10 } diff --git a/src/service/media/data.rs b/src/service/media/data.rs index a57cfcc2..3de84426 100644 --- a/src/service/media/data.rs +++ b/src/service/media/data.rs @@ -70,7 +70,12 @@ impl Data { ); // 8 bytes for unused_expires_at (u64), 1 byte for 0xFF, and // user.as_bytes().len() for user value: [unused_expires_at, 0xFF, user] - let mut value = Vec::with_capacity(user.as_bytes().len() + 9); + let mut value = Vec::with_capacity( + user.as_bytes() + .len() + .checked_add(9) + .expect("User len too large,capacity overflow!"), + ); value.extend_from_slice(&unused_expires_at.to_be_bytes()); value.push(0xFF); value.extend_from_slice(user.as_bytes()); @@ -80,7 +85,7 @@ impl Data { /// Count the number of pending MXC URIs for a specific user pub(super) async fn count_pending_mxc_for_user(&self, user: &UserId) -> (usize, u64) { - let mut count = 0; + let mut count: usize = 0; let mut earliest_expiration = u64::MAX; let user_bytes = user.as_bytes(); @@ -89,18 +94,19 @@ impl Data { .ignore_err() .ready_for_each(|(_key, value)| { let mut parts = value.splitn(2, |&b| b == 0xFF); - if let Some(expires_at_bytes) = parts.next() { - if let Some(user_id_bytes) = parts.next() { - if user_id_bytes == user_bytes { - count += 1; - let expires_at = u64::from_be_bytes( - expires_at_bytes.try_into().unwrap_or([0u8; 8]), - ); - if expires_at < earliest_expiration { - earliest_expiration = expires_at; - } + match (parts.next(), parts.next()) { + | (Some(expires_at_bytes), Some(user_id_bytes)) + if user_id_bytes == user_bytes => + { + // safe to add 1 even if count = usize::MAX it also > max_uploads + count = count.saturating_add(1_usize); + let expires_at = + u64::from_be_bytes(expires_at_bytes.try_into().unwrap_or([0_u8; 8])); + if expires_at < earliest_expiration { + earliest_expiration = expires_at; } - } + }, + | _ => {}, } }) .await; @@ -133,12 +139,10 @@ impl Data { }, }; let user_id_bytes = parts.next()?; - let user_str = match str_from_bytes(user_id_bytes) { - | Ok(v) => v, - | Err(_) => { - tracing::error!("Failed to parse user_str for {}", key); - return None; - }, + + let Ok(user_str) = str_from_bytes(user_id_bytes) else { + tracing::error!("Failed to parse user_str for {}", key); + return None; }; let user_id = match user_str.try_into() { | Ok(v) => v, diff --git a/src/service/media/mod.rs b/src/service/media/mod.rs index 0ce48a3f..81cd2987 100644 --- a/src/service/media/mod.rs +++ b/src/service/media/mod.rs @@ -93,8 +93,8 @@ impl Service { let config = &self.services.server.config; // Rate limiting (rc_media_create) - let rate = config.rc_media_create_per_second as f64; - let burst = config.rc_media_create_burst_count as f64; + let rate = f64::from(config.rc_media_create_per_second); + let burst = f64::from(config.rc_media_create_burst_count); // Check rate limiting if rate > 0.0 && burst > 0.0 { @@ -106,7 +106,7 @@ impl Service { .or_insert_with(|| (now, burst)); let elapsed = now.duration_since(*last_time).as_secs_f64(); - let new_tokens = (*tokens + elapsed * rate).min(burst); + let new_tokens = elapsed.mul_add(rate, *tokens).min(burst); if new_tokens >= 1.0 { *last_time = now; @@ -126,12 +126,12 @@ impl Service { // Check if the user has reached the maximum number of pending media uploads if current_uploads >= max_uploads { - let retry_after = earliest_expiration.saturating_sub( + let retry_after = earliest_expiration.saturating_sub(u64::try_from( SystemTime::now() .duration_since(std::time::UNIX_EPOCH) .unwrap() - .as_millis() as u64, - ); + .as_millis(), + )?); return Err(tuwunel_core::Error::Request( ruma::api::client::error::ErrorKind::LimitExceeded { retry_after: Some(ruma::api::client::error::RetryAfter::Delay( @@ -166,10 +166,12 @@ impl Service { return Err!(Request(Forbidden("You did not create this media ID"))); } - let current_time = SystemTime::now() - .duration_since(std::time::UNIX_EPOCH) - .expect("Time went backwards") - .as_millis() as u64; + let current_time = u64::try_from( + SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .expect("Time went backwards") + .as_millis(), + )?; if expires_at < current_time { return Err!(Request(NotFound("Pending media ID expired")));