def parse_sections(self, offset):
        """Fetch the PE file sections.

        The sections will be readily available in the "sections" attribute.
        Its attributes will contain all the section information plus "data"
        a buffer containing the section's data.

        The "Characteristics" member will be processed and attributes
        representing the section characteristics (with the 'IMAGE_SCN_'
        string trimmed from the constant's names) will be added to the
        section instance.

        Refer to the SectionStructure class for additional info.
        """

        self.sections = []
        MAX_SIMULTANEOUS_ERRORS = 3
        for i in range(self.FILE_HEADER.NumberOfSections):
            if i >= MAX_SECTIONS:
                self.__warnings.append(
                    "Too many sections {0} (>={1})".format(
                        self.FILE_HEADER.NumberOfSections, MAX_SECTIONS
                    )
                )
                break
            simultaneous_errors = 0
            section = SectionStructure(self.__IMAGE_SECTION_HEADER_format__, pe=self)
            if not section:
                break
            section_offset = offset + section.sizeof() * i
            section.set_file_offset(section_offset)
            section_data = self.__data__[
                section_offset : section_offset + section.sizeof()
            ]
            # Check if the section is all nulls and stop if so.
            if count_zeroes(section_data) == section.sizeof():
                self.__warnings.append(f"Invalid section {i}. Contents are null-bytes.")
                break
            if not section_data:
                self.__warnings.append(
                    f"Invalid section {i}. No data in the file (is this corkami's "
                    "virtsectblXP?)."
                )
                break
            section.__unpack__(section_data)
            self.__structures__.append(section)

            if section.SizeOfRawData + section.PointerToRawData > len(self.__data__):
                simultaneous_errors += 1
                self.__warnings.append(
                    f"Error parsing section {i}. SizeOfRawData is larger than file."
                )

            if self.adjust_PointerToRawData(section.PointerToRawData) > len(
                self.__data__
            ):
                simultaneous_errors += 1
                self.__warnings.append(
                    f"Error parsing section {i}. PointerToRawData points beyond "
                    "the end of the file."
                )

            if section.Misc_VirtualSize > 0x10000000:
                simultaneous_errors += 1
                self.__warnings.append(
                    f"Suspicious value found parsing section {i}. VirtualSize is "
                    "extremely large > 256MiB."
                )

            if (
                self.adjust_SectionAlignment(
                    section.VirtualAddress,
                    self.OPTIONAL_HEADER.SectionAlignment,
                    self.OPTIONAL_HEADER.FileAlignment,
                )
                > 0x10000000
            ):
                simultaneous_errors += 1
                self.__warnings.append(
                    f"Suspicious value found parsing section {i}. VirtualAddress is "
                    "beyond 0x10000000."
                )

            if (
                self.OPTIONAL_HEADER.FileAlignment != 0
                and (section.PointerToRawData % self.OPTIONAL_HEADER.FileAlignment) != 0
            ):
                simultaneous_errors += 1
                self.__warnings.append(
                    (
                        f"Error parsing section {i}. "
                        "PointerToRawData should normally be "
                        "a multiple of FileAlignment, this might imply the file "
                        "is trying to confuse tools which parse this incorrectly."
                    )
                )

            if simultaneous_errors >= MAX_SIMULTANEOUS_ERRORS:
                self.__warnings.append("Too many warnings parsing section. Aborting.")
                break

            section_flags = retrieve_flags(SECTION_CHARACTERISTICS, "IMAGE_SCN_")

            # Set the section's flags according to the Characteristics member
            set_flags(section, section.Characteristics, section_flags)

            if section.__dict__.get(
                "IMAGE_SCN_MEM_WRITE", False
            ) and section.__dict__.get("IMAGE_SCN_MEM_EXECUTE", False):
                if section.Name.rstrip(b"\x00") == b"PAGE" and self.is_driver():
                    # Drivers can have a PAGE section with those flags set without
                    # implying that it is malicious
                    pass
                else:
                    self.__warnings.append(
                        f"Suspicious flags set for section {i}. "
                        "Both IMAGE_SCN_MEM_WRITE and IMAGE_SCN_MEM_EXECUTE are set. "
                        "This might indicate a packed executable."
                    )

            self.sections.append(section)

        # Sort the sections by their VirtualAddress and add a field to each of them
        # with the VirtualAddress of the next section. This will allow to check
        # for potentially overlapping sections in badly constructed PEs.
        self.sections.sort(key=lambda a: a.VirtualAddress)
        for idx, section in enumerate(self.sections):
            if idx == len(self.sections) - 1:
                section.next_section_virtual_address = None
            else:
                section.next_section_virtual_address = self.sections[
                    idx + 1
                ].VirtualAddress

        if self.FILE_HEADER.NumberOfSections > 0 and self.sections:
            return (
                offset + self.sections[0].sizeof() * self.FILE_HEADER.NumberOfSections
            )
        else:
            return offset
Fetch the PE file sections.

        The sections will be readily available in the "sections" attribute.
        Its attributes will contain all the section information plus "data"
        a buffer containing the section's data.

        The "Characteristics" member will be processed and attributes
        representing the section characteristics (with the 'IMAGE_SCN_'
        string trimmed from the constant's names) will be added to the
        section instance.

        Refer to the SectionStructure class for additional info.
        
pefile.py