karlch / vimiv-qt

An image viewer with vim-like keybindings
https://karlch.github.io/vimiv-qt/
GNU General Public License v3.0
177 stars 15 forks source link

Crash when getting metadata for svg and avif files #803

Closed janpeterd closed 4 months ago

janpeterd commented 4 months ago

When I press i keybind to display metadata of svg the program crashes and produces this error:

[00:46:00] ERROR    <vimiv>              Uncaught exception! Exiting gracefully and printing stack...
Traceback (most recent call last):
  File "/usr/lib/python3.11/site-packages/vimiv/gui/eventhandler.py", line 138, in keyPressEvent
    elif not self._process_event(keysequence, mode=mode):
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/vimiv/gui/eventhandler.py", line 183, in _process_event
    runners.run(command, count=count, mode=mode)
  File "/usr/lib/python3.11/site-packages/vimiv/commands/runners.py", line 45, in inner
    return func(text, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/vimiv/commands/runners.py", line 76, in run
    _run_single(cmdpart, mode, count)
  File "/usr/lib/python3.11/site-packages/vimiv/commands/runners.py", line 45, in inner
    return func(text, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/vimiv/commands/runners.py", line 95, in _run_single
    command(count + text, mode)
  File "/usr/lib/python3.11/site-packages/vimiv/commands/runners.py", line 115, in command
    _run_command(count, cmdname, args, mode)
  File "/usr/lib/python3.11/site-packages/vimiv/commands/runners.py", line 150, in _run_command
    cmd(args, count=count)
  File "/usr/lib/python3.11/site-packages/vimiv/api/commands.py", line 322, in __call__
    objreg._call_with_instance(self.func, **kwargs)
  File "/usr/lib/python3.11/site-packages/vimiv/api/objreg.py", line 68, in _call_with_instance
    return func(cls.instance, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/vimiv/gui/metadatawidget.py", line 103, in metadata
    self._update_text()
  File "/usr/lib/python3.11/site-packages/vimiv/gui/metadatawidget.py", line 158, in _update_text
    data = self.handler.get_metadata(keys)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/vimiv/imutils/metadata.py", line 150, in get_metadata
    out = {**backend(self._path).get_metadata(keys), **out}
             ^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/vimiv/plugins/metadata_pyexiv2.py", line 31, in __init__
    self._metadata.read()
  File "/usr/lib/python3.11/site-packages/pyexiv2/metadata.py", line 115, in read
    self.__image = self._instantiate_image(self.filename)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/pyexiv2/metadata.py", line 87, in _instantiate_image
    return libexiv2python._Image(filename)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
OSError: /home/jp/Pictures/jp-radio.svg: The file contains data of an unknown image type

I get the same error with avif files:

[00:47:33] ERROR    <vimiv>              Uncaught exception! Exiting gracefully and printing stack...
Traceback (most recent call last):
  File "/usr/lib/python3.11/site-packages/vimiv/gui/eventhandler.py", line 138, in keyPressEvent
    elif not self._process_event(keysequence, mode=mode):
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/vimiv/gui/eventhandler.py", line 183, in _process_event
    runners.run(command, count=count, mode=mode)
  File "/usr/lib/python3.11/site-packages/vimiv/commands/runners.py", line 45, in inner
    return func(text, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/vimiv/commands/runners.py", line 76, in run
    _run_single(cmdpart, mode, count)
  File "/usr/lib/python3.11/site-packages/vimiv/commands/runners.py", line 45, in inner
    return func(text, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/vimiv/commands/runners.py", line 95, in _run_single
    command(count + text, mode)
  File "/usr/lib/python3.11/site-packages/vimiv/commands/runners.py", line 115, in command
    _run_command(count, cmdname, args, mode)
  File "/usr/lib/python3.11/site-packages/vimiv/commands/runners.py", line 150, in _run_command
    cmd(args, count=count)
  File "/usr/lib/python3.11/site-packages/vimiv/api/commands.py", line 322, in __call__
    objreg._call_with_instance(self.func, **kwargs)
  File "/usr/lib/python3.11/site-packages/vimiv/api/objreg.py", line 68, in _call_with_instance
    return func(cls.instance, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/vimiv/gui/metadatawidget.py", line 103, in metadata
    self._update_text()
  File "/usr/lib/python3.11/site-packages/vimiv/gui/metadatawidget.py", line 158, in _update_text
    data = self.handler.get_metadata(keys)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/vimiv/imutils/metadata.py", line 150, in get_metadata
    out = {**backend(self._path).get_metadata(keys), **out}
             ^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/vimiv/plugins/metadata_pyexiv2.py", line 31, in __init__
    self._metadata.read()
  File "/usr/lib/python3.11/site-packages/pyexiv2/metadata.py", line 115, in read
    self.__image = self._instantiate_image(self.filename)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/pyexiv2/metadata.py", line 87, in _instantiate_image
    return libexiv2python._Image(filename)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
OSError: /home/jp/Code/Projects/webdev/portfolio/.svelte-kit/output/server/_app/immutable/assets/hero.s6K3NcxQ.avif: The file contains data of an unknown image type

I installed the vimiv-qt-git package from the AUR.

This is my config it should be almost default but it might help:

[GENERAL]
monitor_filesystem = True
startup_library = True
style = gruvbox_dark_hard
read_only = False

[COMMAND]
history_limit = 100

[COMPLETION]
fuzzy = False

[SEARCH]
ignore_case = True
incremental = True

[IMAGE]
autoplay = True
autowrite = ask
overzoom = 1.0
zoom_wheel_ctrl = True

[LIBRARY]
width = 0.3
show_hidden = False

[THUMBNAIL]
size = 128
save = True

[SLIDESHOW]
delay = 2.0
indicator = slideshow:

[STATUSBAR]
collapse_home = True
show = True
message_timeout = 60000
mark_indicator = <b>*</b>
left = {pwd}{read-only}
left_image = {index}/{total} {basename}{read-only} [{zoomlevel}]
left_thumbnail = {thumbnail-index}/{thumbnail-total} {thumbnail-basename}{read-only}
left_manipulate = {basename}   {image-size}   Modified: {modified}   {processing}
center_thumbnail = {thumbnail-size}
center = {slideshow-indicator} {slideshow-delay} {transformation-info}
right = {keys}  {mark-count}  {mode}
right_image = {keys}  {mark-indicator} {mark-count}  {mode}

[KEYHINT]
delay = 500
timeout = 5000

[TITLE]
fallback = vimiv
image = vimiv - {basename}

[METADATA]
keys1 = Exif.Image.Make,Exif.Image.Model,Exif.Photo.LensModel,Exif.Image.DateTime,Exif.Image.Artist,Exif.Image.Copyright
keys2 = Exif.Photo.ExposureTime,Exif.Photo.FNumber,Exif.Photo.ISOSpeedRatings,Exif.Photo.ApertureValue,Exif.Photo.ExposureBiasValue,Exif.Photo.FocalLength,Exif.Photo.ExposureProgram
keys3 = Exif.GPSInfo.GPSLatitudeRef,Exif.GPSInfo.GPSLatitude,Exif.GPSInfo.GPSLongitudeRef,Exif.GPSInfo.GPSLongitude,Exif.GPSInfo.GPSAltitudeRef,Exif.GPSInfo.GPSAltitude
keys4 = Iptc.Application2.Caption,Iptc.Application2.Keywords,Iptc.Application2.City,Iptc.Application2.SubLocation,Iptc.Application2.ProvinceState,Iptc.Application2.CountryName,Iptc.Application2.Source,Iptc.Application2.Credit,Iptc.Application2.Copyright,Iptc.Application2.Contact
keys5 = Exif.Image.ImageWidth,Exif.Image.ImageLength,Exif.Photo.PixelXDimension,Exif.Photo.PixelYDimension,Exif.Image.BitsPerSample,Exif.Image.Compression,Exif.Photo.ColorSpace

[SORT]
image_order = alphabetical
directory_order = alphabetical
reverse = False
ignore_case = False
shuffle = False

[PLUGINS]
print = default
metadata = default
imageformats = avif

[ALIASES]
jcjgraf commented 4 months ago

Thanks for reporting. Do you experience the issue with other images of these formats too? Do you mind sharing those two images?

janpeterd commented 4 months ago

Yes using the metadata command crashes the program on all SVG and avif images

This is the image that produced the first error. jp-radio

(github doesnt allow me to upload .avif files)

But I don't think that it is file specific, since it happens on all files of these types.

I tested other filetypes and so far only these 2 cause a crash.

karlch commented 4 months ago

Thanks for reporting! I can definitely reproduce this with pyexiv2 and a random svg I had lying around.

@jcjgraf seems like changing the constructor of the corresponding metadata plugin to

class MetadataPyexiv2(metadata.MetadataPlugin):
    """Provides metadata support based on pyexiv2."""

    def __init__(self, path: str) -> None:
        self._path = path

        try:
            self._metadata = pyexiv2.ImageMetadata(path)
            self._metadata.read()
        except FileNotFoundError:
            _logger.debug("File %s not found", path)
            self._metadata = None
        except OSError as e:
            _logger.warning(str(e))
            self._metadata = None

does the trick. I find the choice of OSError by pyexiv2 very questionable, but do you think we should go with this? I could commit and push in this case.

jcjgraf commented 4 months ago

Thanks for looking into it. I never run into this issue as I am using a different metadata backend. This fix makes sense to me :+1: