# Buggy code
def _args_from_vars(self, variables):
    """


    :param list variables:
    :return:
    """

    args = set()
    if not self.project.arch.call_pushes_ret:
        ret_addr_offset = 0
    else:
        ret_addr_offset = self.project.arch.bytes

    for variable in variables:
        if isinstance(variable, SimStackVariable):
            # a stack variable. convert it to a stack argument.
            # TODO: deal with the variable base
            if variable.offset <= 0:
                # skip the return address on the stack
                # TODO: make sure it was the return address
                continue
            arg = SimStackArg(variable.offset - ret_addr_offset, variable.size)
            args.add(arg)
        elif isinstance(variable, SimRegisterVariable):
            # a register variable, convert it to a register argument
            if not self._is_sane_register_variable(variable):
                continue
            reg_name = self.project.arch.translate_register_name(
                variable.reg, size=variable.size
            )
            arg = SimRegArg(reg_name, variable.size)
            args.add(arg)
        else:
            l.error("Unsupported type of variable %s.", type(variable))

    return args


# Traceback (AttributeError)
Traceback (most recent call last):
File "/home/dnivra/angr-dev/angr-management/angrmanagement/ui/main_window.py", line 496, in decompile_current_function
self.workspace.decompile_current_function()
File "/home/dnivra/angr-dev/angr-management/angrmanagement/ui/workspace.py", line 265, in decompile_current_function
view.decompile_current_function()
File "/home/dnivra/angr-dev/angr-management/angrmanagement/ui/views/disassembly_view.py", line 382, in decompile_current_function
self.workspace.decompile_function(self._current_function.am_obj)
File "/home/dnivra/angr-dev/angr-management/angrmanagement/ui/workspace.py", line 279, in decompile_function
view.function = func
File "/home/dnivra/angr-dev/angr-management/angrmanagement/ui/views/code_view.py", line 66, in function
self.decompile()
File "/home/dnivra/angr-dev/angr-management/angrmanagement/ui/views/code_view.py", line 43, in decompile
d = self.workspace.instance.project.analyses.Decompiler(
File "/home/dnivra/angr-dev/angr/angr/analyses/analysis.py", line 115, in __call__
oself.__init__(*args, **kwargs)
File "/home/dnivra/angr-dev/angr/angr/analyses/decompiler/decompiler.py", line 24, in __init__
self._decompile()
File "/home/dnivra/angr-dev/angr/angr/analyses/decompiler/decompiler.py", line 41, in _decompile
clinic = self.project.analyses.Clinic(self.func,
File "/home/dnivra/angr-dev/angr/angr/analyses/analysis.py", line 115, in __call__
oself.__init__(*args, **kwargs)
File "/home/dnivra/angr-dev/angr/angr/analyses/decompiler/clinic.py", line 70, in __init__
self._analyze()
File "/home/dnivra/angr-dev/angr/angr/analyses/decompiler/clinic.py", line 138, in _analyze
ail_graph = self._make_returns(ail_graph)
File "/home/dnivra/angr-dev/angr/angr/utils/timing.py", line 28, in timed_func
return func(*args, **kwargs)
File "/home/dnivra/angr-dev/angr/angr/analyses/decompiler/clinic.py", line 457, in _make_returns
AILGraphWalker(ail_graph, _handler, replace_nodes=True).walk()
File "/home/dnivra/angr-dev/angr/angr/analyses/decompiler/ailgraph_walker.py", line 23, in walk
r = self.handler(node)
File "/home/dnivra/angr-dev/angr/angr/analyses/decompiler/clinic.py", line 453, in _handler
walker.walk(block)
File "/home/dnivra/angr-dev/angr/angr/analyses/decompiler/ailblock_walker.py", line 37, in walk
self._handle_stmt(i, stmt, block)
File "/home/dnivra/angr-dev/angr/angr/analyses/decompiler/ailblock_walker.py", line 50, in _handle_stmt
return handler(stmt_idx, stmt, block)
File "/home/dnivra/angr-dev/angr/angr/analyses/decompiler/clinic.py", line 434, in _handle_Return
and self.function.calling_convention.ret_val is not None:
AttributeError: 'NoneType' object has no attribute 'ret_val'

# Fixed code
def _args_from_vars(self, variables: List, var_manager):
    """
    Derive function arguments from input variables.

    :param variables:
    :param var_manager: The variable manager of this function.
    :return:
    """

    args = set()
    if not self.project.arch.call_pushes_ret:
        ret_addr_offset = 0
    else:
        ret_addr_offset = self.project.arch.bytes

    reg_vars_with_single_access: List[SimRegisterVariable] = []

    for variable in variables:
        if isinstance(variable, SimStackVariable):
            # a stack variable. convert it to a stack argument.
            # TODO: deal with the variable base
            if variable.offset <= 0:
                # skip the return address on the stack
                # TODO: make sure it was the return address
                continue
            arg = SimStackArg(variable.offset - ret_addr_offset, variable.size)
            args.add(arg)
        elif isinstance(variable, SimRegisterVariable):
            # a register variable, convert it to a register argument
            if not self._is_sane_register_variable(variable):
                continue
            reg_name = self.project.arch.translate_register_name(
                variable.reg, size=variable.size
            )
            arg = SimRegArg(reg_name, variable.size)
            args.add(arg)

            accesses = var_manager.get_variable_accesses(variable)
            if len(accesses) == 1:
                reg_vars_with_single_access.append(variable)
        else:
            l.error("Unsupported type of variable %s.", type(variable))

    # the function might be saving registers at the beginning and restoring them at the end
    # we should remove all registers that are strictly callee-saved and are not used anywhere in this function
    end_blocks = [
        (endpoint.addr, endpoint.size)
        for endpoint in self._function.endpoints_with_type["return"]
    ]

    restored_reg_vars: Set[SimRegArg] = set()

    # is there any instruction that restores this register in any end blocks?
    if reg_vars_with_single_access:
        if self._function.returning is False:
            # no restoring is required if this function does not return
            for var_ in reg_vars_with_single_access:
                reg_name = self.project.arch.translate_register_name(
                    var_.reg, size=var_.size
                )
                restored_reg_vars.add(SimRegArg(reg_name, var_.size))

        else:
            reg_offsets: Set[int] = set(r.reg for r in reg_vars_with_single_access)
            for var_ in var_manager.get_variables(sort="reg"):
                if var_.reg in reg_offsets:
                    # check if there is only a write to it
                    accesses = var_manager.get_variable_accesses(var_)
                    if len(accesses) == 1 and accesses[0].access_type == "write":
                        found = False
                        for end_block_addr, end_block_size in end_blocks:
                            if (
                                end_block_addr
                                <= accesses[0].location.ins_addr
                                < end_block_addr + end_block_size
                            ):
                                found = True
                                break

                        if found:
                            reg_name = self.project.arch.translate_register_name(
                                var_.reg, size=var_.size
                            )
                            restored_reg_vars.add(SimRegArg(reg_name, var_.size))

    return args.difference(restored_reg_vars)