[FIX] base: avoid fail with wrong mimetype

Uploading a WEBP or SVG file disguised with a proper file extension (JPG, PNG)
will cause a traceback because img.image is
not populated when there is an empty source, SVG, or WEBP file uploaded
as this code should not be reached with these file types.

The reason this occurs is because we check for the file extension when
deciding to post process an image, but when we get to initializing the
ImageProcess object, we then check the actual file structure to verify
the type of file.

This is a workaround for the time being, but should not be a final
solution in future versions.

Adding a null check on img.image in the _postprocess_contents method
in order to avoid attempting to access the size of this image when it is
null.

Raises a user error in order to trigger the catch and exit the code
while logging the error and 'Post processing ignored:'.

Includes test for this new workflow with no errors.

opw-3672250

closes odoo/odoo#162976

X-original-commit: e9750b16a61c3598f7a2b14a1552fcb4ecf1a293
Signed-off-by: Benoit Socias (bso) <bso@odoo.com>
Signed-off-by: Ryan Cen (ryce) <ryce@odoo.com>
This commit is contained in:
Ryan Cen
2024-04-23 23:18:06 +00:00
committed by Benoit Socias
parent ebf695ea09
commit 7dc51b3dee
2 changed files with 12 additions and 1 deletions
+5 -1
View File
@@ -326,7 +326,7 @@ class IrAttachment(models.Model):
supported_subtype = ICP('base.image_autoresize_extensions', 'png,jpeg,bmp,tiff').split(',') supported_subtype = ICP('base.image_autoresize_extensions', 'png,jpeg,bmp,tiff').split(',')
mimetype = values['mimetype'] = self._compute_mimetype(values) mimetype = values['mimetype'] = self._compute_mimetype(values)
_type, _, _subtype = mimetype.partition('/') _type, _match, _subtype = mimetype.partition('/')
is_image_resizable = _type == 'image' and _subtype in supported_subtype is_image_resizable = _type == 'image' and _subtype in supported_subtype
if is_image_resizable and (values.get('datas') or values.get('raw')): if is_image_resizable and (values.get('datas') or values.get('raw')):
is_raw = values.get('raw') is_raw = values.get('raw')
@@ -341,6 +341,10 @@ class IrAttachment(models.Model):
else: # datas else: # datas
img = ImageProcess(base64.b64decode(values['datas']), verify_resolution=False) img = ImageProcess(base64.b64decode(values['datas']), verify_resolution=False)
if not img.image:
_logger.info('Post processing ignored : Empty source, SVG, or WEBP')
return values
w, h = img.image.size w, h = img.image.size
nw, nh = map(int, max_resolution.split('x')) nw, nh = map(int, max_resolution.split('x'))
if w > nw or h > nh: if w > nw or h > nh:
@@ -260,6 +260,13 @@ class TestIrAttachment(TransactionCaseWithUserDemo):
self.Attachment._gc_file_store_unsafe() self.Attachment._gc_file_store_unsafe()
self.assertFalse(os.path.isfile(store_path), 'file removed') self.assertFalse(os.path.isfile(store_path), 'file removed')
def test_14_invalid_mimetype_with_correct_file_extension_no_post_processing(self):
# test with fake svg with png mimetype
unique_blob = b'<svg xmlns="http://www.w3.org/2000/svg"></svg>'
a1 = self.Attachment.create({'name': 'a1', 'raw': unique_blob, 'mimetype': 'image/png'})
self.assertEqual(a1.raw, unique_blob)
self.assertEqual(a1.mimetype, 'image/png')
class TestPermissions(TransactionCaseWithUserDemo): class TestPermissions(TransactionCaseWithUserDemo):
def setUp(self): def setUp(self):