thumbnail: Factor frames into account for IMAGE_BOMB_TOTAL_PIXELS.

This commit is contained in:
Alex Vandiver
2024-07-19 18:19:28 +00:00
committed by Tim Abbott
parent aacf28f7e3
commit 71406ac767
2 changed files with 35 additions and 1 deletions

View File

@@ -163,7 +163,10 @@ def libvips_check_image(image_data: bytes) -> Iterator[pyvips.Image]:
except pyvips.Error: except pyvips.Error:
raise BadImageError(_("Could not decode image; did you upload an image file?")) raise BadImageError(_("Could not decode image; did you upload an image file?"))
if source_image.width * source_image.height > IMAGE_BOMB_TOTAL_PIXELS: if (
source_image.width * source_image.height * source_image.get_n_pages()
> IMAGE_BOMB_TOTAL_PIXELS
):
raise BadImageError(_("Image size exceeds limit.")) raise BadImageError(_("Image size exceeds limit."))
try: try:

View File

@@ -380,6 +380,37 @@ class TestStoreThumbnail(ZulipTestCase):
), ),
) )
def test_big_upload(self) -> None:
# We decline to treat as an image a large single-frame image
self.login_user(self.example_user("hamlet"))
with get_test_image_file("img.gif") as image_file:
with patch.object(pyvips.Image, "new_from_buffer") as mock_from_buffer:
mock_from_buffer.return_value.width = 1000000
mock_from_buffer.return_value.height = 1000000
mock_from_buffer.return_value.get_n_pages.return_value = 1
response = self.assert_json_success(
self.client_post("/json/user_uploads", {"file": image_file})
)
path_id = re.sub(r"/user_uploads/", "", response["url"])
self.assertTrue(Attachment.objects.filter(path_id=path_id).exists())
self.assertFalse(ImageAttachment.objects.filter(path_id=path_id).exists())
def test_big_animated_upload(self) -> None:
# We also decline to process a small but many-frame image
self.login_user(self.example_user("hamlet"))
with get_test_image_file("img.gif") as image_file:
with patch.object(pyvips.Image, "new_from_buffer") as mock_from_buffer:
mock_from_buffer.return_value.width = 100
mock_from_buffer.return_value.height = 100
mock_from_buffer.return_value.get_n_pages.return_value = 1000000
response = self.assert_json_success(
self.client_post("/json/user_uploads", {"file": image_file})
)
path_id = re.sub(r"/user_uploads/", "", response["url"])
self.assertTrue(Attachment.objects.filter(path_id=path_id).exists())
self.assertFalse(ImageAttachment.objects.filter(path_id=path_id).exists())
def test_bad_upload(self) -> None: def test_bad_upload(self) -> None:
assert settings.LOCAL_FILES_DIR assert settings.LOCAL_FILES_DIR
hamlet = self.example_user("hamlet") hamlet = self.example_user("hamlet")