Repository: mandiant/capa
File: capa/features/extractors/dnfile/helpers.py (Python)

Code before:
        else:
            module = impl_map.ImportScope.row.Name
        method: str = impl_map.ImportName

        member_forward_table: int
        if impl_map.MemberForwarded.table is None:
            logger.debug("ImplMap[0x%X] MemberForwarded table is None", rid)
            continue
        else:
            member_forward_table = impl_map.MemberForwarded.table.number
        member_forward_row: int = impl_map.MemberForwarded.row_index

        # ECMA says "Each row of the ImplMap table associates a row in the MethodDef table (MemberForwarded) with the
        # name of a routine (ImportName) in some unmanaged DLL (ImportScope)"; so we calculate and map the MemberForwarded
        # MethodDef table token to help us later record native import method calls made from CIL
        token: int = calculate_dotnet_token_value(member_forward_table, member_forward_row)

        # like Kernel32.dll
        if module and "." in module:
            module = module.split(".")[0]

        # like kernel32.CreateFileA
        yield DnUnmanagedMethod(token, module, method)


def get_dotnet_table_row(pe: dnfile.dnPE, table_index: int, row_index: int):
    assert pe.net is not None
    assert pe.net.mdtables is not None

    if row_index - 1 <= 0:
        return None

    try:
        table = pe.net.mdtables.tables.get(table_index, [])
        return table[row_index - 1]
    except IndexError:
        return None


def resolve_nested_typedef_name(
    nested_class_table: dict, index: int, typedef: dnfile.mdtable.TypeDefRow, pe: dnfile.dnPE
):
    """Resolves all nested TypeDef class names. Returns the namespace as a str and the nested TypeRef name as a tuple"""

    if index in nested_class_table:
        typedef_name = []
        name = typedef.TypeName

        # Append the current typedef name
        typedef_name.append(name)


Review comment (bug):
```suggestion
def get_dotnet_table_row(pe: dnfile.dnPE, table_index: int, row_index: int) -> Optional[dnfile.base.MDTableRow]:
```

Code after:
        else:
            module = impl_map.ImportScope.row.Name
        method: str = impl_map.ImportName

        member_forward_table: int
        if impl_map.MemberForwarded.table is None:
            logger.debug("ImplMap[0x%X] MemberForwarded table is None", rid)
            continue
        else:
            member_forward_table = impl_map.MemberForwarded.table.number
        member_forward_row: int = impl_map.MemberForwarded.row_index

        # ECMA says "Each row of the ImplMap table associates a row in the MethodDef table (MemberForwarded) with the
        # name of a routine (ImportName) in some unmanaged DLL (ImportScope)"; so we calculate and map the MemberForwarded
        # MethodDef table token to help us later record native import method calls made from CIL
        token: int = calculate_dotnet_token_value(member_forward_table, member_forward_row)

        # like Kernel32.dll
        if module and "." in module:
            module = module.split(".")[0]

        # like kernel32.CreateFileA
        yield DnUnmanagedMethod(token, module, method)


def get_dotnet_table_row(pe: dnfile.dnPE, table_index: int, row_index: int) -> Optional[dnfile.base.MDTableRow]:
    assert pe.net is not None
    assert pe.net.mdtables is not None

    if row_index - 1 <= 0:
        return None

    try:
        table = pe.net.mdtables.tables.get(table_index, [])
        return table[row_index - 1]
    except IndexError:
        return None


def resolve_nested_typedef_name(
    nested_class_table: dict, index: int, typedef: dnfile.mdtable.TypeDefRow, pe: dnfile.dnPE
) -> Tuple[str, Tuple[str, ...]]:
    """Resolves all nested TypeDef class names. Returns the namespace as a str and the nested TypeRef name as a tuple"""

    if index in nested_class_table:
        typedef_name = []
        name = typedef.TypeName

        # Append the current typedef name
        typedef_name.append(name)