def __parse__(self, fname, data, fast_load):
        """Parse a Portable Executable file.

        Loads a PE file, parsing all its structures and making them available
        through the instance's attributes.
        """

        if fname is not None:
            stat = os.stat(fname)
            if stat.st_size == 0:
                raise PEFormatError("The file is empty")
            fd = None
            try:
                fd = open(fname, "rb")
                self.fileno = fd.fileno()
                if hasattr(mmap, "MAP_PRIVATE"):
                    # Unix
                    self.__data__ = mmap.mmap(self.fileno, 0, mmap.MAP_PRIVATE)
                else:
                    # Windows
                    self.__data__ = mmap.mmap(self.fileno, 0, access=mmap.ACCESS_READ)
                self.__from_file = True
            except IOError as excp:
                exception_msg = "{0}".format(excp)
                exception_msg = exception_msg and (": %s" % exception_msg)
                raise Exception(
                    "Unable to access file '{0}'{1}".format(fname, exception_msg)
                )
            finally:
                if fd is not None:
                    fd.close()
        elif data is not None:
            self.__data__ = data
            self.__from_file = False

        # Resources should not overlap each other, so they should not exceed the
        # file size.
        self.__resource_size_limit_upperbounds = len(self.__data__)
        self.__resource_size_limit_reached = False

        if not fast_load:
            for byte, byte_count in Counter(bytearray(self.__data__)).items():
                # Only report the cases where a byte makes up for more than 50% (if
                # zero) or 15% (if non-zero) of the file's contents. There are
                # legitimate PEs where 0x00 bytes are close to 50% of the whole
                # file's contents.
                if (byte == 0 and byte_count / len(self.__data__) > 0.5) or (
                    byte != 0 and byte_count / len(self.__data__) > 0.15
                ):
                    self.__warnings.append(
                        (
                            "Byte 0x{0:02x} makes up {1:.4f}% of the file's contents."
                            " This may indicate truncation / malformation."
                        ).format(byte, 100.0 * byte_count / len(self.__data__))
                    )

        dos_header_data = self.__data__[:64]
        if len(dos_header_data) != 64:
            raise PEFormatError(
                "Unable to read the DOS Header, possibly a truncated file."
            )

        self.DOS_HEADER = self.__unpack_data__(
            self.__IMAGE_DOS_HEADER_format__, dos_header_data, file_offset=0
        )

        if self.DOS_HEADER.e_magic == IMAGE_DOSZM_SIGNATURE:
            raise PEFormatError("Probably a ZM Executable (not a PE file).")
        if not self.DOS_HEADER or self.DOS_HEADER.e_magic != IMAGE_DOS_SIGNATURE:
            raise PEFormatError("DOS Header magic not found.")

        # Check for sane value in e_lfanew
        #
        if self.DOS_HEADER.e_lfanew > len(self.__data__):
            raise PEFormatError("Invalid e_lfanew value, probably not a PE file")

        nt_headers_offset = self.DOS_HEADER.e_lfanew

        self.NT_HEADERS = self.__unpack_data__(
            self.__IMAGE_NT_HEADERS_format__,
            self.__data__[nt_headers_offset : nt_headers_offset + 8],
            file_offset=nt_headers_offset,
        )

        # We better check the signature right here, before the file screws
        # around with sections:
        # Some malware will cause the Signature value to not exist at all
        if not self.NT_HEADERS or not self.NT_HEADERS.Signature:
            raise PEFormatError("NT Headers not found.")

        if (0xFFFF & self.NT_HEADERS.Signature) == IMAGE_NE_SIGNATURE:
            raise PEFormatError("Invalid NT Headers signature. Probably a NE file")
        if (0xFFFF & self.NT_HEADERS.Signature) == IMAGE_LE_SIGNATURE:
            raise PEFormatError("Invalid NT Headers signature. Probably a LE file")
        if (0xFFFF & self.NT_HEADERS.Signature) == IMAGE_LX_SIGNATURE:
            raise PEFormatError("Invalid NT Headers signature. Probably a LX file")
        if (0xFFFF & self.NT_HEADERS.Signature) == IMAGE_TE_SIGNATURE:
            raise PEFormatError("Invalid NT Headers signature. Probably a TE file")
        if self.NT_HEADERS.Signature != IMAGE_NT_SIGNATURE:
            raise PEFormatError("Invalid NT Headers signature.")

        self.FILE_HEADER = self.__unpack_data__(
            self.__IMAGE_FILE_HEADER_format__,
            self.__data__[nt_headers_offset + 4 : nt_headers_offset + 4 + 32],
            file_offset=nt_headers_offset + 4,
        )
        image_flags = retrieve_flags(IMAGE_CHARACTERISTICS, "IMAGE_FILE_")

        if not self.FILE_HEADER:
            raise PEFormatError("File Header missing")

        # Set the image's flags according to the Characteristics member
        set_flags(self.FILE_HEADER, self.FILE_HEADER.Characteristics, image_flags)

        optional_header_offset = nt_headers_offset + 4 + self.FILE_HEADER.sizeof()

        # Note: location of sections can be controlled from PE header:
        sections_offset = optional_header_offset + self.FILE_HEADER.SizeOfOptionalHeader

        self.OPTIONAL_HEADER = self.__unpack_data__(
            self.__IMAGE_OPTIONAL_HEADER_format__,
            # Read up to 256 bytes to allow creating a copy of too much data
            self.__data__[optional_header_offset : optional_header_offset + 256],
            file_offset=optional_header_offset,
        )

        # According to solardesigner's findings for his
        # Tiny PE project, the optional header does not
        # need fields beyond "Subsystem" in order to be
        # loadable by the Windows loader (given that zeros
        # are acceptable values and the header is loaded
        # in a zeroed memory page)
        # If trying to parse a full Optional Header fails
        # we try to parse it again with some 0 padding
        #
        MINIMUM_VALID_OPTIONAL_HEADER_RAW_SIZE = 69

        if (
            self.OPTIONAL_HEADER is None
            and len(
                self.__data__[optional_header_offset : optional_header_offset + 0x200]
            )
            >= MINIMUM_VALID_OPTIONAL_HEADER_RAW_SIZE
        ):
            # Add enough zeros to make up for the unused fields
            #
            padding_length = 128

            # Create padding
            #
            padded_data = self.__data__[
                optional_header_offset : optional_header_offset + 0x200
            ] + (b"\0" * padding_length)

            self.OPTIONAL_HEADER = self.__unpack_data__(
                self.__IMAGE_OPTIONAL_HEADER_format__,
                padded_data,
                file_offset=optional_header_offset,
            )

        # Check the Magic in the OPTIONAL_HEADER and set the PE file
        # type accordingly
        #
        if self.OPTIONAL_HEADER is not None:
            if self.OPTIONAL_HEADER.Magic == OPTIONAL_HEADER_MAGIC_PE:
                self.PE_TYPE = OPTIONAL_HEADER_MAGIC_PE

            elif self.OPTIONAL_HEADER.Magic == OPTIONAL_HEADER_MAGIC_PE_PLUS:
                self.PE_TYPE = OPTIONAL_HEADER_MAGIC_PE_PLUS

                self.OPTIONAL_HEADER = self.__unpack_data__(
                    self.__IMAGE_OPTIONAL_HEADER64_format__,
                    self.__data__[
                        optional_header_offset : optional_header_offset + 0x200
                    ],
                    file_offset=optional_header_offset,
                )

                # Again, as explained above, we try to parse
                # a reduced form of the Optional Header which
                # is still valid despite not including all
                # structure members
                #
                MINIMUM_VALID_OPTIONAL_HEADER_RAW_SIZE = 69 + 4

                if (
                    self.OPTIONAL_HEADER is None
                    and len(
                        self.__data__[
                            optional_header_offset : optional_header_offset + 0x200
                        ]
                    )
                    >= MINIMUM_VALID_OPTIONAL_HEADER_RAW_SIZE
                ):
                    padding_length = 128
                    padded_data = self.__data__[
                        optional_header_offset : optional_header_offset + 0x200
                    ] + (b"\0" * padding_length)
                    self.OPTIONAL_HEADER = self.__unpack_data__(
                        self.__IMAGE_OPTIONAL_HEADER64_format__,
                        padded_data,
                        file_offset=optional_header_offset,
                    )

        if not self.FILE_HEADER:
            raise PEFormatError("File Header missing")

        # Die gracefully if there is no OPTIONAL_HEADER field
        # 975440f5ad5e2e4a92c4d9a5f22f75c1
        if self.OPTIONAL_HEADER is None:
            raise PEFormatError("No Optional Header found, invalid PE32 or PE32+ file.")
        if self.PE_TYPE is None:
            self.__warnings.append(
                "Invalid type 0x{0:04x} in Optional Header.".format(
                    self.OPTIONAL_HEADER.Magic
                )
            )

        dll_characteristics_flags = retrieve_flags(
            DLL_CHARACTERISTICS, "IMAGE_DLLCHARACTERISTICS_"
        )

        # Set the Dll Characteristics flags according to the DllCharacteristics member
        set_flags(
            self.OPTIONAL_HEADER,
            self.OPTIONAL_HEADER.DllCharacteristics,
            dll_characteristics_flags,
        )

        self.OPTIONAL_HEADER.DATA_DIRECTORY = []
        offset = optional_header_offset + self.OPTIONAL_HEADER.sizeof()

        self.NT_HEADERS.FILE_HEADER = self.FILE_HEADER
        self.NT_HEADERS.OPTIONAL_HEADER = self.OPTIONAL_HEADER

        # Windows 8 specific check
        #
        if (
            self.OPTIONAL_HEADER.AddressOfEntryPoint
            < self.OPTIONAL_HEADER.SizeOfHeaders
        ):
            self.__warnings.append(
                "SizeOfHeaders is smaller than AddressOfEntryPoint: this file "
                "cannot run under Windows 8."
            )

        # The NumberOfRvaAndSizes is sanitized to stay within
        # reasonable limits so can be casted to an int
        #
        if self.OPTIONAL_HEADER.NumberOfRvaAndSizes > 0x10:
            self.__warnings.append(
                "Suspicious NumberOfRvaAndSizes in the Optional Header. "
                "Normal values are never larger than 0x10, the value is: 0x%x"
                % self.OPTIONAL_HEADER.NumberOfRvaAndSizes
            )

        MAX_ASSUMED_VALID_NUMBER_OF_RVA_AND_SIZES = 0x100
        for i in range(int(0x7FFFFFFF & self.OPTIONAL_HEADER.NumberOfRvaAndSizes)):
            if len(self.__data__) - offset == 0:
                break

            if len(self.__data__) - offset < 8:
                data = self.__data__[offset:] + b"\0" * 8
            else:
                data = self.__data__[
                    offset : offset + MAX_ASSUMED_VALID_NUMBER_OF_RVA_AND_SIZES
                ]

            dir_entry = self.__unpack_data__(
                self.__IMAGE_DATA_DIRECTORY_format__, data, file_offset=offset
            )

            if dir_entry is None:
                break

            # Would fail if missing an entry
            # 1d4937b2fa4d84ad1bce0309857e70ca offending sample
            try:
                dir_entry.name = DIRECTORY_ENTRY[i]
            except (KeyError, AttributeError):
                break

            offset += dir_entry.sizeof()

            self.OPTIONAL_HEADER.DATA_DIRECTORY.append(dir_entry)

            # If the offset goes outside the optional header,
            # the loop is broken, regardless of how many directories
            # NumberOfRvaAndSizes says there are
            #
            # We assume a normally sized optional header, hence that we do
            # a sizeof() instead of reading SizeOfOptionalHeader.
            # Then we add a default number of directories times their size,
            # if we go beyond that, we assume the number of directories
            # is wrong and stop processing
            if offset >= (
                optional_header_offset + self.OPTIONAL_HEADER.sizeof() + 8 * 16
            ):
                break

        offset = self.parse_sections(sections_offset)

        # There could be a problem if there are no raw data sections
        # greater than 0
        # fc91013eb72529da005110a3403541b6 example
        # Should this throw an exception in the minimum header offset
        # can't be found?
        #
        rawDataPointers = [
            self.adjust_PointerToRawData(s.PointerToRawData)
            for s in self.sections
            if s.PointerToRawData > 0
        ]

        if len(rawDataPointers) > 0:
            lowest_section_offset = min(rawDataPointers)
        else:
            lowest_section_offset = None

        if not lowest_section_offset or lowest_section_offset < offset:
            self.header = self.__data__[:offset]
        else:
            self.header = self.__data__[:lowest_section_offset]

        # Check whether the entry point lies within a section
        #
        if (
            self.get_section_by_rva(self.OPTIONAL_HEADER.AddressOfEntryPoint)
            is not None
        ):
            # Check whether the entry point lies within the file
            #
            ep_offset = self.get_offset_from_rva(
                self.OPTIONAL_HEADER.AddressOfEntryPoint
            )
            if ep_offset > len(self.__data__):
                self.__warnings.append(
                    "Possibly corrupt file. AddressOfEntryPoint lies outside the"
                    " file. AddressOfEntryPoint: 0x%x"
                    % self.OPTIONAL_HEADER.AddressOfEntryPoint
                )

        else:
            self.__warnings.append(
                "AddressOfEntryPoint lies outside the sections' boundaries. "
                "AddressOfEntryPoint: 0x%x" % self.OPTIONAL_HEADER.AddressOfEntryPoint
            )

        if not fast_load:
            self.full_load()
Parse a Portable Executable file.

        Loads a PE file, parsing all its structures and making them available
        through the instance's attributes.
        
pefile.py