diff --git a/server-rs/crates/api-server/src/raw_image.rs b/server-rs/crates/api-server/src/raw_image.rs index bead3a52e..6f3b55c52 100644 --- a/server-rs/crates/api-server/src/raw_image.rs +++ b/server-rs/crates/api-server/src/raw_image.rs @@ -4,7 +4,7 @@ use axum::{ http::StatusCode, }; use bytes::Bytes; -use image::{GenericImageView, ImageFormat, ImageReader}; +use image::{ImageDecoder, ImageFormat, ImageReader}; use platform_image::{ GPT_IMAGE_2_2K_LONG_EDGE_THRESHOLD, RAW_IMAGE_MAX_EDGE, RAW_IMAGE_MAX_PIXELS, RawImageEditImage, RawImageEditOptions, create_vector_engine_raw_image_edit, @@ -393,11 +393,11 @@ fn decode_image( if reader.format() != Some(ImageFormat::Png) { return Err(bad_request(format!("{field} 文件必须是有效 PNG 文件"))); } - let decoded = reader - .decode() + let decoder = reader + .into_decoder() .map_err(|error| map_decode_image_error(field, error))?; if matches!( - decoded.color(), + decoder.color_type(), image::ColorType::Rgba16 | image::ColorType::Rgb16 | image::ColorType::L16 @@ -407,7 +407,23 @@ fn decode_image( "{field} 必须为 8-bit PNG(每通道 8 位)" ))); } - let (width, height) = decoded.dimensions(); + let (width, height) = decoder.dimensions(); + let decoded_bytes = usize::try_from(decoder.total_bytes()).map_err(|_| { + bad_request(format!( + "{field} 文件超出 PNG 尺寸或解码资源上限(单边不超过 {RAW_IMAGE_MAX_EDGE}px)" + )) + })?; + let max_decoded_bytes = + usize::try_from(RAW_IMAGE_MAX_PIXELS.saturating_mul(4)).unwrap_or(usize::MAX); + if decoded_bytes > max_decoded_bytes { + return Err(bad_request(format!( + "{field} 文件超出 PNG 尺寸或解码资源上限(单边不超过 {RAW_IMAGE_MAX_EDGE}px)" + ))); + } + let mut decoded = vec![0_u8; decoded_bytes]; + decoder + .read_image(&mut decoded) + .map_err(|error| map_decode_image_error(field, error))?; Ok(( RawImageEditImage { bytes,