diff --git a/contract_wasm_interface_parser/__init__.py b/contract_wasm_interface_parser/__init__.py index af05e1a..c6cdcf7 100644 --- a/contract_wasm_interface_parser/__init__.py +++ b/contract_wasm_interface_parser/__init__.py @@ -42,7 +42,13 @@ def parse_contract_metadata(wasm: Union[bytes, str]) -> ContractMetaData: return metadata -def leb128_decode(data, offset): +def leb128_decode(data: bytes, offset: int) -> Tuple[int, int]: + """Decode a Little Endian Base 128 encoded integer. + + :param data: The data to decode. + :param offset: The offset to start decoding. + :return: The decoded integer and the number of bytes read. + """ result = 0 shift = 0 size = 0 @@ -56,34 +62,46 @@ def leb128_decode(data, offset): def get_custom_sections(wasm_data: bytes) -> List[Tuple[str, bytes]]: + """Get the custom sections from the given WebAssembly data. + + :param wasm_data: The WebAssembly data. + :return: The custom sections as a list of tuples containing the name and content. + """ + assert wasm_data[:4] == b"\x00asm", "Invalid WebAssembly magic number" offset = 8 # Skip past the magic number and version custom_sections = [] while offset < len(wasm_data): - section_id, size_leb = leb128_decode(wasm_data, offset) - offset += size_leb - section_size, size_leb_size = leb128_decode(wasm_data, offset) - offset += size_leb_size + section_id, section_id_size = leb128_decode(wasm_data, offset) + offset += section_id_size + section_len, section_len_size = leb128_decode(wasm_data, offset) + offset += section_len_size if section_id == 0: # Custom Section - name_len, size_name_len = leb128_decode(wasm_data, offset) - offset += size_name_len + name_len, size_name_size = leb128_decode(wasm_data, offset) + offset += size_name_size name = wasm_data[offset : offset + name_len].decode("utf-8") offset += name_len content = wasm_data[ - offset : offset + section_size - size_name_len - name_len + offset : offset + section_len - size_name_size - name_len ] - offset += section_size - size_name_len - name_len + offset += section_len - size_name_size - name_len custom_sections.append((name, content)) else: - offset += section_size + offset += section_len return custom_sections def parse_entries( data: bytes, cls: Type[SCEnvMetaEntry | SCMetaEntry | SCSpecEntry] ) -> List[SCEnvMetaEntry | SCMetaEntry | SCSpecEntry]: + """Parse a list of entries from the given data. + + :param data: The data to parse. + :param cls: The class to use for parsing. + :return: The parsed entries. + """ entries = [] offset = 0 while offset < len(data):