Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix regression that caused retdata to be flagged #2029

Merged
merged 1 commit into from
Jul 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,15 +1,24 @@
"""
Module detecting unused return values from low level
"""
from slither.detectors.abstract_detector import DetectorClassification
from slither.detectors.operations.unused_return_values import UnusedReturnValues
from typing import List

from slither.core.cfg.node import Node
from slither.slithir.operations import LowLevelCall
from slither.slithir.operations.operation import Operation

from slither.core.declarations.function_contract import FunctionContract
from slither.core.variables.state_variable import StateVariable
from slither.detectors.abstract_detector import (
AbstractDetector,
DetectorClassification,
DETECTOR_INFO,
)
from slither.utils.output import Output


class UncheckedLowLevel(UnusedReturnValues):
class UncheckedLowLevel(AbstractDetector):
"""
If the return value of a send is not checked, it might lead to losing ether
If the return value of a low-level call is not checked, it might lead to losing ether
"""

ARGUMENT = "unchecked-lowlevel"
Expand Down Expand Up @@ -38,5 +47,44 @@ class UncheckedLowLevel(UnusedReturnValues):

WIKI_RECOMMENDATION = "Ensure that the return value of a low-level call is checked or logged."

def _is_instance(self, ir: Operation) -> bool: # pylint: disable=no-self-use
return isinstance(ir, LowLevelCall)
@staticmethod
def detect_unused_return_values(f: FunctionContract) -> List[Node]:
"""
Return the nodes where the return value of a call is unused
Args:
f (Function)
Returns:
list(Node)
"""
values_returned = []
nodes_origin = {}
for n in f.nodes:
for ir in n.irs:
if isinstance(ir, LowLevelCall):
# if a return value is stored in a state variable, it's ok
if ir.lvalue and not isinstance(ir.lvalue, StateVariable):
values_returned.append(ir.lvalue)
nodes_origin[ir.lvalue] = ir

for read in ir.read:
if read in values_returned:
values_returned.remove(read)

return [nodes_origin[value].node for value in values_returned]

def _detect(self) -> List[Output]:
"""Detect low level calls where the success value is not checked"""
results = []
for c in self.compilation_unit.contracts_derived:
for f in c.functions_and_modifiers:
unused_return = UncheckedLowLevel.detect_unused_return_values(f)
if unused_return:

for node in unused_return:
info: DETECTOR_INFO = [f, " ignores return value by ", node, "\n"]

res = self.generate_result(info)

results.append(res)

return results
6 changes: 2 additions & 4 deletions slither/detectors/operations/unused_return_values.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,8 @@ def detect_unused_return_values(
def _detect(self) -> List[Output]:
"""Detect high level calls which return a value that are never used"""
results = []
for c in self.compilation_unit.contracts:
for f in c.functions + c.modifiers:
if f.contract_declarer != c:
continue
for c in self.compilation_unit.contracts_derived:
for f in c.functions_and_modifiers:
unused_return = self.detect_unused_return_values(f)
if unused_return:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,14 @@ contract MyConc{
}

function good(address payable dst) external payable{
(bool ret, bytes memory _) = dst.call{value:msg.value}("");
(bool ret, ) = dst.call{value:msg.value}("");
require(ret);
}

function good2(address payable dst) external payable{
(bool ret, ) = dst.call{value:msg.value}("");
if (!ret) {
revert();
}
}
}
Binary file not shown.