def _get_element_ptr_tuplelike(parent, key):
    typ = parent.typ
    assert isinstance(typ, TupleLike)

    if isinstance(typ, StructType):
        assert isinstance(key, str)
        subtype = typ.members[key]
        attrs = list(typ.tuple_keys())
        index = attrs.index(key)
        annotation = key
    else:
        assert isinstance(key, int)
        subtype = typ.members[key]
        attrs = list(range(len(typ.members)))
        index = key
        annotation = None

    # generated by empty() + make_setter
    if parent.value == "~empty":
        return IRnode.from_list("~empty", typ=subtype)

    if parent.value == "multi":
        assert parent.encoding != Encoding.ABI, "no abi-encoded literals"
        return parent.args[index]

    ofst = 0  # offset from parent start

    if parent.encoding in (Encoding.ABI, Encoding.JSON_ABI):
        if parent.location == STORAGE:
            raise CompilerPanic("storage variables should not be abi encoded")  # pragma: notest

        member_t = typ.members[attrs[index]]

        for i in range(index):
            member_abi_t = typ.members[attrs[i]].abi_type
            ofst += member_abi_t.embedded_static_size()

        return _getelemptr_abi_helper(parent, member_t, ofst)

    if parent.location.word_addressable:
        for i in range(index):
            ofst += typ.members[attrs[i]].storage_size_in_words
    elif parent.location.byte_addressable:
        for i in range(index):
            ofst += typ.members[attrs[i]].memory_bytes_required
    else:
        raise CompilerPanic(f"bad location {parent.location}")  # pragma: notest

    return IRnode.from_list(
        add_ofst(parent, ofst),
        typ=subtype,
        location=parent.location,
        encoding=parent.encoding,
        annotation=annotation,
    )
The software performs operations on a memory buffer, but it can read from or write to a memory location that is outside of the intended boundary of the buffer.