提前拒绝高位深 PNG 解码
通过 image crate 的 ImageReader decoder 元数据在像素缓冲分配前拒绝 16-bit PNG。 继续使用同一外部 decoder 执行受限像素读取校验,不手写 PNG 解析器。
This commit is contained in:
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user