-
Notifications
You must be signed in to change notification settings - Fork 979
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
180 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
""" | ||
Module detecting incorrect operator usage for exponentiation where bitwise xor '^' is used instead of '**' | ||
""" | ||
from typing import Tuple, List, Union | ||
|
||
from slither.core.cfg.node import Node | ||
from slither.core.declarations import Contract, Function | ||
from slither.detectors.abstract_detector import ( | ||
AbstractDetector, | ||
DetectorClassification, | ||
DETECTOR_INFO, | ||
) | ||
from slither.slithir.operations import Binary, BinaryType, Operation | ||
from slither.slithir.utils.utils import RVALUE | ||
from slither.slithir.variables.constant import Constant | ||
from slither.utils.output import Output | ||
|
||
|
||
def _is_constant_candidate(var: Union[RVALUE, Function]) -> bool: | ||
""" | ||
Check if the variable is a constant. | ||
Do not consider variable that are expressed with hexadecimal. | ||
Something like 2^0xf is likely to be a correct bitwise operator | ||
:param var: | ||
:return: | ||
""" | ||
return isinstance(var, Constant) and not var.original_value.startswith("0x") | ||
|
||
|
||
def _is_bitwise_xor_on_constant(ir: Operation) -> bool: | ||
return ( | ||
isinstance(ir, Binary) | ||
and ir.type == BinaryType.CARET | ||
and (_is_constant_candidate(ir.variable_left) or _is_constant_candidate(ir.variable_right)) | ||
) | ||
|
||
|
||
def _detect_incorrect_operator(contract: Contract) -> List[Tuple[Function, Node]]: | ||
ret: List[Tuple[Function, Node]] = [] | ||
f: Function | ||
for f in contract.functions + contract.modifiers: # type:ignore | ||
# Heuristic: look for binary expressions with ^ operator where at least one of the operands is a constant, and | ||
# the constant is not in hex, because hex typically is used with bitwise xor and not exponentiation | ||
nodes = [node for node in f.nodes for ir in node.irs if _is_bitwise_xor_on_constant(ir)] | ||
for node in nodes: | ||
ret.append((f, node)) | ||
return ret | ||
|
||
|
||
# pylint: disable=too-few-public-methods | ||
class IncorrectOperatorExponentiation(AbstractDetector): | ||
""" | ||
Incorrect operator usage of bitwise xor mistaking it for exponentiation | ||
""" | ||
|
||
ARGUMENT = "incorrect-exp" | ||
HELP = "Incorrect exponentiation" | ||
IMPACT = DetectorClassification.HIGH | ||
CONFIDENCE = DetectorClassification.MEDIUM | ||
|
||
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-exponentiation" | ||
|
||
WIKI_TITLE = "Incorrect exponentiation" | ||
WIKI_DESCRIPTION = "Detect use of bitwise `xor ^` instead of exponential `**`" | ||
WIKI_EXPLOIT_SCENARIO = """ | ||
```solidity | ||
contract Bug{ | ||
uint UINT_MAX = 2^256 - 1; | ||
... | ||
} | ||
``` | ||
Alice deploys a contract in which `UINT_MAX` incorrectly uses `^` operator instead of `**` for exponentiation""" | ||
|
||
WIKI_RECOMMENDATION = "Use the correct operator `**` for exponentiation." | ||
|
||
def _detect(self) -> List[Output]: | ||
"""Detect the incorrect operator usage for exponentiation where bitwise xor ^ is used instead of ** | ||
Returns: | ||
list: (function, node) | ||
""" | ||
results: List[Output] = [] | ||
for c in self.compilation_unit.contracts_derived: | ||
res = _detect_incorrect_operator(c) | ||
for (func, node) in res: | ||
info: DETECTOR_INFO = [ | ||
func, | ||
" has bitwise-xor operator ^ instead of the exponentiation operator **: \n", | ||
] | ||
info += ["\t - ", node, "\n"] | ||
results.append(self.generate_result(info)) | ||
|
||
return results |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
from typing import List | ||
from slither.detectors.abstract_detector import ( | ||
AbstractDetector, | ||
DetectorClassification, | ||
DETECTOR_INFO, | ||
) | ||
from slither.slithir.operations import ( | ||
Binary, | ||
BinaryType, | ||
) | ||
|
||
from slither.core.declarations import Function | ||
from slither.utils.output import Output | ||
|
||
|
||
class TautologicalCompare(AbstractDetector): | ||
""" | ||
Same variable comparison detector | ||
""" | ||
|
||
ARGUMENT = "tautological-compare" | ||
HELP = "Comparing a variable to itself always returns true or false, depending on comparison" | ||
IMPACT = DetectorClassification.MEDIUM | ||
CONFIDENCE = DetectorClassification.HIGH | ||
|
||
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#tautological-compare" | ||
|
||
WIKI_TITLE = "Tautological compare" | ||
WIKI_DESCRIPTION = "A variable compared to itself is probably an error as it will always return `true` for `==`, `>=`, `<=` and always `false` for `<`, `>` and `!=`." | ||
WIKI_EXPLOIT_SCENARIO = """ | ||
```solidity | ||
function check(uint a) external returns(bool){ | ||
return (a >= a); | ||
} | ||
``` | ||
`check` always return true.""" | ||
|
||
WIKI_RECOMMENDATION = "Remove comparison or compare to different value." | ||
|
||
def _check_function(self, f: Function) -> List[Output]: | ||
affected_nodes = set() | ||
for node in f.nodes: | ||
for ir in node.irs: | ||
if isinstance(ir, Binary): | ||
if ir.type in [ | ||
BinaryType.GREATER, | ||
BinaryType.GREATER_EQUAL, | ||
BinaryType.LESS, | ||
BinaryType.LESS_EQUAL, | ||
BinaryType.EQUAL, | ||
BinaryType.NOT_EQUAL, | ||
]: | ||
if ir.variable_left == ir.variable_right: | ||
affected_nodes.add(node) | ||
|
||
results = [] | ||
for n in affected_nodes: | ||
info: DETECTOR_INFO = [f, " compares a variable to itself:\n\t", n, "\n"] | ||
res = self.generate_result(info) | ||
results.append(res) | ||
return results | ||
|
||
def _detect(self): | ||
results = [] | ||
|
||
for f in self.compilation_unit.functions_and_modifiers: | ||
results.extend(self._check_function(f)) | ||
|
||
return results |
6 changes: 6 additions & 0 deletions
6
tests/e2e/detectors/test_data/tautological-compare/0.8.20/compare.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
|
||
contract A{ | ||
function check(uint a) external returns(bool){ | ||
return (a >= a); | ||
} | ||
} |
Binary file added
BIN
+1.98 KB
tests/e2e/detectors/test_data/tautological-compare/0.8.20/compare.sol-0.8.20.zip
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters