olefile icon indicating copy to clipboard operation
olefile copied to clipboard

Invalid OleFile Raises Different Exceptions in Python 2 and 3

Open TheElementalOfDestruction opened this issue 6 years ago • 9 comments

Is your feature request related to a problem? Please describe. Python 2 raises an IOError for an invalid olefile, but Python 3 raises an OSError for an invalid olefile.

Describe the solution you'd like Choose a single exception type and use it for both versions. Preferably, raise a custom exception type.

Describe alternatives you've considered Right now I can sort of get around this by just catching all IOErrors, checking if they are for invalid ole, and then raising them under a new exception if they are. Otherwise, I re-raise the original exception.

Additional context I am the current manager of the msg-extractor project, and this would be a great help.

Interesting... it's the same code for Python 2 and 3, so I would need a few more details to troubleshoot the issue: which OS are you using, and is there any chance you can share a file that triggers the exception? Also, can you share the stack trace for the exception on each python version? Thanks!

decalage2 avatar Dec 10 '18 20:12 decalage2

Os independent as far as I can tell. I've tested it on multiple operating systems and the problem still occurs. A file that triggers the exception is literally ANYTHING that is not an actual olefile. Personally, I just used olefile.OleFileIO(b'f'*2000).

PyPy2 stack trace:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Users\Creation\Desktop\pypy2-v5.9.0-win32\site-packages\olefile\olefile.py", line 1075, in __init__
    self.open(filename, write_mode=write_mode)
  File "C:\Users\Creation\Desktop\pypy2-v5.9.0-win32\site-packages\olefile\olefile.py", line 1192, in open
    self._raise_defect(DEFECT_FATAL, "not an OLE2 structured storage file")
  File "C:\Users\Creation\Desktop\pypy2-v5.9.0-win32\site-packages\olefile\olefile.py", line 1105, in _raise_defect
    raise exception_type(message)
IOError: not an OLE2 structured storage file

Python 2 stack trace:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.7/site-packages/olefile/olefile.py", line 1075, in __init__
    self.open(filename, write_mode=write_mode)
  File "/usr/lib/python2.7/site-packages/olefile/olefile.py", line 1192, in open
    self._raise_defect(DEFECT_FATAL, "not an OLE2 structured storage file")
  File "/usr/lib/python2.7/site-packages/olefile/olefile.py", line 1105, in _raise_defect
    raise exception_type(message)
IOError: not an OLE2 structured storage file

Python 3 stack trace:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.6/site-packages/olefile/olefile.py", line 1075, in __init__
    self.open(filename, write_mode=write_mode)
  File "/usr/lib/python3.6/site-packages/olefile/olefile.py", line 1192, in open
    self._raise_defect(DEFECT_FATAL, "not an OLE2 structured storage file")
  File "/usr/lib/python3.6/site-packages/olefile/olefile.py", line 1105, in _raise_defect
    raise exception_type(message)
OSError: not an OLE2 structured storage file

Either way, it would definitely be preferable IMO for olefile to raise a custom exception type.

Wait, I think I know what happened. I don't know WHY it happened, but it did.

In olefile.py at some point IOError got reassigned to be OSError

OK, I'll look into that. Looking at the olefile code, most issues should trigger IOError, while OSError is only used in one specific case, when trying to read from a closed file.

decalage2 avatar Dec 10 '18 21:12 decalage2

But you are right that it would be better for olefile to define its own exceptions.

decalage2 avatar Dec 10 '18 21:12 decalage2

Wait

It's python 3 itself. IOError has been replaced with OSError. Try help(IOError) in a python 3 console.

Changed in version 3.3: EnvironmentError, IOError, WindowsError, socket.error, select.error and mmap.error have been merged into OSError, and the constructor may return a subclass.

decalage2 avatar Dec 10 '18 21:12 decalage2

IMO, the custom exception doesn't need to be anything fancy. Just a simple:

class OleFileError(IOError): # or whatever name and whatever exception you want to derive from
    pass

would do just fine. Just some way for users to be able to easily catch this specific kind of error.

Added a new pull request that will fix this issue