From fbc1e5449ae6e712e28407bd269670b805874aeb Mon Sep 17 00:00:00 2001 From: j-t-1 <120829237+j-t-1@users.noreply.github.com> Date: Fri, 5 Jun 2026 05:57:38 +0000 Subject: [PATCH 1/3] Move functions for consistency Moved three functions at the start to more logical positions. Put the word, double-word, quad-word get/set methods in size order. Ordered format characters to be the same as the documentation. https://docs.python.org/3/library/struct.html#format-characters --- pefile.py | 172 +++++++++++++++++++++++++++--------------------------- 1 file changed, 86 insertions(+), 86 deletions(-) diff --git a/pefile.py b/pefile.py index 53c0d671..284f57da 100644 --- a/pefile.py +++ b/pefile.py @@ -38,42 +38,6 @@ codecs.register_error("backslashreplace_", codecs.lookup_error("backslashreplace")) -# lru_cache with a shallow copy of the objects returned (list, dict, ...). -# We don't use copy.deepcopy as it's _really_ slow, and for the data we retrieve -# copy.copy is sufficient. -# https://stackoverflow.com/questions/54909357 -def lru_cache_copy(maxsize=128, typed=False): - def decorator(f): - cached_function = lru_cache(maxsize, typed)(f) - - @wraps(f) - def wrapper(*args, **kwargs): - return copy.copy(cached_function(*args, **kwargs)) - return wrapper - - return decorator - - -@lru_cache(maxsize=2048) -def cache_adjust_SectionAlignment(val, section_alignment, file_alignment): - if section_alignment < 0x1000: # page size - section_alignment = file_alignment - - # 0x200 is the minimum valid FileAlignment according to the documentation - # although ntoskrnl.exe has an alignment of 0x80 in some Windows versions - # - # elif section_alignment < 0x80: - # section_alignment = 0x80 - - if section_alignment and val % section_alignment: - return section_alignment * (val // section_alignment) - return val - - -def count_zeroes(data): - return data.count(0) - - fast_load = False # This will set a maximum length of a string to be retrieved from the file. @@ -711,6 +675,26 @@ def set_flags(obj, flag_field, flags): obj.__dict__[flag] = False +# lru_cache with a shallow copy of the objects returned (list, dict, ...). +# We don't use copy.deepcopy as it's _really_ slow, and for the data we retrieve +# copy.copy is sufficient. +# https://stackoverflow.com/questions/54909357 +def lru_cache_copy(maxsize=128, typed=False): + def decorator(f): + cached_function = lru_cache(maxsize, typed)(f) + + @wraps(f) + def wrapper(*args, **kwargs): + return copy.copy(cached_function(*args, **kwargs)) + return wrapper + + return decorator + + +def count_zeroes(data): + return data.count(0) + + def power_of_two(val): return val != 0 and (val & (val - 1)) == 0 @@ -867,9 +851,9 @@ def get_text(self): "I": 4, "l": 4, "L": 4, - "f": 4, "q": 8, "Q": 8, + "f": 4, "d": 8, "s": 1, } @@ -2327,6 +2311,22 @@ def is_valid_function_name( ) +@lru_cache(maxsize=2048) +def cache_adjust_SectionAlignment(val, section_alignment, file_alignment): + if section_alignment < 0x1000: # page size + section_alignment = file_alignment + + # 0x200 is the minimum valid FileAlignment according to the documentation + # although ntoskrnl.exe has an alignment of 0x80 in some Windows versions + # + # elif section_alignment < 0x80: + # section_alignment = 0x80 + + if section_alignment and val % section_alignment: + return section_alignment * (val // section_alignment) + return val + + class PE: """A Portable Executable representation. @@ -7284,104 +7284,104 @@ def get_physical_by_rva(self, rva): return None ## - # Double-Word get / set + # Word get / set ## - def get_data_from_dword(self, dword): - """Return a four byte string representing the double word value (little endian).""" - return struct.pack(" len(data): + if (offset + 1) * 2 > len(data): return None - return struct.unpack(" len(self.__data__): + if offset + 2 > len(self.__data__): return None - return self.get_dword_from_data(self.__data__[offset : offset + 4], 0) + return self.get_word_from_data(self.__data__[offset : offset + 2], 0) - def set_dword_at_rva(self, rva, dword): - """Set the double word value at the file offset corresponding to the given RVA.""" - return self.set_bytes_at_rva(rva, self.get_data_from_dword(dword)) + def set_word_at_rva(self, rva, word): + """Set the word value at the file offset corresponding to the given RVA.""" + return self.set_bytes_at_rva(rva, self.get_data_from_word(word)) - def set_dword_at_offset(self, offset, dword): - """Set the double word value at the given file offset.""" - return self.set_bytes_at_offset(offset, self.get_data_from_dword(dword)) + def set_word_at_offset(self, offset, word): + """Set the word value at the given file offset.""" + return self.set_bytes_at_offset(offset, self.get_data_from_word(word)) ## - # Word get / set + # Double-Word get / set ## - def get_data_from_word(self, word): - """Return a two byte string representing the word value. (little endian).""" - return struct.pack(" len(data): + if (offset + 1) * 4 > len(data): return None - return struct.unpack(" len(self.__data__): + if offset + 4 > len(self.__data__): return None - return self.get_word_from_data(self.__data__[offset : offset + 2], 0) + return self.get_dword_from_data(self.__data__[offset : offset + 4], 0) - def set_word_at_rva(self, rva, word): - """Set the word value at the file offset corresponding to the given RVA.""" - return self.set_bytes_at_rva(rva, self.get_data_from_word(word)) + def set_dword_at_rva(self, rva, dword): + """Set the double word value at the file offset corresponding to the given RVA.""" + return self.set_bytes_at_rva(rva, self.get_data_from_dword(dword)) - def set_word_at_offset(self, offset, word): - """Set the word value at the given file offset.""" - return self.set_bytes_at_offset(offset, self.get_data_from_word(word)) + def set_dword_at_offset(self, offset, dword): + """Set the double word value at the given file offset.""" + return self.set_bytes_at_offset(offset, self.get_data_from_dword(dword)) ## # Quad-Word get / set @@ -7418,7 +7418,7 @@ def get_qword_at_rva(self, rva): return None def get_qword_from_offset(self, offset): - """Return the quad-word value at the given file offset. (little endian)""" + """Return the quad-word value at the given file offset. (little endian).""" if offset + 8 > len(self.__data__): return None From c0bbcf3ea7e088c57f87b9a1e9a0aa7fd2188980 Mon Sep 17 00:00:00 2001 From: j-t-1 <120829237+j-t-1@users.noreply.github.com> Date: Thu, 2 Jul 2026 11:10:18 +0000 Subject: [PATCH 2/3] Move functions for consistency Moved three functions at the start to more logical positions. Put the word, double-word, quad-word get/set methods in size order. Ordered format characters to be the same as the documentation. https://docs.python.org/3/library/struct.html#format-characters --- pefile.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pefile.py b/pefile.py index be248ad0..04cb0b34 100644 --- a/pefile.py +++ b/pefile.py @@ -2317,11 +2317,11 @@ def cache_adjust_SectionAlignment(val, section_alignment, file_alignment): # 0x200 is the minimum valid FileAlignment according to the documentation # although ntoskrnl.exe has an alignment of 0x80 in some Windows versions # - # elif section_alignment < 0x80: + # if section_alignment < 0x80: # section_alignment = 0x80 if section_alignment and val % section_alignment: - return section_alignment * (val // section_alignment) + return (val // section_alignment) * section_alignment return val From 39d033cf2f32318c627ddfe95a97366ac9348d06 Mon Sep 17 00:00:00 2001 From: j-t-1 <120829237+j-t-1@users.noreply.github.com> Date: Thu, 2 Jul 2026 11:13:00 +0000 Subject: [PATCH 3/3] Move functions for consistency Moved three functions at the start to more logical positions. Put the word, double-word, quad-word get/set methods in size order. Ordered format characters to be the same as the documentation. https://docs.python.org/3/library/struct.html#format-characters --- pefile.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pefile.py b/pefile.py index 04cb0b34..f6a396a7 100644 --- a/pefile.py +++ b/pefile.py @@ -7309,7 +7309,7 @@ def get_word_at_rva(self, rva): return None def get_word_from_offset(self, offset): - """Return the word value at the given file offset. (little endian)""" + """Return the word value at the given file offset (little endian)""" if offset + 2 > len(self.__data__): return None @@ -7409,7 +7409,7 @@ def get_qword_at_rva(self, rva): return None def get_qword_from_offset(self, offset): - """Return the quad-word value at the given file offset. (little endian).""" + """Return the quad-word value at the given file offset (little endian).""" if offset + 8 > len(self.__data__): return None