fix(image): decode raster bodies served with XML MIME types

This commit is contained in:
ldm0
2026-10-20 03:50:08 +08:00
committed by Donough Liu
parent a017801943
commit 2eefd9690c
+35 -13
View File
@@ -448,9 +448,6 @@ fn image_response_descriptor_from_bytes(
moli_web_mime::MimeSniffingContext::Image,
body,
);
if !moli_web_mime::is_image_mime_essence(&computed_mime_type) {
return None;
}
if moli_web_mime::is_svg_image_mime_essence(&computed_mime_type) {
let metadata = moli_image::probe_svg_image(body).ok()?;
return crate::native_bridge::ImageResponseDescriptor::svg(metadata);
@@ -489,18 +486,29 @@ mod tests {
for (mime, bytes) in [
("image/png", png.as_slice()),
("image/svg+xml", svg.as_slice()),
("application/xml", png.as_slice()),
("text/xml", png.as_slice()),
("application/blah+xml", png.as_slice()),
] {
let encoded = manager.from_frozen_bytes(bytes.to_vec());
for status in [200, 206, 301, 302, 400, 404, 410, 500, 503] {
let response = crate::protocol_types::NavigationResponse::from_text_body(
url::Url::parse("https://images.test/image").unwrap(),
status,
vec![("Content-Type".to_owned(), mime.as_bytes().to_vec())],
String::new(),
);
let descriptor = image_response_descriptor_from_parkable(&response, &encoded)
.unwrap_or_else(|| panic!("{mime} image rejected at HTTP {status}"));
assert_eq!((descriptor.width, descriptor.height), (2, 1));
for nosniff in [false, true] {
let mut headers = vec![("Content-Type".to_owned(), mime.as_bytes().to_vec())];
if nosniff {
headers.push(("X-Content-Type-Options".to_owned(), b"nosniff".to_vec()));
}
for status in [200, 206, 301, 302, 400, 404, 410, 500, 503] {
let response = crate::protocol_types::NavigationResponse::from_text_body(
url::Url::parse("https://images.test/image").unwrap(),
status,
headers.clone(),
String::new(),
);
let descriptor = image_response_descriptor_from_parkable(&response, &encoded)
.unwrap_or_else(|| {
panic!("{mime} image rejected at HTTP {status}, nosniff={nosniff}")
});
assert_eq!((descriptor.width, descriptor.height), (2, 1));
}
}
}
}
@@ -508,12 +516,26 @@ mod tests {
#[test]
fn image_response_rejects_empty_and_invalid_data_at_any_http_status() {
let manager = moli_parkable_image::ParkableImageManager::default();
let png =
moli_image::encode_png(&moli_image::RgbaImage::try_new(2, 1, vec![255; 8]).unwrap())
.unwrap()
.bytes;
let svg = br#"<svg xmlns="http://www.w3.org/2000/svg" width="2" height="1"/>"#;
for (mime, bytes) in [
("image/png", b"".as_slice()),
("image/png", b"\x89PNG\r\n\x1a\n".as_slice()),
("image/png", b"not an image".as_slice()),
("image/svg+xml", b"<html>Not Found</html>".as_slice()),
("text/html", b"<html>Not Found</html>".as_slice()),
("application/xml", b"\x89PNG\r\n\x1a\n".as_slice()),
(
"application/xml",
b"<?xml version='1.0'?><not-an-image/>".as_slice(),
),
("application/blah+xml", b"<html>Not Found</html>".as_slice()),
("image/svg+xml", png.as_slice()),
("application/xml", svg.as_slice()),
("application/blah+xml", svg.as_slice()),
] {
let encoded = manager.from_frozen_bytes(bytes.to_vec());
for status in [200, 404, 500] {