pefile icon indicating copy to clipboard operation
pefile copied to clipboard

Py2: is_valid_function_name throws exception if bytearray is used as __data__

Open psrok1 opened this issue 5 years ago • 0 comments

During execution of code presented below:

with open("calc.exe", "rb") as f: data = bytearray(f.read())
pefile.PE(data=data)

it interrupts with exception:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "build/bdist.linux-x86_64/egg/pefile.py", line 1754, in __init__
  File "build/bdist.linux-x86_64/egg/pefile.py", line 2110, in __parse__
  File "build/bdist.linux-x86_64/egg/pefile.py", line 2224, in full_load
  File "build/bdist.linux-x86_64/egg/pefile.py", line 2474, in parse_data_directories
  File "build/bdist.linux-x86_64/egg/pefile.py", line 3933, in parse_import_directory
  File "build/bdist.linux-x86_64/egg/pefile.py", line 4067, in parse_imports
  File "build/bdist.linux-x86_64/egg/pefile.py", line 1464, in is_valid_function_name
  File "build/bdist.linux-x86_64/egg/pefile.py", line 1464, in <genexpr>
TypeError: 'in <string>' requires string as left operand, not int

Compatibility between Py 2.x and 3.x is ensured by future package, which contains newbytes implementation. Unfortunately, it's not used everywhere and sometimes replaced by def b(x): return x function (implemented here, used here):

if PY3:
    allowed_function_name = b(
        string.ascii_lowercase + string.ascii_uppercase +
        string.digits + '_?@$()<>')
else:
    allowed_function_name = b(
        string.lowercase + string.uppercase +
        string.digits + b'_?@$()<>')

def is_valid_function_name(s):
    return (s is not None and
        isinstance(s, (str, bytes, bytearray)) and
        all(c in allowed_function_name for c in set(s)))

When bytearray is passed to is_valid_function_name under Python 2.x, it is unpacked into list of ints, which doesn't work properly with in <str> operator (expected in <bytes>)

psrok1 avatar Jul 22 '19 08:07 psrok1