LeoHsiao1 / pyexiv2

Read and write image metadata, including EXIF, IPTC, XMP, ICC Profile.
GNU General Public License v3.0
201 stars 39 forks source link

Uncatchable error thrown by exiv2 #8

Closed WNiels closed 4 years ago

WNiels commented 4 years ago

Bug description: While reading some of my images, i get the following error printed to console:

Error: Upper boundary of data for directory Casio2, entry 0x2000 is out of bounds: Offset = 0x00000822, size = 31578, exceeds buffer size by 76 Bytes; truncating the entry

This error seems to be thrown by exiv2 but is not translated into a catchable python error.

Expected behaviour: The error should be catchable. A UpperBoundaryError extending Exception should be thrown. The following code should be able to catch this error.

try:
    exif = im.read_exif() # where img is a valid pyexiv2.Image object
except BaseException as e:
    print(e)

What i found so far: I traced the error down to the following function in core.py:

    def _open_image(self):
        """ Let C++ program open an image and read its metadata,
        save as a global variable in C++ program. """
        api.open_image.restype = ctypes.c_char_p
        ret = api.open_image(
            self.filename).decode()  # WIP: "Error: Upper boundary of data (...)" seems to originate here.
        if ret != OK:
            raise RuntimeError(ret)

Edit Added new findings.

LeoHsiao1 commented 4 years ago

Hi! I've noticed that some of the exceptions thrown by exiv2 are not caught properly by python, and the exception you mentioned is one of them, which is defined here. I will try to deal with this problem next week. Please send me a picture that can raise this exception so that I can debug it.

WNiels commented 4 years ago

Thanks for the fast reply, i have sent you an email with a picture for debugging.

LeoHsiao1 commented 4 years ago

Hi! I've been a bit lazy lately, so I just released the new version today. In version 2.0.0, stderr's log 'EXV_ERROR' will be converted to an exception. For example:

>>> from pyexiv2 import Image
>>> img = Image(r'c:\Users\Leo\Desktop\CIMG7607_recompress.JPG') 
Traceback (most recent call last):   
  File "<stdin>", line 1, in <module>
  File "C:\Users\Leo\AppData\Local\Programs\Python\Python38\lib\site-packages\pyexiv2\core.py", line 19, in __init__
    self.img = api.open_image(filename.encode(encoding))
RuntimeError: Upper boundary of data for directory Casio2, entry 0x2000 is out of bounds: Offset = 0x00000822, size = 30384, exceeds buffer size by 76 Bytes; truncating the entry

In addition, I have solved the UnicodeDecodeError you mentioned in the email, by adding a parameter encoding='utf-8' to some methods. For example:

>>> img.read_exif()
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 0: invalid start byte
>>> img.read_exif(encoding='ISO-8859-1')
{'Exif.Image.Make': 'CASIO COMPUTER CO.,LTD ', 'Exif.Image.Model': 'EX-Z50 ', ...}
LeoHsiao1 commented 4 years ago

Oops! I found that in the first case, your image will not be opened. The error log of exiv2 will not interrupt the program, but it will become fatal after it is converted into an exception. So what about making it an optional feature? For example:

>>> import pyexiv2
>>> img = pyexiv2.Image(r'c:\Users\Leo\Desktop\CIMG7607_recompress.JPG')
Error: Upper boundary of data for directory Casio2, entry 0x2000 is out of bounds: Offset = 0x00000822, size = 30384, exceeds buffer size by 76 Bytes; truncating the entry
>>> pyexiv2.convert_error_log_to_exception()    # Enable
>>> img = Image(r'c:\Users\Leo\Desktop\CIMG7607_recompress.JPG')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "D:\1\pyexiv2\pyexiv2\core.py", line 21, in __init__
    self.img = api.open_image(filename.encode(encoding))
RuntimeError: Upper boundary of data for directory Casio2, entry 0x2000 is out of bounds: Offset = 0x00000822, size = 30384, exceeds buffer size by 76 Bytes; truncating the entry
WNiels commented 4 years ago

Hi,

thanks so far! I have also been busy.But I will try to test your changes this week and give you feedback!

With kind regards,

Niels Westphal mail@nielswestphal.de Tel.: 0176 66874143

On Sun, Feb 16, 2020 at 4:11 PM 威尔阿威 notifications@github.com wrote:

Oops! I found that in the first case, your image will not be opened. The error log of exiv2 will not interrupt the program, but it will become fatal after it is converted into an exception. So what about making it an optional feature? For example:

import pyexiv2>>> img = pyexiv2.Image(r'c:\Users\Leo\Desktop\CIMG7607_recompress.JPG') Error: Upper boundary of data for directory Casio2, entry 0x2000 is out of bounds: Offset = 0x00000822, size = 30384, exceeds buffer size by 76 Bytes; truncating the entry>>> pyexiv2.convert_error_log_to_exception() # Enable>>> img = Image(r'c:\Users\Leo\Desktop\CIMG7607_recompress.JPG') Traceback (most recent call last): File "", line 1, in File "D:\1\pyexiv2\pyexiv2\core.py", line 21, in init self.img = api.open_image(filename.encode(encoding))RuntimeError: Upper boundary of data for directory Casio2, entry 0x2000 is out of bounds: Offset = 0x00000822, size = 30384, exceeds buffer size by 76 Bytes; truncating the entry

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/LeoHsiao1/pyexiv2/issues/8?email_source=notifications&email_token=AC3TEKSW2J4I2FLX67CPID3RDFJRFA5CNFSM4KOG2I5KYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEL4JUGI#issuecomment-586717721, or unsubscribe https://github.com/notifications/unsubscribe-auth/AC3TEKQMC6JT6NMGBUXUSE3RDFJRFANCNFSM4KOG2I5A .

LeoHsiao1 commented 4 years ago

I added a function pyexiv2.set_log_level() to the dev branch.

You can use the following code:

>>> import pyexiv2
>>> img = pyexiv2.Image(r'c:\Users\Leo\Desktop\CIMG7607_recompress.JPG')
RuntimeError: Upper boundary of data for directory Casio2, entry 0x2000 is out of bounds: Offset = 0x00000822, size = 30384, exceeds buffer size by 76 Bytes; truncating the entry
>>> pyexiv2.set_log_level(4)      # Ignore the error log
>>> img = pyexiv2.Image(r'c:\Users\Leo\Desktop\CIMG7607_recompress.JPG')

>>> data = img.read_exif()
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 0: invalid start byte
>>> data = img.read_exif(encoding='ISO-8859-1')      # Use an appropriate encoding
>>> img.close()

If there are no problems, I will add this feature to version 2.1.0.

LeoHsiao1 commented 4 years ago

I have released version 2.1.0

github-actions[bot] commented 3 years ago

This issue has been automatically closed because there has been no activity for a month.