限制 Raw 图片解码资源

为 PNG 解码设置边长和分配上限
避免压缩图片膨胀导致内存耗尽
This commit is contained in:
2026-09-08 19:45:02 +08:00
parent a86a2ee4d2
commit 22785b4d7b
+8 -3
View File
@@ -6,8 +6,8 @@ use axum::{
use base64::{Engine as _, engine::general_purpose::STANDARD as BASE64_STANDARD}; use base64::{Engine as _, engine::general_purpose::STANDARD as BASE64_STANDARD};
use image::{ImageFormat, ImageReader}; use image::{ImageFormat, ImageReader};
use platform_image::{ use platform_image::{
RawImageEditOptions, ReferenceImage, create_vector_engine_raw_image_edit, RAW_IMAGE_MAX_EDGE, RAW_IMAGE_MAX_PIXELS, RawImageEditOptions, ReferenceImage,
validate_raw_image_edit_dimensions, create_vector_engine_raw_image_edit, validate_raw_image_edit_dimensions,
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use serde_json::json; use serde_json::json;
@@ -197,9 +197,14 @@ fn decode_image(value: RawImageData, field: &str) -> Result<ReferenceImage, AppE
if bytes.is_empty() { if bytes.is_empty() {
return Err(bad_request(format!("{field}.data 不能为空"))); return Err(bad_request(format!("{field}.data 不能为空")));
} }
let reader = ImageReader::new(Cursor::new(bytes.as_slice())) let mut reader = ImageReader::new(Cursor::new(bytes.as_slice()))
.with_guessed_format() .with_guessed_format()
.map_err(|_| bad_request(format!("{field}.data 必须是有效 PNG 文件")))?; .map_err(|_| bad_request(format!("{field}.data 必须是有效 PNG 文件")))?;
let mut limits = image::Limits::default();
limits.max_image_width = Some(RAW_IMAGE_MAX_EDGE);
limits.max_image_height = Some(RAW_IMAGE_MAX_EDGE);
limits.max_alloc = Some(RAW_IMAGE_MAX_PIXELS.saturating_mul(4));
reader.limits(limits);
if reader.format() != Some(ImageFormat::Png) { if reader.format() != Some(ImageFormat::Png) {
return Err(bad_request(format!("{field}.data 必须是有效 PNG 文件"))); return Err(bad_request(format!("{field}.data 必须是有效 PNG 文件")));
} }