jazzband / django-avatar

A Django app for handling user avatars.
BSD 3-Clause "New" or "Revised" License
808 stars 303 forks source link

check if image is not corrupted during upload #218

Closed PetrDlouhy closed 1 year ago

PetrDlouhy commented 1 year ago

When user uploaded this image as his avatar: https://public.blenderkit.com/avatars/12630/20220720_114050.jpg all views containing that avatar started to fail with following error:

TypeError: object of type 'int' has no len()
  File "django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
  File "django/core/handlers/base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "newrelic/hooks/framework_django.py", line 552, in wrapper
    return wrapped(*args, **kwargs)
  File "django/views/generic/base.py", line 84, in view
    return self.dispatch(request, *args, **kwargs)
  File "newrelic/hooks/framework_django.py", line 946, in wrapper
    return wrapped(*args, **kwargs)
  File "django/views/generic/base.py", line 119, in dispatch
    return handler(request, *args, **kwargs)
  File "django/views/generic/base.py", line 216, in get
    url = self.get_redirect_url(*args, **kwargs)
  File "blenderhub/apps/frontend/views.py", line 193, in get_redirect_url
    return avatar_url(user_profile, kwargs["size"])
  File "avatar/templatetags/avatar_tags.py", line 21, in avatar_url
    avatar_url = provider.get_avatar_url(user, width, height)
  File "avatar/providers.py", line 38, in get_avatar_url
    avatar = get_primary_avatar(user, width, height)
  File "avatar/utils.py", line 141, in get_primary_avatar
    avatar.create_thumbnail(width, height)
  File "avatar/models.py", line 141, in create_thumbnail
    image = self.transpose_image(image)
  File "avatar/models.py", line 127, in transpose_image
    image = ImageOps.exif_transpose(image)
  File "PIL/ImageOps.py", line 602, in exif_transpose
    transposed_image.info["exif"] = transposed_exif.tobytes()
  File "PIL/Image.py", line 3628, in tobytes
    return b"Exif\x00\x00" + head + ifd.tobytes(offset)
  File "PIL/TiffImagePlugin.py", line 878, in tobytes
    data = ifd.tobytes(offset)
  File "PIL/TiffImagePlugin.py", line 887, in tobytes
    "<table: %d bytes>" % len(data) if len(data) >= 16 else str(values)

This failure could potentially broke whole website. This PR tries to capture that failure during avatar upload and report to user, that the image is corrupted.