mirror of https://github.com/crytic/slither
Merge pull request #732 from crytic/dev-19-new-detectors
Open source 19 new bug detectorspull/733/head
commit
bb1c1fbbad
@ -0,0 +1,60 @@ |
||||
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification |
||||
from slither.slithir.operations import Binary, BinaryType |
||||
from slither.slithir.variables import Constant |
||||
|
||||
|
||||
class ShiftParameterMixup(AbstractDetector): |
||||
""" |
||||
Check for cases where a return(a,b) is used in an assembly function that also returns two variables |
||||
""" |
||||
|
||||
ARGUMENT = "incorrect-shift" |
||||
HELP = "The order of parameters in a shift instruction is incorrect." |
||||
IMPACT = DetectorClassification.HIGH |
||||
CONFIDENCE = DetectorClassification.HIGH |
||||
|
||||
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#shift-parameter-mixup" |
||||
|
||||
WIKI_TITLE = "Incorrect shift in assembly." |
||||
WIKI_DESCRIPTION = "Detect if the values in a shift operation are reversed" |
||||
WIKI_EXPLOIT_SCENARIO = """ |
||||
```solidity |
||||
contract C { |
||||
function f() internal returns (uint a) { |
||||
assembly { |
||||
a := shr(a, 8) |
||||
} |
||||
} |
||||
} |
||||
``` |
||||
The shift statement will right-shift the constant 8 by `a` bits""" |
||||
|
||||
WIKI_RECOMMENDATION = "Swap the order of parameters." |
||||
|
||||
def _check_function(self, f): |
||||
results = [] |
||||
|
||||
for node in f.nodes: |
||||
for ir in node.irs: |
||||
if isinstance(ir, Binary) and ir.type in [ |
||||
BinaryType.LEFT_SHIFT, |
||||
BinaryType.RIGHT_SHIFT, |
||||
]: |
||||
if isinstance(ir.variable_left, Constant): |
||||
info = [f, " contains an incorrect shift operation: ", node, "\n"] |
||||
json = self.generate_result(info) |
||||
|
||||
results.append(json) |
||||
return results |
||||
|
||||
def _detect(self): |
||||
results = [] |
||||
for c in self.contracts: |
||||
for f in c.functions: |
||||
if f.contract_declarer != c: |
||||
continue |
||||
|
||||
if f.contains_assembly: |
||||
results += self._check_function(f) |
||||
|
||||
return results |
@ -0,0 +1,138 @@ |
||||
""" |
||||
Module detecting unimplemented interfaces |
||||
|
||||
Collect all the interfaces |
||||
Check for contracts which implement all interface functions but do not explicitly derive from those interfaces. |
||||
""" |
||||
|
||||
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification |
||||
|
||||
|
||||
class MissingInheritance(AbstractDetector): |
||||
""" |
||||
Unimplemented interface detector |
||||
""" |
||||
|
||||
ARGUMENT = "missing-inheritance" |
||||
HELP = "Missing inheritance" |
||||
IMPACT = DetectorClassification.INFORMATIONAL |
||||
CONFIDENCE = DetectorClassification.HIGH |
||||
|
||||
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#missing-inheritance" |
||||
WIKI_TITLE = "Missing inheritance" |
||||
WIKI_DESCRIPTION = "Detect missing inheritance." |
||||
WIKI_EXPLOIT_SCENARIO = """ |
||||
```solidity |
||||
interface ISomething { |
||||
function f1() external returns(uint); |
||||
} |
||||
|
||||
contract Something { |
||||
function f1() external returns(uint){ |
||||
return 42; |
||||
} |
||||
} |
||||
``` |
||||
`Something` should inherit from `ISomething`. |
||||
""" |
||||
|
||||
WIKI_RECOMMENDATION = "Inherit from the missing interface or contract." |
||||
|
||||
@staticmethod |
||||
def detect_unimplemented_interface(contract, interfaces): |
||||
""" |
||||
Detects if contract intends to implement one of the interfaces but does not explicitly do so by deriving from it |
||||
:param contract: The contract to check |
||||
:param interfaces: List of all the interfaces |
||||
:return: Interfaces likely intended to implement by the contract |
||||
""" |
||||
|
||||
intended_interfaces = [] |
||||
sigs_contract = {f.full_name for f in contract.functions_entry_points} |
||||
|
||||
if not sigs_contract: |
||||
return intended_interfaces |
||||
|
||||
for interface in interfaces: |
||||
# If contract already inherits from interface, skip that interface |
||||
if interface in contract.inheritance: |
||||
continue |
||||
|
||||
sigs_interface = {f.full_name for f in interface.functions_entry_points} |
||||
|
||||
# Contract should implement all the functions of the intended interface |
||||
if not sigs_interface.issubset(sigs_contract): |
||||
continue |
||||
|
||||
# A parent contract inherited should not implement a superset of intended interface |
||||
# This is because in the following: |
||||
# interface ERC20_interface: |
||||
# - balanceOf(uint) -> uint |
||||
# - transfer(address, address) -> bool |
||||
# contract ForeignToken: |
||||
# - balanceOf(uint) -> uint |
||||
# contract MyERC20Implementation is ERC20_interface |
||||
# |
||||
# We do not want MyERC20Implementation to be declared as missing ForeignToken interface |
||||
intended_interface_is_subset_parent = False |
||||
for parent in contract.inheritance: |
||||
sigs_parent = {f.full_name for f in parent.functions_entry_points} |
||||
if sigs_interface.issubset(sigs_parent): |
||||
intended_interface_is_subset_parent = True |
||||
break |
||||
|
||||
if not intended_interface_is_subset_parent: |
||||
# Should not be a subset of an earlier determined intended_interface or derive from it |
||||
intended_interface_is_subset_intended = False |
||||
for intended_interface in intended_interfaces: |
||||
sigs_intended_interface = { |
||||
f.full_name for f in intended_interface.functions_entry_points |
||||
} |
||||
if ( |
||||
sigs_interface.issubset(sigs_intended_interface) |
||||
or interface in intended_interface.inheritance |
||||
): |
||||
intended_interface_is_subset_intended = True |
||||
break |
||||
|
||||
# If superset of an earlier determined intended_interface or derives from it, |
||||
# remove the intended_interface |
||||
if ( |
||||
sigs_intended_interface.issubset(sigs_interface) |
||||
or intended_interface in interface.inheritance |
||||
): |
||||
intended_interfaces.remove(intended_interface) |
||||
|
||||
if not intended_interface_is_subset_intended: |
||||
intended_interfaces.append(interface) |
||||
|
||||
return intended_interfaces |
||||
|
||||
def _detect(self): |
||||
"""Detect unimplemented interfaces |
||||
Returns: |
||||
list: {'contract'} |
||||
""" |
||||
|
||||
# Collect all the interfaces |
||||
# Here interface can be "interface" from solidity, or contracts with only functions declaration |
||||
# Skip interfaces without functions |
||||
interfaces = [ |
||||
contract |
||||
for contract in self.slither.contracts |
||||
if contract.is_signature_only() |
||||
and any(not f.is_constructor_variables for f in contract.functions) |
||||
] |
||||
|
||||
# Check derived contracts for missing interface implementations |
||||
results = [] |
||||
for contract in self.slither.contracts_derived: |
||||
# Skip interfaces |
||||
if contract in interfaces: |
||||
continue |
||||
intended_interfaces = self.detect_unimplemented_interface(contract, interfaces) |
||||
for interface in intended_interfaces: |
||||
info = [contract, " should inherit from ", interface, "\n"] |
||||
res = self.generate_result(info) |
||||
results.append(res) |
||||
return results |
@ -0,0 +1,160 @@ |
||||
""" |
||||
Detects the passing of arrays located in memory to functions which expect to modify arrays via storage reference. |
||||
""" |
||||
|
||||
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification |
||||
from slither.core.solidity_types.array_type import ArrayType |
||||
from slither.core.variables.state_variable import StateVariable |
||||
from slither.core.variables.local_variable import LocalVariable |
||||
from slither.slithir.operations.high_level_call import HighLevelCall |
||||
from slither.slithir.operations.internal_call import InternalCall |
||||
|
||||
|
||||
class ArrayByReference(AbstractDetector): |
||||
""" |
||||
Detects passing of arrays located in memory to functions which expect to modify arrays via storage reference. |
||||
""" |
||||
|
||||
ARGUMENT = "array-by-reference" |
||||
HELP = "Modifying storage array by value" |
||||
IMPACT = DetectorClassification.HIGH |
||||
CONFIDENCE = DetectorClassification.HIGH |
||||
|
||||
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#modifying-storage-array-by-value" |
||||
|
||||
WIKI_TITLE = "Modifying storage array by value" |
||||
WIKI_DESCRIPTION = ( |
||||
"Detect arrays passed to a function that expects reference to a storage array" |
||||
) |
||||
WIKI_EXPLOIT_SCENARIO = """ |
||||
```solidity |
||||
contract Memory { |
||||
uint[1] public x; // storage |
||||
|
||||
function f() public { |
||||
f1(x); // update x |
||||
f2(x); // do not update x |
||||
} |
||||
|
||||
function f1(uint[1] storage arr) internal { // by reference |
||||
arr[0] = 1; |
||||
} |
||||
|
||||
function f2(uint[1] arr) internal { // by value |
||||
arr[0] = 2; |
||||
} |
||||
} |
||||
``` |
||||
|
||||
Bob calls `f()`. Bob assumes that at the end of the call `x[0]` is 2, but it is 1. |
||||
As a result, Bob's usage of the contract is incorrect.""" |
||||
|
||||
WIKI_RECOMMENDATION = "Ensure the correct usage of `memory` and `storage` in the function parameters. Make all the locations explicit." |
||||
|
||||
@staticmethod |
||||
def get_funcs_modifying_array_params(contracts): |
||||
""" |
||||
Obtains a set of functions which take arrays not located in storage as parameters, and writes to them. |
||||
:param contracts: The collection of contracts to check functions in. |
||||
:return: A set of functions which take an array not located in storage as a parameter and writes to it. |
||||
""" |
||||
# Initialize our resulting set of functions which modify non-reference array parameters |
||||
results = set() |
||||
|
||||
# Loop through all functions in all contracts. |
||||
for contract in contracts: |
||||
for function in contract.functions_declared: |
||||
|
||||
# Skip any constructor functions. |
||||
if function.is_constructor: |
||||
continue |
||||
|
||||
# Determine if this function takes an array as a parameter and the location isn't storage. |
||||
# If it has been written to, we know this sets an non-storage-ref array. |
||||
for param in function.parameters: |
||||
if isinstance(param.type, ArrayType) and param.location != "storage": |
||||
if param in function.variables_written: |
||||
results.add(function) |
||||
break |
||||
|
||||
return results |
||||
|
||||
@staticmethod |
||||
def detect_calls_passing_ref_to_function(contracts, array_modifying_funcs): |
||||
""" |
||||
Obtains all calls passing storage arrays by value to a function which cannot write to them successfully. |
||||
:param contracts: The collection of contracts to check for problematic calls in. |
||||
:param array_modifying_funcs: The collection of functions which take non-storage arrays as input and writes to |
||||
them. |
||||
:return: A list of tuples (calling_node, affected_argument, invoked_function) which denote all problematic |
||||
nodes invoking a function with some storage array argument where the invoked function seemingly attempts to |
||||
write to the array unsuccessfully. |
||||
""" |
||||
# Define our resulting array. |
||||
results = [] |
||||
|
||||
# Verify we have functions in our list to check for. |
||||
if not array_modifying_funcs: |
||||
return results |
||||
|
||||
# Loop for each node in each function/modifier in each contract |
||||
# pylint: disable=too-many-nested-blocks |
||||
for contract in contracts: |
||||
for function in contract.functions_and_modifiers_declared: |
||||
for node in function.nodes: |
||||
|
||||
# If this node has no expression, skip it. |
||||
if not node.expression: |
||||
continue |
||||
|
||||
for ir in node.irs: |
||||
# Verify this is a high level call. |
||||
if not isinstance(ir, (HighLevelCall, InternalCall)): |
||||
continue |
||||
|
||||
# Verify this references a function in our array modifying functions collection. |
||||
if ir.function not in array_modifying_funcs: |
||||
continue |
||||
|
||||
# Verify one of these parameters is an array in storage. |
||||
for arg in ir.arguments: |
||||
# Verify this argument is a variable that is an array type. |
||||
if not isinstance(arg, (StateVariable, LocalVariable)): |
||||
continue |
||||
if not isinstance(arg.type, ArrayType): |
||||
continue |
||||
|
||||
# If it is a state variable OR a local variable referencing storage, we add it to the list. |
||||
if isinstance(arg, StateVariable) or ( |
||||
isinstance(arg, LocalVariable) and arg.location == "storage" |
||||
): |
||||
results.append((node, arg, ir.function)) |
||||
return results |
||||
|
||||
def _detect(self): |
||||
""" |
||||
Detects passing of arrays located in memory to functions which expect to modify arrays via storage reference. |
||||
:return: The JSON results of the detector, which contains the calling_node, affected_argument_variable and |
||||
invoked_function for each result found. |
||||
""" |
||||
results = [] |
||||
array_modifying_funcs = self.get_funcs_modifying_array_params(self.contracts) |
||||
problematic_calls = self.detect_calls_passing_ref_to_function( |
||||
self.contracts, array_modifying_funcs |
||||
) |
||||
|
||||
if problematic_calls: |
||||
for calling_node, affected_argument, invoked_function in problematic_calls: |
||||
info = [ |
||||
calling_node.function, |
||||
" passes array ", |
||||
affected_argument, |
||||
"by reference to ", |
||||
invoked_function, |
||||
"which only takes arrays by value\n", |
||||
] |
||||
|
||||
res = self.generate_result(info) |
||||
results.append(res) |
||||
|
||||
return results |
@ -0,0 +1,84 @@ |
||||
""" |
||||
Module detecting dangerous conversion to enum |
||||
""" |
||||
|
||||
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification |
||||
from slither.slithir.operations import TypeConversion |
||||
from slither.core.declarations.enum import Enum |
||||
|
||||
|
||||
def _uses_vulnerable_solc_version(version): |
||||
"""Detect if used compiler version is 0.4.[0|1|2|3|4] |
||||
Args: |
||||
version (solc version used) |
||||
Returns: |
||||
Bool |
||||
""" |
||||
if version in ["0.4.0", "0.4.1", "0.4.2", "0.4.3", "0.4.4"]: |
||||
return True |
||||
return False |
||||
|
||||
|
||||
def _detect_dangerous_enum_conversions(contract): |
||||
"""Detect dangerous conversion to enum by checking IR |
||||
Args: |
||||
contract (Contract) |
||||
Returns: |
||||
list[(node, variable)] (Nodes where a variable is being converted into enum) |
||||
""" |
||||
return [ |
||||
(n, ir.variable) |
||||
for f in contract.functions_declared |
||||
for n in f.nodes |
||||
for ir in n.irs |
||||
if isinstance(ir, TypeConversion) and isinstance(ir.type.type, Enum) |
||||
] |
||||
|
||||
|
||||
class EnumConversion(AbstractDetector): |
||||
""" |
||||
Detect dangerous conversion to enum |
||||
""" |
||||
|
||||
ARGUMENT = "enum-conversion" |
||||
HELP = "Detect dangerous enum conversion" |
||||
IMPACT = DetectorClassification.MEDIUM |
||||
CONFIDENCE = DetectorClassification.HIGH |
||||
|
||||
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#dangerous-enum-conversion" |
||||
WIKI_TITLE = "Dangerous enum conversion" |
||||
WIKI_DESCRIPTION = "Detect out-of-range `enum` conversion (`solc` < `0.4.5`)." |
||||
WIKI_EXPLOIT_SCENARIO = """ |
||||
```solidity |
||||
pragma solidity 0.4.2; |
||||
contract Test{ |
||||
|
||||
enum E{a} |
||||
|
||||
function bug(uint a) public returns(E){ |
||||
return E(a); |
||||
} |
||||
} |
||||
``` |
||||
Attackers can trigger unexpected behaviour by calling `bug(1)`.""" |
||||
|
||||
WIKI_RECOMMENDATION = "Use a recent compiler version. If `solc` <`0.4.5` is required, check the `enum` conversion range." |
||||
|
||||
def _detect(self): |
||||
"""Detect dangerous conversion to enum""" |
||||
results = [] |
||||
# If solc version >= 0.4.5 then return |
||||
if not _uses_vulnerable_solc_version(self.slither.solc_version): |
||||
return results |
||||
|
||||
for c in self.slither.contracts: |
||||
ret = _detect_dangerous_enum_conversions(c) |
||||
for node, var in ret: |
||||
func_info = [node, " has a dangerous enum conversion\n"] |
||||
# Output each node with the function info header as a separate result. |
||||
variable_info = ["\t- Variable: ", var, f" of type: {str(var.type)}\n"] |
||||
node_info = ["\t- Enum conversion: ", node, "\n"] |
||||
json = self.generate_result(func_info + variable_info + node_info) |
||||
results.append(json) |
||||
|
||||
return results |
@ -0,0 +1,62 @@ |
||||
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification |
||||
|
||||
|
||||
class MultipleConstructorSchemes(AbstractDetector): |
||||
""" |
||||
Module detecting multiple constructors in the same contract. |
||||
(This was possible prior to Solidity 0.4.23, using old and new constructor schemes). |
||||
""" |
||||
|
||||
ARGUMENT = "multiple-constructors" |
||||
HELP = "Multiple constructor schemes" |
||||
IMPACT = DetectorClassification.HIGH |
||||
CONFIDENCE = DetectorClassification.HIGH |
||||
|
||||
WIKI = ( |
||||
"https://github.com/crytic/slither/wiki/Detector-Documentation#multiple-constructor-schemes" |
||||
) |
||||
|
||||
WIKI_TITLE = "Multiple constructor schemes" |
||||
WIKI_DESCRIPTION = ( |
||||
"Detect multiple constructor definitions in the same contract (using new and old schemes)." |
||||
) |
||||
WIKI_EXPLOIT_SCENARIO = """ |
||||
```solidity |
||||
contract A { |
||||
uint x; |
||||
constructor() public { |
||||
x = 0; |
||||
} |
||||
function A() public { |
||||
x = 1; |
||||
} |
||||
|
||||
function test() public returns(uint) { |
||||
return x; |
||||
} |
||||
} |
||||
``` |
||||
In Solidity [0.4.22](https://github.com/ethereum/solidity/releases/tag/v0.4.23), a contract with both constructor schemes will compile. The first constructor will take precedence over the second, which may be unintended.""" |
||||
|
||||
WIKI_RECOMMENDATION = "Only declare one constructor, preferably using the new scheme `constructor(...)` instead of `function <contractName>(...)`." |
||||
|
||||
def _detect(self): |
||||
""" |
||||
Detect multiple constructor schemes in the same contract |
||||
:return: Returns a list of contract JSON result, where each result contains all constructor definitions. |
||||
""" |
||||
results = [] |
||||
for contract in self.contracts: |
||||
# Obtain any constructors defined in this contract |
||||
constructors = [f for f in contract.constructors if f.contract_declarer == contract] |
||||
|
||||
# If there is more than one, we encountered the described issue occurring. |
||||
if constructors and len(constructors) > 1: |
||||
info = [contract, " contains multiple constructors in the same contract:\n"] |
||||
for constructor in constructors: |
||||
info += ["\t- ", constructor, "\n"] |
||||
|
||||
res = self.generate_result(info) |
||||
results.append(res) |
||||
|
||||
return results |
@ -0,0 +1,89 @@ |
||||
""" |
||||
Module detecting public mappings with nested variables (returns incorrect values prior to 0.5.x) |
||||
""" |
||||
|
||||
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification |
||||
from slither.core.solidity_types.mapping_type import MappingType |
||||
from slither.core.solidity_types.user_defined_type import UserDefinedType |
||||
from slither.core.declarations.structure import Structure |
||||
|
||||
|
||||
def detect_public_nested_mappings(contract): |
||||
""" |
||||
Detect any state variables that are initialized from an immediate function call (prior to constructor run). |
||||
:param contract: The contract to detect state variable definitions for. |
||||
:return: A list of all state variables defined in the given contract that meet the specified criteria. |
||||
""" |
||||
results = [] |
||||
|
||||
for state_variable in contract.variables: |
||||
# Verify this variable is defined in this contract |
||||
if state_variable.contract != contract: |
||||
continue |
||||
|
||||
# Verify this is a public mapping |
||||
if state_variable.visibility != "public" or not isinstance( |
||||
state_variable.type, MappingType |
||||
): |
||||
continue |
||||
|
||||
# Verify the value type is a user defined type (struct) |
||||
if not isinstance(state_variable.type.type_to, UserDefinedType) or not isinstance( |
||||
state_variable.type.type_to.type, Structure |
||||
): |
||||
continue |
||||
|
||||
# Obtain the struct |
||||
struct_type = state_variable.type.type_to.type |
||||
for struct_member in struct_type.elems.values(): |
||||
if isinstance(struct_member.type, UserDefinedType) and isinstance( |
||||
struct_member.type.type, Structure |
||||
): |
||||
results.append(state_variable) |
||||
break |
||||
|
||||
return results |
||||
|
||||
|
||||
class PublicMappingNested(AbstractDetector): |
||||
""" |
||||
Detects public mappings with nested variables (returns incorrect values prior to 0.5.x) |
||||
""" |
||||
|
||||
ARGUMENT = "public-mappings-nested" |
||||
HELP = "Public mappings with nested variables" |
||||
IMPACT = DetectorClassification.HIGH |
||||
CONFIDENCE = DetectorClassification.HIGH |
||||
|
||||
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#public-mappings-with-nested-variables" |
||||
|
||||
WIKI_TITLE = "Public mappings with nested variables" |
||||
WIKI_DESCRIPTION = "Prior to Solidity 0.5, a public mapping with nested structures returned [incorrect values](https://github.com/ethereum/solidity/issues/5520)." |
||||
WIKI_EXPLOIT_SCENARIO = """Bob interacts with a contract that has a public mapping with nested structures. The values returned by the mapping are incorrect, breaking Bob's usage""" |
||||
WIKI_RECOMMENDATION = "Do not use public mapping with nested structures." |
||||
|
||||
def _detect(self): |
||||
""" |
||||
Detect public mappings with nested variables (returns incorrect values prior to 0.5.x) |
||||
|
||||
Returns: |
||||
list: {'vuln', 'filename,'contract','func', 'public_nested_mappings'} |
||||
|
||||
""" |
||||
results = [] |
||||
|
||||
for p in self.slither.pragma_directives: |
||||
if "0.5.0" in p.version and not "<0.5.0" in p.version: |
||||
return [] |
||||
if self.slither.solc_version and self.slither.solc_version.startswith("0.5."): |
||||
return [] |
||||
|
||||
for contract in self.contracts: |
||||
public_nested_mappings = detect_public_nested_mappings(contract) |
||||
if public_nested_mappings: |
||||
for public_nested_mapping in public_nested_mappings: |
||||
info = [public_nested_mapping, " is a public mapping with nested variables\n"] |
||||
json = self.generate_result(info) |
||||
results.append(json) |
||||
|
||||
return results |
@ -0,0 +1,157 @@ |
||||
""" |
||||
Module detecting re-used base constructors in inheritance hierarchy. |
||||
""" |
||||
|
||||
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification |
||||
|
||||
|
||||
# Helper: adds explicitly called constructors with arguments to the results lookup. |
||||
def _add_constructors_with_args( |
||||
base_constructors, called_by_constructor, current_contract, results |
||||
): |
||||
for explicit_base_constructor in base_constructors: |
||||
if len(explicit_base_constructor.parameters) > 0: |
||||
if explicit_base_constructor not in results: |
||||
results[explicit_base_constructor] = [] |
||||
results[explicit_base_constructor] += [(current_contract, called_by_constructor)] |
||||
|
||||
|
||||
class ReusedBaseConstructor(AbstractDetector): |
||||
""" |
||||
Re-used base constructors |
||||
""" |
||||
|
||||
ARGUMENT = "reused-constructor" |
||||
HELP = "Reused base constructor" |
||||
IMPACT = DetectorClassification.MEDIUM |
||||
# The confidence is medium, because prior Solidity 0.4.22, we cant differentiate |
||||
# contract C is A() { |
||||
# to |
||||
# contract C is A { |
||||
CONFIDENCE = DetectorClassification.MEDIUM |
||||
|
||||
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#reused-base-constructors" |
||||
|
||||
WIKI_TITLE = "Reused base constructors" |
||||
WIKI_DESCRIPTION = "Detects if the same base constructor is called with arguments from two different locations in the same inheritance hierarchy." |
||||
WIKI_EXPLOIT_SCENARIO = """ |
||||
```solidity |
||||
pragma solidity ^0.4.0; |
||||
|
||||
contract A{ |
||||
uint num = 5; |
||||
constructor(uint x) public{ |
||||
num += x; |
||||
} |
||||
} |
||||
|
||||
contract B is A{ |
||||
constructor() A(2) public { /* ... */ } |
||||
} |
||||
|
||||
contract C is A { |
||||
constructor() A(3) public { /* ... */ } |
||||
} |
||||
|
||||
contract D is B, C { |
||||
constructor() public { /* ... */ } |
||||
} |
||||
|
||||
contract E is B { |
||||
constructor() A(1) public { /* ... */ } |
||||
} |
||||
``` |
||||
The constructor of `A` is called multiple times in `D` and `E`: |
||||
- `D` inherits from `B` and `C`, both of which construct `A`. |
||||
- `E` only inherits from `B`, but `B` and `E` construct `A`. |
||||
.""" |
||||
WIKI_RECOMMENDATION = "Remove the duplicate constructor call." |
||||
|
||||
def _detect_explicitly_called_base_constructors(self, contract): |
||||
""" |
||||
Detects explicitly calls to base constructors with arguments in the inheritance hierarchy. |
||||
:param contract: The contract to detect explicit calls to a base constructor with arguments to. |
||||
:return: Dictionary of function:list(tuple): { constructor : [(invoking_contract, called_by_constructor]} |
||||
""" |
||||
results = dict() |
||||
|
||||
# Create a set to track all completed contracts |
||||
processed_contracts = set() |
||||
queued_contracts = [contract] + contract.inheritance |
||||
|
||||
# Loop until there are no queued contracts left. |
||||
while len(queued_contracts) > 0: |
||||
|
||||
# Pop a contract off the front of the queue, if it has already been processed, we stop. |
||||
current_contract = queued_contracts.pop(0) |
||||
if current_contract in processed_contracts: |
||||
continue |
||||
|
||||
# Add this contract to the processed contracts |
||||
processed_contracts.add(current_contract) |
||||
|
||||
# Prior Solidity 0.4.22, the constructor would appear two times |
||||
# Leading to several FPs |
||||
# As the result, we might miss some TPs if the reused is due to the constructor called |
||||
# In the contract definition |
||||
if self.slither.solc_version >= "0.4.22": |
||||
# Find all base constructors explicitly called from the contract definition with arguments. |
||||
_add_constructors_with_args( |
||||
current_contract.explicit_base_constructor_calls, |
||||
False, |
||||
current_contract, |
||||
results, |
||||
) |
||||
|
||||
# Find all base constructors explicitly called from the constructor definition with arguments. |
||||
if current_contract.constructors_declared: |
||||
_add_constructors_with_args( |
||||
current_contract.constructors_declared.explicit_base_constructor_calls, |
||||
True, |
||||
current_contract, |
||||
results, |
||||
) |
||||
|
||||
return results |
||||
|
||||
def _detect(self): |
||||
""" |
||||
Detect reused base constructors. |
||||
:return: Returns a list of JSON results. |
||||
""" |
||||
|
||||
results = [] |
||||
|
||||
# The bug is not possible with solc >= 0.5.0 |
||||
if not self.slither.solc_version.startswith("0.4."): |
||||
return [] |
||||
|
||||
# Loop for each contract |
||||
for contract in self.contracts: |
||||
|
||||
# Detect all locations which all underlying base constructors with arguments were called from. |
||||
called_base_constructors = self._detect_explicitly_called_base_constructors(contract) |
||||
for base_constructor, call_list in called_base_constructors.items(): |
||||
# Only report if there are multiple calls to the same base constructor. |
||||
if len(call_list) <= 1: |
||||
continue |
||||
|
||||
# Generate data to output. |
||||
info = [ |
||||
contract, |
||||
" gives base constructor ", |
||||
base_constructor, |
||||
" arguments more than once in inheritance hierarchy:\n", |
||||
] |
||||
|
||||
for (calling_contract, called_by_constructor) in call_list: |
||||
info += [ |
||||
"\t- From ", |
||||
calling_contract, |
||||
f" {'constructor' if called_by_constructor else 'contract'} definition\n", |
||||
] |
||||
|
||||
res = self.generate_result(info) |
||||
results.append(res) |
||||
|
||||
return results |
@ -0,0 +1,150 @@ |
||||
""" |
||||
Module detecting ABIEncoderV2 array bug |
||||
""" |
||||
|
||||
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification |
||||
from slither.core.solidity_types import ArrayType |
||||
from slither.core.solidity_types import UserDefinedType |
||||
from slither.core.variables.local_variable import LocalVariable |
||||
from slither.core.variables.state_variable import StateVariable |
||||
from slither.slithir.operations import SolidityCall |
||||
from slither.core.declarations.solidity_variables import SolidityFunction |
||||
from slither.slithir.operations import EventCall |
||||
from slither.slithir.operations import HighLevelCall |
||||
from slither.utils.utils import unroll |
||||
|
||||
vulnerable_solc_versions = [ |
||||
"0.4.7", |
||||
"0.4.8", |
||||
"0.4.9", |
||||
"0.4.10", |
||||
"0.4.11", |
||||
"0.4.12", |
||||
"0.4.13", |
||||
"0.4.14", |
||||
"0.4.15", |
||||
"0.4.16", |
||||
"0.4.17", |
||||
"0.4.18", |
||||
"0.4.19", |
||||
"0.4.20", |
||||
"0.4.21", |
||||
"0.4.22", |
||||
"0.4.23", |
||||
"0.4.24", |
||||
"0.4.25", |
||||
"0.5.0", |
||||
"0.5.1", |
||||
"0.5.2", |
||||
"0.5.3", |
||||
"0.5.4", |
||||
"0.5.5", |
||||
"0.5.6", |
||||
"0.5.7", |
||||
"0.5.8", |
||||
"0.5.9", |
||||
"0.5.10", |
||||
] |
||||
|
||||
|
||||
class ABIEncoderV2Array(AbstractDetector): |
||||
""" |
||||
Detects Storage ABIEncoderV2 array bug |
||||
""" |
||||
|
||||
ARGUMENT = "abiencoderv2-array" |
||||
HELP = "Storage abiencoderv2 array" |
||||
IMPACT = DetectorClassification.HIGH |
||||
CONFIDENCE = DetectorClassification.HIGH |
||||
|
||||
WIKI = ( |
||||
"https://github.com/crytic/slither/wiki/Detector-Documentation#storage-abiencoderv2-array" |
||||
) |
||||
WIKI_TITLE = "Storage ABIEncoderV2 Array" |
||||
WIKI_DESCRIPTION = """`solc` versions `0.4.7`-`0.5.10` contain a [compiler bug](https://blog.ethereum.org/2019/06/25/solidity-storage-array-bugs.) leading to incorrect ABI encoder usage.""" |
||||
WIKI_EXPLOIT_SCENARIO = """ |
||||
```solidity |
||||
contract A { |
||||
uint[2][3] bad_arr = [[1, 2], [3, 4], [5, 6]]; |
||||
|
||||
/* Array of arrays passed to abi.encode is vulnerable */ |
||||
function bad() public { |
||||
bytes memory b = abi.encode(bad_arr); |
||||
} |
||||
} |
||||
``` |
||||
`abi.encode(bad_arr)` in a call to `bad()` will incorrectly encode the array as `[[1, 2], [2, 3], [3, 4]]` and lead to unintended behavior. |
||||
""" |
||||
WIKI_RECOMMENDATION = "Use a compiler >= `0.5.10`." |
||||
|
||||
@staticmethod |
||||
def _detect_storage_abiencoderv2_arrays(contract): |
||||
""" |
||||
Detects and returns all nodes with storage-allocated abiencoderv2 arrays of arrays/structs in abi.encode, events or external calls |
||||
:param contract: Contract to detect within |
||||
:return: A list of tuples with (function, node) where function node has storage-allocated abiencoderv2 arrays of arrays/structs |
||||
""" |
||||
# Create our result set. |
||||
results = set() |
||||
|
||||
# Loop for each function and modifier. |
||||
# pylint: disable=too-many-nested-blocks |
||||
for function in contract.functions_and_modifiers_declared: |
||||
# Loop every node, looking for storage-allocated array of arrays/structs |
||||
# in arguments to abi.encode, events or external calls |
||||
for node in function.nodes: |
||||
for ir in node.irs: |
||||
# Call to abi.encode() |
||||
if ( |
||||
isinstance(ir, SolidityCall) |
||||
and ir.function == SolidityFunction("abi.encode()") |
||||
or |
||||
# Call to emit event |
||||
# Call to external function |
||||
isinstance(ir, (EventCall, HighLevelCall)) |
||||
): |
||||
for arg in unroll(ir.arguments): |
||||
# Check if arguments are storage allocated arrays of arrays/structs |
||||
if ( |
||||
isinstance(arg.type, ArrayType) |
||||
# Storage allocated |
||||
and ( |
||||
isinstance(arg, StateVariable) |
||||
or (isinstance(arg, LocalVariable) and arg.is_storage) |
||||
) |
||||
# Array of arrays or structs |
||||
and isinstance(arg.type.type, (ArrayType, UserDefinedType)) |
||||
): |
||||
results.add((function, node)) |
||||
break |
||||
|
||||
# Return the resulting set of tuples |
||||
return results |
||||
|
||||
def _detect(self): |
||||
""" |
||||
Detect ABIEncoderV2 array bug |
||||
""" |
||||
results = [] |
||||
|
||||
# Check if vulnerable solc versions are used |
||||
if self.slither.solc_version not in vulnerable_solc_versions: |
||||
return results |
||||
|
||||
# Check if pragma experimental ABIEncoderV2 is used |
||||
if not any( |
||||
(p.directive[0] == "experimental" and p.directive[1] == "ABIEncoderV2") |
||||
for p in self.slither.pragma_directives |
||||
): |
||||
return results |
||||
|
||||
# Check for storage-allocated abiencoderv2 arrays of arrays/structs |
||||
# in arguments of abi.encode, events or external calls |
||||
for contract in self.contracts: |
||||
storage_abiencoderv2_arrays = self._detect_storage_abiencoderv2_arrays(contract) |
||||
for function, node in storage_abiencoderv2_arrays: |
||||
info = ["Function ", function, " trigger an abi encoding bug:\n\t- ", node, "\n"] |
||||
res = self.generate_result(info) |
||||
results.append(res) |
||||
|
||||
return results |
@ -0,0 +1,147 @@ |
||||
""" |
||||
Module detecting storage signed integer array bug |
||||
""" |
||||
|
||||
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification |
||||
from slither.core.cfg.node import NodeType |
||||
from slither.core.solidity_types import ArrayType |
||||
from slither.core.solidity_types.elementary_type import Int, ElementaryType |
||||
from slither.core.variables.local_variable import LocalVariable |
||||
from slither.core.variables.state_variable import StateVariable |
||||
from slither.slithir.operations.assignment import Assignment |
||||
from slither.slithir.operations.init_array import InitArray |
||||
|
||||
vulnerable_solc_versions = [ |
||||
"0.4.7", |
||||
"0.4.8", |
||||
"0.4.9", |
||||
"0.4.10", |
||||
"0.4.11", |
||||
"0.4.12", |
||||
"0.4.13", |
||||
"0.4.14", |
||||
"0.4.15", |
||||
"0.4.16", |
||||
"0.4.17", |
||||
"0.4.18", |
||||
"0.4.19", |
||||
"0.4.20", |
||||
"0.4.21", |
||||
"0.4.22", |
||||
"0.4.23", |
||||
"0.4.24", |
||||
"0.4.25", |
||||
"0.5.0", |
||||
"0.5.1", |
||||
"0.5.2", |
||||
"0.5.3", |
||||
"0.5.4", |
||||
"0.5.5", |
||||
"0.5.6", |
||||
"0.5.7", |
||||
"0.5.8", |
||||
"0.5.9", |
||||
"0.5.10", |
||||
] |
||||
|
||||
|
||||
class StorageSignedIntegerArray(AbstractDetector): |
||||
""" |
||||
Storage signed integer array |
||||
""" |
||||
|
||||
ARGUMENT = "storage-array" |
||||
HELP = "Signed storage integer array compiler bug" |
||||
IMPACT = DetectorClassification.HIGH |
||||
CONFIDENCE = DetectorClassification.MEDIUM |
||||
|
||||
WIKI = ( |
||||
"https://github.com/crytic/slither/wiki/Detector-Documentation#storage-signed-integer-array" |
||||
) |
||||
WIKI_TITLE = "Storage Signed Integer Array" |
||||
WIKI_DESCRIPTION = """`solc` versions `0.4.7`-`0.5.10` contain [a compiler bug](https://blog.ethereum.org/2019/06/25/solidity-storage-array-bugs) |
||||
leading to incorrect values in signed integer arrays.""" |
||||
WIKI_EXPLOIT_SCENARIO = """ |
||||
```solidity |
||||
contract A { |
||||
int[3] ether_balances; // storage signed integer array |
||||
function bad0() private { |
||||
// ... |
||||
ether_balances = [-1, -1, -1]; |
||||
// ... |
||||
} |
||||
} |
||||
``` |
||||
`bad0()` uses a (storage-allocated) signed integer array state variable to store the ether balances of three accounts. |
||||
`-1` is supposed to indicate uninitialized values but the Solidity bug makes these as `1`, which could be exploited by the accounts. |
||||
""" |
||||
WIKI_RECOMMENDATION = "Use a compiler version >= `0.5.10`." |
||||
|
||||
@staticmethod |
||||
def _is_vulnerable_type(ir): |
||||
""" |
||||
Detect if the IR lvalue is a vulnerable type |
||||
Must be a storage allocation, and an array of Int |
||||
Assume the IR is a InitArray, or an Assignement to an ArrayType |
||||
""" |
||||
# Storage allocation |
||||
# Base type is signed integer |
||||
return ( |
||||
( |
||||
isinstance(ir.lvalue, StateVariable) |
||||
or (isinstance(ir.lvalue, LocalVariable) and ir.lvalue.is_storage) |
||||
) |
||||
and isinstance(ir.lvalue.type.type, ElementaryType) |
||||
and ir.lvalue.type.type.type in Int |
||||
) |
||||
|
||||
def detect_storage_signed_integer_arrays(self, contract): |
||||
""" |
||||
Detects and returns all nodes with storage-allocated signed integer array init/assignment |
||||
:param contract: Contract to detect within |
||||
:return: A list of tuples with (function, node) where function node has storage-allocated signed integer array init/assignment |
||||
""" |
||||
# Create our result set. |
||||
results = set() |
||||
|
||||
# Loop for each function and modifier. |
||||
for function in contract.functions_and_modifiers_declared: |
||||
# Loop for every node in this function, looking for storage-allocated |
||||
# signed integer array initializations/assignments |
||||
for node in function.nodes: |
||||
if node.type == NodeType.EXPRESSION: |
||||
for ir in node.irs: |
||||
# Storage-allocated signed integer array initialization expression |
||||
if isinstance(ir, InitArray) and self._is_vulnerable_type(ir): |
||||
results.add((function, node)) |
||||
# Assignment expression with lvalue being a storage-allocated signed integer array and |
||||
# rvalue being a signed integer array of different base type than lvalue |
||||
if ( |
||||
isinstance(ir, Assignment) |
||||
and isinstance(ir.lvalue.type, ArrayType) |
||||
and self._is_vulnerable_type(ir) |
||||
# Base type is signed integer and lvalue base type is different from rvalue base type |
||||
and ir.lvalue.type.type != ir.rvalue.type.type |
||||
): |
||||
results.add((function, node)) |
||||
|
||||
# Return the resulting set of tuples |
||||
return results |
||||
|
||||
def _detect(self): |
||||
""" |
||||
Detect storage signed integer array init/assignment |
||||
""" |
||||
results = [] |
||||
if self.slither.solc_version not in vulnerable_solc_versions: |
||||
return results |
||||
for contract in self.contracts: |
||||
storage_signed_integer_arrays = self.detect_storage_signed_integer_arrays(contract) |
||||
for function, node in storage_signed_integer_arrays: |
||||
contract_info = ["Contract ", contract, " \n"] |
||||
function_info = ["\t- Function ", function, "\n"] |
||||
node_info = ["\t\t- ", node, " has a storage signed integer array assignment\n"] |
||||
res = self.generate_result(contract_info + function_info + node_info) |
||||
results.append(res) |
||||
|
||||
return results |
@ -0,0 +1,149 @@ |
||||
""" |
||||
Module detecting uninitialized function pointer calls in constructors |
||||
""" |
||||
|
||||
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification |
||||
from slither.slithir.operations import InternalDynamicCall, OperationWithLValue |
||||
from slither.slithir.variables import ReferenceVariable |
||||
from slither.slithir.variables.variable import SlithIRVariable |
||||
|
||||
vulnerable_solc_versions = [ |
||||
"0.4.5", |
||||
"0.4.6", |
||||
"0.4.7", |
||||
"0.4.8", |
||||
"0.4.9", |
||||
"0.4.10", |
||||
"0.4.11", |
||||
"0.4.12", |
||||
"0.4.13", |
||||
"0.4.14", |
||||
"0.4.15", |
||||
"0.4.16", |
||||
"0.4.17", |
||||
"0.4.18", |
||||
"0.4.19", |
||||
"0.4.20", |
||||
"0.4.21", |
||||
"0.4.22", |
||||
"0.4.23", |
||||
"0.4.24", |
||||
"0.4.25", |
||||
"0.5.0", |
||||
"0.5.1", |
||||
"0.5.2", |
||||
"0.5.3", |
||||
"0.5.4", |
||||
"0.5.5", |
||||
"0.5.6", |
||||
"0.5.7", |
||||
"0.5.8", |
||||
] |
||||
|
||||
|
||||
def _get_variables_entrance(function): |
||||
""" |
||||
Return the first SSA variables of the function |
||||
Catpure the phi operation at the entry point |
||||
""" |
||||
ret = [] |
||||
if function.entry_point: |
||||
for ir_ssa in function.entry_point.irs_ssa: |
||||
if isinstance(ir_ssa, OperationWithLValue): |
||||
ret.append(ir_ssa.lvalue) |
||||
return ret |
||||
|
||||
|
||||
def _is_vulnerable(node, variables_entrance): |
||||
""" |
||||
Vulnerable if an IR ssa: |
||||
- It is an internal dynamic call |
||||
- The destination has not an index of 0 |
||||
- The destination is not in the allowed variable |
||||
""" |
||||
for ir_ssa in node.irs_ssa: |
||||
if isinstance(ir_ssa, InternalDynamicCall): |
||||
destination = ir_ssa.function |
||||
# If it is a reference variable, destination should be the origin variable |
||||
# Note: this will create FN if one of the field of a structure is updated, while not begin |
||||
# the field of the function pointer. This should be fixed once we have the IR refactoring |
||||
if isinstance(destination, ReferenceVariable): |
||||
destination = destination.points_to_origin |
||||
if isinstance(destination, SlithIRVariable) and ir_ssa.function.index == 0: |
||||
return True |
||||
if destination in variables_entrance: |
||||
return True |
||||
return False |
||||
|
||||
|
||||
class UninitializedFunctionPtrsConstructor(AbstractDetector): |
||||
""" |
||||
Uninitialized function pointer calls in constructors |
||||
""" |
||||
|
||||
ARGUMENT = "uninitialized-fptr-cst" |
||||
HELP = "Uninitialized function pointer calls in constructors" |
||||
IMPACT = DetectorClassification.LOW |
||||
CONFIDENCE = DetectorClassification.HIGH |
||||
|
||||
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#uninitialized-function-pointers-in-constructors" |
||||
WIKI_TITLE = "Uninitialized function pointers in constructors" |
||||
WIKI_DESCRIPTION = "solc versions `0.4.5`-`0.4.26` and `0.5.0`-`0.5.8` contain a compiler bug leading to unexpected behavior when calling uninitialized function pointers in constructors." |
||||
WIKI_EXPLOIT_SCENARIO = """ |
||||
```solidity |
||||
contract bad0 { |
||||
|
||||
constructor() public { |
||||
/* Uninitialized function pointer */ |
||||
function(uint256) internal returns(uint256) a; |
||||
a(10); |
||||
} |
||||
|
||||
} |
||||
``` |
||||
The call to `a(10)` will lead to unexpected behavior because function pointer `a` is not initialized in the constructor.""" |
||||
WIKI_RECOMMENDATION = ( |
||||
"Initialize function pointers before calling. Avoid function pointers if possible." |
||||
) |
||||
|
||||
@staticmethod |
||||
def _detect_uninitialized_function_ptr_in_constructor(contract): |
||||
""" |
||||
Detect uninitialized function pointer calls in constructors |
||||
:param contract: The contract of interest for detection |
||||
:return: A list of nodes with uninitialized function pointer calls in the constructor of given contract |
||||
""" |
||||
results = [] |
||||
constructor = contract.constructors_declared |
||||
if constructor: |
||||
variables_entrance = _get_variables_entrance(constructor) |
||||
results = [ |
||||
node for node in constructor.nodes if _is_vulnerable(node, variables_entrance) |
||||
] |
||||
return results |
||||
|
||||
def _detect(self): |
||||
""" |
||||
Detect uninitialized function pointer calls in constructors of contracts |
||||
Returns: |
||||
list: ['uninitialized function pointer calls in constructors'] |
||||
""" |
||||
results = [] |
||||
|
||||
# Check if vulnerable solc versions are used |
||||
if self.slither.solc_version not in vulnerable_solc_versions: |
||||
return results |
||||
|
||||
for contract in self.slither.contracts: |
||||
contract_info = ["Contract ", contract, " \n"] |
||||
nodes = self._detect_uninitialized_function_ptr_in_constructor(contract) |
||||
for node in nodes: |
||||
node_info = [ |
||||
"\t ", |
||||
node, |
||||
" is an unintialized function pointer call in a constructor\n", |
||||
] |
||||
json = self.generate_result(contract_info + node_info) |
||||
results.append(json) |
||||
|
||||
return results |
@ -0,0 +1,105 @@ |
||||
""" |
||||
Module detecting unimplemented functions |
||||
Recursively check the called functions |
||||
|
||||
Collect all the implemented and unimplemented functions of all the contracts |
||||
Check for unimplemented functions that are never implemented |
||||
Consider public state variables as implemented functions |
||||
Do not consider fallback function or constructor |
||||
""" |
||||
|
||||
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification |
||||
|
||||
# Since 0.5.1, Solidity allows creating state variable matching a function signature. |
||||
older_solc_versions = ["0.5.0"] + ["0.4." + str(x) for x in range(0, 27)] |
||||
|
||||
|
||||
class UnimplementedFunctionDetection(AbstractDetector): |
||||
""" |
||||
Unimplemented functions detector |
||||
""" |
||||
|
||||
ARGUMENT = "unimplemented-functions" |
||||
HELP = "Unimplemented functions" |
||||
IMPACT = DetectorClassification.INFORMATIONAL |
||||
CONFIDENCE = DetectorClassification.HIGH |
||||
|
||||
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#unimplemented-functions" |
||||
|
||||
WIKI_TITLE = "Unimplemented functions" |
||||
WIKI_DESCRIPTION = "Detect functions that are not implemented on derived-most contracts." |
||||
WIKI_EXPLOIT_SCENARIO = """ |
||||
```solidity |
||||
interface BaseInterface { |
||||
function f1() external returns(uint); |
||||
function f2() external returns(uint); |
||||
} |
||||
|
||||
interface BaseInterface2 { |
||||
function f3() external returns(uint); |
||||
} |
||||
|
||||
contract DerivedContract is BaseInterface, BaseInterface2 { |
||||
function f1() external returns(uint){ |
||||
return 42; |
||||
} |
||||
} |
||||
``` |
||||
`DerivedContract` does not implement `BaseInterface.f2` or `BaseInterface2.f3`. |
||||
As a result, the contract will not properly compile. |
||||
All unimplemented functions must be implemented on a contract that is meant to be used.""" |
||||
|
||||
WIKI_RECOMMENDATION = "Implement all unimplemented functions in any contract you intend to use directly (not simply inherit from)." |
||||
|
||||
@staticmethod |
||||
def _match_state_variable(contract, f): |
||||
return any(s.full_name == f.full_name for s in contract.state_variables) |
||||
|
||||
def _detect_unimplemented_function(self, contract): |
||||
""" |
||||
Detects any function definitions which are not implemented in the given contract. |
||||
:param contract: The contract to search unimplemented functions for. |
||||
:return: A list of functions which are not implemented. |
||||
""" |
||||
|
||||
# If it's simply a contract signature, we have no functions. |
||||
if contract.is_signature_only(): |
||||
return set() |
||||
|
||||
# Populate our unimplemented functions set with any functions not implemented in this contract, excluding the |
||||
# fallback function and constructor. |
||||
unimplemented = set() |
||||
for f in contract.all_functions_called: |
||||
if ( |
||||
not f.is_implemented |
||||
and not f.is_constructor |
||||
and not f.is_fallback |
||||
and not f.is_constructor_variables |
||||
): |
||||
if self.slither.solc_version not in older_solc_versions: |
||||
# Since 0.5.1, Solidity allows creating state variable matching a function signature |
||||
if not self._match_state_variable(contract, f): |
||||
unimplemented.add(f) |
||||
else: |
||||
unimplemented.add(f) |
||||
return unimplemented |
||||
|
||||
def _detect(self): |
||||
"""Detect unimplemented functions |
||||
|
||||
Recursively visit the calls |
||||
Returns: |
||||
list: {'vuln', 'filename,'contract','func'} |
||||
""" |
||||
results = [] |
||||
for contract in self.slither.contracts_derived: |
||||
functions = self._detect_unimplemented_function(contract) |
||||
if functions: |
||||
info = [contract, " does not implement functions:\n"] |
||||
|
||||
for function in sorted(functions, key=lambda x: x.full_name): |
||||
info += ["\t- ", function, "\n"] |
||||
|
||||
res = self.generate_result(info) |
||||
results.append(res) |
||||
return results |
@ -0,0 +1,122 @@ |
||||
""" |
||||
Module detecting bad PRNG due to the use of block.timestamp, now or blockhash (block.blockhash) as a source of randomness |
||||
""" |
||||
|
||||
from slither.analyses.data_dependency.data_dependency import is_dependent_ssa |
||||
from slither.core.declarations.solidity_variables import ( |
||||
SolidityVariable, |
||||
SolidityFunction, |
||||
SolidityVariableComposed, |
||||
) |
||||
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification |
||||
from slither.slithir.operations import BinaryType, Binary |
||||
from slither.slithir.operations import SolidityCall |
||||
|
||||
|
||||
def collect_return_values_of_bad_PRNG_functions(f): |
||||
""" |
||||
Return the return-values of calls to blockhash() |
||||
Args: |
||||
f (Function) |
||||
Returns: |
||||
list(values) |
||||
""" |
||||
values_returned = [] |
||||
for n in f.nodes: |
||||
for ir in n.irs_ssa: |
||||
if ( |
||||
isinstance(ir, SolidityCall) |
||||
and ir.function == SolidityFunction("blockhash(uint256)") |
||||
and ir.lvalue |
||||
): |
||||
values_returned.append(ir.lvalue) |
||||
return values_returned |
||||
|
||||
|
||||
def contains_bad_PRNG_sources(func, blockhash_ret_values): |
||||
""" |
||||
Check if any node in function has a modulus operator and the first operand is dependent on block.timestamp, now or blockhash() |
||||
Returns: |
||||
(nodes) |
||||
""" |
||||
ret = set() |
||||
# pylint: disable=too-many-nested-blocks |
||||
for node in func.nodes: |
||||
for ir in node.irs_ssa: |
||||
if isinstance(ir, Binary) and ir.type == BinaryType.MODULO: |
||||
if is_dependent_ssa( |
||||
ir.variable_left, SolidityVariableComposed("block.timestamp"), func.contract |
||||
) or is_dependent_ssa(ir.variable_left, SolidityVariable("now"), func.contract): |
||||
ret.add(node) |
||||
break |
||||
|
||||
for ret_val in blockhash_ret_values: |
||||
if is_dependent_ssa(ir.variable_left, ret_val, func.contract): |
||||
ret.add(node) |
||||
break |
||||
return list(ret) |
||||
|
||||
|
||||
def detect_bad_PRNG(contract): |
||||
""" |
||||
Args: |
||||
contract (Contract) |
||||
Returns: |
||||
list((Function), (list (Node))) |
||||
""" |
||||
blockhash_ret_values = [] |
||||
for f in contract.functions: |
||||
blockhash_ret_values += collect_return_values_of_bad_PRNG_functions(f) |
||||
ret = [] |
||||
for f in contract.functions: |
||||
bad_prng_nodes = contains_bad_PRNG_sources(f, blockhash_ret_values) |
||||
if bad_prng_nodes: |
||||
ret.append((f, bad_prng_nodes)) |
||||
return ret |
||||
|
||||
|
||||
class BadPRNG(AbstractDetector): |
||||
""" |
||||
Detect weak PRNG due to a modulo operation on block.timestamp, now or blockhash |
||||
""" |
||||
|
||||
ARGUMENT = "weak-prng" |
||||
HELP = "Weak PRNG" |
||||
IMPACT = DetectorClassification.HIGH |
||||
CONFIDENCE = DetectorClassification.MEDIUM |
||||
|
||||
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#weak-PRNG" |
||||
|
||||
WIKI_TITLE = "Weak PRNG" |
||||
WIKI_DESCRIPTION = "Weak PRNG due to a modulo on `block.timestamp`, `now` or `blockhash`. These can be influenced by miners to some extent so they should be avoided." |
||||
WIKI_EXPLOIT_SCENARIO = """ |
||||
```solidity |
||||
contract Game { |
||||
|
||||
uint reward_determining_number; |
||||
|
||||
function guessing() external{ |
||||
reward_determining_number = uint256(block.blockhash(10000)) % 10; |
||||
} |
||||
} |
||||
``` |
||||
Eve is a miner. Eve calls `guessing` and re-orders the block containing the transaction. |
||||
As a result, Eve wins the game.""" |
||||
|
||||
WIKI_RECOMMENDATION = ( |
||||
"Do not use `block.timestamp`, `now` or `blockhash` as a source of randomness" |
||||
) |
||||
|
||||
def _detect(self): |
||||
"""Detect bad PRNG due to the use of block.timestamp, now or blockhash (block.blockhash) as a source of randomness""" |
||||
results = [] |
||||
for c in self.slither.contracts_derived: |
||||
values = detect_bad_PRNG(c) |
||||
for func, nodes in values: |
||||
|
||||
for node in nodes: |
||||
info = [func, ' uses a weak PRNG: "', node, '" \n'] |
||||
res = self.generate_result(info) |
||||
results.append(res) |
||||
|
||||
return results |
@ -0,0 +1,118 @@ |
||||
""" |
||||
Module detecting assignment of array length |
||||
""" |
||||
|
||||
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification |
||||
from slither.core.cfg.node import NodeType |
||||
from slither.slithir.operations import Assignment, Length |
||||
from slither.slithir.variables.reference import ReferenceVariable |
||||
from slither.slithir.operations.binary import Binary |
||||
from slither.analyses.data_dependency.data_dependency import is_tainted |
||||
|
||||
|
||||
def detect_array_length_assignment(contract): |
||||
""" |
||||
Detects and returns all nodes which assign array length. |
||||
:param contract: Contract to detect assignment within. |
||||
:return: A list of tuples with (Variable, node) where Variable references an array whose length was set by node. |
||||
""" |
||||
|
||||
# Create our result set. |
||||
results = set() |
||||
|
||||
# Loop for each function and modifier. |
||||
# pylint: disable=too-many-nested-blocks |
||||
for function in contract.functions_and_modifiers_declared: |
||||
# Define a set of reference variables which refer to array length. |
||||
array_length_refs = set() |
||||
|
||||
# Loop for every node in this function, looking for expressions where array length references are made, |
||||
# and subsequent expressions where array length references are assigned to. |
||||
for node in function.nodes: |
||||
if node.type == NodeType.EXPRESSION: |
||||
for ir in node.irs: |
||||
|
||||
# First we look for the member access for 'length', for which a reference is created. |
||||
# We add the reference to our list of array length references. |
||||
if isinstance(ir, Length): # a |
||||
# if ir.variable_right == "length": |
||||
array_length_refs.add(ir.lvalue) |
||||
|
||||
# If we have an assignment/binary operation, verify the left side refers to a reference variable |
||||
# which is in our list or array length references. (Array length is being assigned to). |
||||
elif isinstance(ir, (Assignment, Binary)): |
||||
if isinstance(ir.lvalue, ReferenceVariable): |
||||
if ir.lvalue in array_length_refs and any( |
||||
is_tainted(v, contract) for v in ir.read |
||||
): |
||||
# the taint is not precise enough yet |
||||
# as a result, REF_0 = REF_0 + 1 |
||||
# where REF_0 points to a LENGTH operation |
||||
# is considered as tainted |
||||
if ir.lvalue in ir.read: |
||||
continue |
||||
results.add(node) |
||||
break |
||||
|
||||
# Return the resulting set of nodes which set array length. |
||||
return results |
||||
|
||||
|
||||
class ArrayLengthAssignment(AbstractDetector): |
||||
""" |
||||
Array length assignment |
||||
""" |
||||
|
||||
ARGUMENT = "controlled-array-length" |
||||
HELP = "Tainted array length assignment" |
||||
IMPACT = DetectorClassification.HIGH |
||||
CONFIDENCE = DetectorClassification.MEDIUM |
||||
|
||||
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#array-length-assignment" |
||||
|
||||
WIKI_TITLE = "Array Length Assignment" |
||||
WIKI_DESCRIPTION = """Detects the direct assignment of an array's length.""" |
||||
WIKI_EXPLOIT_SCENARIO = """ |
||||
```solidity |
||||
contract A { |
||||
uint[] testArray; // dynamic size array |
||||
|
||||
function f(uint usersCount) public { |
||||
// ... |
||||
testArray.length = usersCount; |
||||
// ... |
||||
} |
||||
|
||||
function g(uint userIndex, uint val) public { |
||||
// ... |
||||
testArray[userIndex] = val; |
||||
// ... |
||||
} |
||||
} |
||||
``` |
||||
Contract storage/state-variables are indexed by a 256-bit integer. |
||||
The user can set the array length to `2**256-1` in order to index all storage slots. |
||||
In the example above, one could call the function `f` to set the array length, then call the function `g` to control any storage slot desired. |
||||
Note that storage slots here are indexed via a hash of the indexers; nonetheless, all storage will still be accessible and could be controlled by the attacker.""" |
||||
|
||||
WIKI_RECOMMENDATION = """Do not allow array lengths to be set directly set; instead, opt to add values as needed. |
||||
Otherwise, thoroughly review the contract to ensure a user-controlled variable cannot reach an array length assignment.""" |
||||
|
||||
def _detect(self): |
||||
""" |
||||
Detect array length assignments |
||||
""" |
||||
results = [] |
||||
for contract in self.contracts: |
||||
array_length_assignments = detect_array_length_assignment(contract) |
||||
if array_length_assignments: |
||||
contract_info = [ |
||||
contract, |
||||
" contract sets array length with a user-controlled value:\n", |
||||
] |
||||
for node in array_length_assignments: |
||||
node_info = contract_info + ["\t- ", node, "\n"] |
||||
res = self.generate_result(node_info) |
||||
results.append(res) |
||||
|
||||
return results |
@ -0,0 +1,83 @@ |
||||
""" |
||||
Module detecting state changes in assert calls |
||||
""" |
||||
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification |
||||
from slither.slithir.operations.internal_call import InternalCall |
||||
|
||||
|
||||
def detect_assert_state_change(contract): |
||||
""" |
||||
Detects and returns all nodes with assert calls that change contract state from within the invariant |
||||
:param contract: Contract to detect |
||||
:return: A list of nodes with assert calls that change contract state from within the invariant |
||||
""" |
||||
|
||||
# Create our result set. |
||||
# List of tuples (function, node) |
||||
results = [] |
||||
|
||||
# Loop for each function and modifier. |
||||
for function in contract.functions_declared + contract.modifiers_declared: |
||||
for node in function.nodes: |
||||
# Detect assert() calls |
||||
if any(c.name == "assert(bool)" for c in node.internal_calls) and ( |
||||
# Detect direct changes to state |
||||
node.state_variables_written |
||||
or |
||||
# Detect changes to state via function calls |
||||
any( |
||||
ir |
||||
for ir in node.irs |
||||
if isinstance(ir, InternalCall) and ir.function.state_variables_written |
||||
) |
||||
): |
||||
results.append((function, node)) |
||||
|
||||
# Return the resulting set of nodes |
||||
return results |
||||
|
||||
|
||||
class AssertStateChange(AbstractDetector): |
||||
""" |
||||
Assert state change |
||||
""" |
||||
|
||||
ARGUMENT = "assert-state-change" |
||||
HELP = "Assert state change" |
||||
IMPACT = DetectorClassification.INFORMATIONAL |
||||
CONFIDENCE = DetectorClassification.INFORMATIONAL |
||||
|
||||
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#assert-state-change" |
||||
WIKI_TITLE = "Assert state shange" |
||||
WIKI_DESCRIPTION = """Incorrect use of `assert()`. See Solidity best [practices](https://solidity.readthedocs.io/en/latest/control-structures.html#id4).""" |
||||
WIKI_EXPLOIT_SCENARIO = """ |
||||
```solidity |
||||
contract A { |
||||
|
||||
uint s_a; |
||||
|
||||
function bad() public { |
||||
assert((s_a += 1) > 10); |
||||
} |
||||
} |
||||
``` |
||||
The assert in `bad()` increments the state variable `s_a` while checking for the condition. |
||||
""" |
||||
WIKI_RECOMMENDATION = """Use `require` for invariants modifying the state.""" |
||||
|
||||
def _detect(self): |
||||
""" |
||||
Detect assert calls that change state from within the invariant |
||||
""" |
||||
results = [] |
||||
for contract in self.contracts: |
||||
assert_state_change = detect_assert_state_change(contract) |
||||
for (func, node) in assert_state_change: |
||||
info = [func, " has an assert() call which possibly changes state.\n"] |
||||
info += ["\t-", node, "\n"] |
||||
info += [ |
||||
"Consider using require() or change the invariant to not modify the state.\n" |
||||
] |
||||
res = self.generate_result(info) |
||||
results.append(res) |
||||
return results |
@ -0,0 +1,94 @@ |
||||
from slither.core.cfg.node import NodeType |
||||
from slither.core.solidity_types.array_type import ArrayType |
||||
from slither.core.solidity_types.mapping_type import MappingType |
||||
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification |
||||
|
||||
|
||||
class CostlyOperationsInLoop(AbstractDetector): |
||||
|
||||
ARGUMENT = "costly-loop" |
||||
HELP = "Costly operations in a loop" |
||||
IMPACT = DetectorClassification.INFORMATIONAL |
||||
# Overall the detector seems precise, but it does not take into account |
||||
# case where there are external calls or internal calls that might read the state |
||||
# variable changes. In these cases the optimization should not be applied |
||||
CONFIDENCE = DetectorClassification.MEDIUM |
||||
|
||||
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#costly-operations-inside-a-loop" |
||||
|
||||
WIKI_TITLE = "Costly operations inside a loop" |
||||
WIKI_DESCRIPTION = ( |
||||
"Costly operations inside a loop might waste gas, so optimizations are justified." |
||||
) |
||||
WIKI_EXPLOIT_SCENARIO = """ |
||||
```solidity |
||||
contract CostlyOperationsInLoop{ |
||||
|
||||
uint loop_count = 100; |
||||
uint state_variable=0; |
||||
|
||||
function bad() external{ |
||||
for (uint i=0; i < loop_count; i++){ |
||||
state_variable++; |
||||
} |
||||
} |
||||
|
||||
function good() external{ |
||||
uint local_variable = state_variable; |
||||
for (uint i=0; i < loop_count; i++){ |
||||
local_variable++; |
||||
} |
||||
state_variable = local_variable; |
||||
} |
||||
} |
||||
``` |
||||
Incrementing `state_variable` in a loop incurs a lot of gas because of expensive `SSTOREs`, which might lead to an `out-of-gas`.""" |
||||
|
||||
WIKI_RECOMMENDATION = "Use a local variable to hold the loop computation result." |
||||
|
||||
@staticmethod |
||||
def costly_operations_in_loop(node, in_loop, visited, ret): |
||||
if node in visited: |
||||
return |
||||
# shared visited |
||||
visited.append(node) |
||||
|
||||
if node.type == NodeType.STARTLOOP: |
||||
in_loop = True |
||||
elif node.type == NodeType.ENDLOOP: |
||||
in_loop = False |
||||
|
||||
if in_loop: |
||||
sv_written = node.state_variables_written |
||||
for sv in sv_written: |
||||
# Ignore Array/Mapping/Struct types for now |
||||
if isinstance(sv.type, (ArrayType, MappingType)): |
||||
continue |
||||
ret.append(node) |
||||
break |
||||
|
||||
for son in node.sons: |
||||
CostlyOperationsInLoop.costly_operations_in_loop(son, in_loop, visited, ret) |
||||
|
||||
@staticmethod |
||||
def detect_costly_operations_in_loop(contract): |
||||
ret = [] |
||||
for f in contract.functions + contract.modifiers: |
||||
if f.contract_declarer == contract and f.is_implemented: |
||||
CostlyOperationsInLoop.costly_operations_in_loop(f.entry_point, False, [], ret) |
||||
|
||||
return ret |
||||
|
||||
def _detect(self): |
||||
"""""" |
||||
results = [] |
||||
for c in self.slither.contracts_derived: |
||||
values = self.detect_costly_operations_in_loop(c) |
||||
for node in values: |
||||
func = node.function |
||||
info = [func, " has costly operations inside a loop:\n"] |
||||
info += ["\t- ", node, "\n"] |
||||
res = self.generate_result(info) |
||||
results.append(res) |
||||
|
||||
return results |
@ -0,0 +1,82 @@ |
||||
""" |
||||
Detect deletion on structure containing a mapping |
||||
""" |
||||
|
||||
from slither.core.declarations import Structure |
||||
from slither.core.solidity_types import MappingType, UserDefinedType |
||||
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification |
||||
from slither.slithir.operations import Delete |
||||
|
||||
|
||||
class MappingDeletionDetection(AbstractDetector): |
||||
""" |
||||
Mapping deletion detector |
||||
""" |
||||
|
||||
ARGUMENT = "mapping-deletion" |
||||
HELP = "Deletion on mapping containing a structure" |
||||
IMPACT = DetectorClassification.MEDIUM |
||||
CONFIDENCE = DetectorClassification.HIGH |
||||
|
||||
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#deletion-on-mapping-containing-a-structure" |
||||
|
||||
WIKI_TITLE = "Deletion on mapping containing a structure" |
||||
WIKI_DESCRIPTION = "A deletion in a structure containing a mapping will not delete the mapping (see the [Solidity documentation](https://solidity.readthedocs.io/en/latest/types.html##delete)). The remaining data may be used to compromise the contract." |
||||
WIKI_EXPLOIT_SCENARIO = """ |
||||
```solidity |
||||
struct BalancesStruct{ |
||||
address owner; |
||||
mapping(address => uint) balances; |
||||
} |
||||
mapping(address => BalancesStruct) public stackBalance; |
||||
|
||||
function remove() internal{ |
||||
delete stackBalance[msg.sender]; |
||||
} |
||||
``` |
||||
`remove` deletes an item of `stackBalance`. |
||||
The mapping `balances` is never deleted, so `remove` does not work as intended.""" |
||||
|
||||
WIKI_RECOMMENDATION = ( |
||||
"Use a lock mechanism instead of a deletion to disable structure containing a mapping." |
||||
) |
||||
|
||||
@staticmethod |
||||
def detect_mapping_deletion(contract): |
||||
"""Detect deletion on structure containing a mapping |
||||
|
||||
Returns: |
||||
list (function, structure, node) |
||||
""" |
||||
ret = [] |
||||
# pylint: disable=too-many-nested-blocks |
||||
for f in contract.functions: |
||||
for node in f.nodes: |
||||
for ir in node.irs: |
||||
if isinstance(ir, Delete): |
||||
value = ir.variable |
||||
if isinstance(value.type, UserDefinedType) and isinstance( |
||||
value.type.type, Structure |
||||
): |
||||
st = value.type.type |
||||
if any(isinstance(e.type, MappingType) for e in st.elems.values()): |
||||
ret.append((f, st, node)) |
||||
return ret |
||||
|
||||
def _detect(self): |
||||
"""Detect mapping deletion |
||||
|
||||
Returns: |
||||
list: {'vuln', 'filename,'contract','func','struct''} |
||||
""" |
||||
results = [] |
||||
for c in self.contracts: |
||||
mapping = MappingDeletionDetection.detect_mapping_deletion(c) |
||||
for (func, struct, node) in mapping: |
||||
info = [func, " deletes ", struct, " which contains a mapping:\n"] |
||||
info += ["\t-", node, "\n"] |
||||
|
||||
res = self.generate_result(info) |
||||
results.append(res) |
||||
|
||||
return results |
@ -0,0 +1,88 @@ |
||||
""" |
||||
Module detecting redundant statements. |
||||
""" |
||||
|
||||
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification |
||||
from slither.core.cfg.node import NodeType |
||||
from slither.core.expressions.elementary_type_name_expression import ElementaryTypeNameExpression |
||||
from slither.core.expressions.identifier import Identifier |
||||
|
||||
|
||||
class RedundantStatements(AbstractDetector): |
||||
""" |
||||
Use of Redundant Statements |
||||
""" |
||||
|
||||
ARGUMENT = "redundant-statements" |
||||
HELP = "Redundant statements" |
||||
IMPACT = DetectorClassification.INFORMATIONAL |
||||
CONFIDENCE = DetectorClassification.HIGH |
||||
|
||||
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#redundant-statements" |
||||
|
||||
WIKI_TITLE = "Redundant Statements" |
||||
WIKI_DESCRIPTION = "Detect the usage of redundant statements that have no effect." |
||||
WIKI_EXPLOIT_SCENARIO = """ |
||||
```solidity |
||||
contract RedundantStatementsContract { |
||||
|
||||
constructor() public { |
||||
uint; // Elementary Type Name |
||||
bool; // Elementary Type Name |
||||
RedundantStatementsContract; // Identifier |
||||
} |
||||
|
||||
function test() public returns (uint) { |
||||
uint; // Elementary Type Name |
||||
assert; // Identifier |
||||
test; // Identifier |
||||
return 777; |
||||
} |
||||
} |
||||
``` |
||||
Each commented line references types/identifiers, but performs no action with them, so no code will be generated for such statements and they can be removed.""" |
||||
|
||||
WIKI_RECOMMENDATION = "Remove redundant statements if they congest code but offer no value." |
||||
|
||||
# This is a disallowed list of tuple (node.type, type(node.expression)) |
||||
REDUNDANT_TOP_LEVEL_EXPRESSIONS = (ElementaryTypeNameExpression, Identifier) |
||||
|
||||
def detect_redundant_statements_contract(self, contract): |
||||
"""Detects the usage of redundant statements in a contract. |
||||
|
||||
Returns: |
||||
list: nodes""" |
||||
results = [] |
||||
|
||||
# Loop through all functions + modifiers defined explicitly in this contract. |
||||
for function in contract.functions_and_modifiers_declared: |
||||
|
||||
# Loop through each node in this function. |
||||
for node in function.nodes: |
||||
if node.expression: |
||||
if node.type == NodeType.EXPRESSION and isinstance( |
||||
node.expression, self.REDUNDANT_TOP_LEVEL_EXPRESSIONS |
||||
): |
||||
results.append(node) |
||||
|
||||
return results |
||||
|
||||
def _detect(self): |
||||
"""Detect redundant statements |
||||
|
||||
Recursively visit the calls |
||||
Returns: |
||||
list: {'vuln', 'filename,'contract','func', 'redundant_statements'} |
||||
|
||||
""" |
||||
results = [] |
||||
for contract in self.contracts: |
||||
redundant_statements = self.detect_redundant_statements_contract(contract) |
||||
if redundant_statements: |
||||
|
||||
for redundant_statement in redundant_statements: |
||||
info = ['Redundant expression "', redundant_statement, '" in', contract, "\n"] |
||||
json = self.generate_result(info) |
||||
results.append(json) |
||||
|
||||
return results |
@ -0,0 +1,107 @@ |
||||
""" |
||||
Module detecting state variables initializing from an immediate function call (prior to constructor run). |
||||
""" |
||||
|
||||
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification |
||||
from slither.visitors.expression.export_values import ExportValues |
||||
from slither.core.declarations.function import Function |
||||
from slither.core.variables.state_variable import StateVariable |
||||
|
||||
|
||||
def detect_function_init_state_vars(contract): |
||||
""" |
||||
Detect any state variables that are initialized from an immediate function call (prior to constructor run). |
||||
:param contract: The contract to detect state variable definitions for. |
||||
:return: A list of all state variables defined in the given contract that meet the specified criteria. |
||||
""" |
||||
results = [] |
||||
|
||||
# Loop for each state variable explicitly defined in this contract. |
||||
for state_variable in contract.variables: |
||||
|
||||
# Skip this variable if it is inherited and not explicitly defined in this contract definition. |
||||
if state_variable.contract != contract: |
||||
continue |
||||
|
||||
# If it has an expression, we try to break it down to identify if it contains a function call, or reference |
||||
# to a non-constant state variable. |
||||
if state_variable.expression: |
||||
exported_values = ExportValues(state_variable.expression).result() |
||||
for exported_value in exported_values: |
||||
if ( |
||||
isinstance(exported_value, StateVariable) and not exported_value.is_constant |
||||
) or (isinstance(exported_value, Function) and not exported_value.pure): |
||||
results.append(state_variable) |
||||
break |
||||
|
||||
return results |
||||
|
||||
|
||||
class FunctionInitializedState(AbstractDetector): |
||||
""" |
||||
State variables initializing from an immediate function call (prior to constructor run). |
||||
""" |
||||
|
||||
ARGUMENT = "function-init-state" |
||||
HELP = "Function initializing state variables" |
||||
IMPACT = DetectorClassification.INFORMATIONAL |
||||
CONFIDENCE = DetectorClassification.HIGH |
||||
|
||||
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#function-initializing-state-variables" |
||||
|
||||
WIKI_TITLE = "Function Initializing State" |
||||
WIKI_DESCRIPTION = "Detects the immediate initialization of state variables through function calls that are not pure/constant, or that use non-constant state variable." |
||||
WIKI_EXPLOIT_SCENARIO = """ |
||||
```solidity |
||||
contract StateVarInitFromFunction { |
||||
|
||||
uint public v = set(); // Initialize from function (sets to 77) |
||||
uint public w = 5; |
||||
uint public x = set(); // Initialize from function (sets to 88) |
||||
address public shouldntBeReported = address(8); |
||||
|
||||
constructor(){ |
||||
// The constructor is run after all state variables are initialized. |
||||
} |
||||
|
||||
function set() public returns(uint) { |
||||
// If this function is being used to initialize a state variable declared |
||||
// before w, w will be zero. If it is declared after w, w will be set. |
||||
if(w == 0) { |
||||
return 77; |
||||
} |
||||
|
||||
return 88; |
||||
} |
||||
} |
||||
``` |
||||
In this case, users might intend a function to return a value a state variable can initialize with, without realizing the context for the contract is not fully initialized. |
||||
In the example above, the same function sets two different values for state variables because it checks a state variable that is not yet initialized in one case, and is initialized in the other. |
||||
Special care must be taken when initializing state variables from an immediate function call so as not to incorrectly assume the state is initialized. |
||||
""" |
||||
|
||||
WIKI_RECOMMENDATION = "Remove any initialization of state variables via non-constant state variables or function calls. If variables must be set upon contract deployment, locate initialization in the constructor instead." |
||||
|
||||
def _detect(self): |
||||
""" |
||||
Detect state variables defined from an immediate function call (pre-contract deployment). |
||||
|
||||
Recursively visit the calls |
||||
Returns: |
||||
list: {'vuln', 'filename,'contract','func', 'shadow'} |
||||
|
||||
""" |
||||
results = [] |
||||
for contract in self.contracts: |
||||
state_variables = detect_function_init_state_vars(contract) |
||||
if state_variables: |
||||
for state_variable in state_variables: |
||||
info = [ |
||||
state_variable, |
||||
" is set pre-construction with a non-constant function or state variable:\n", |
||||
] |
||||
info += [f"\t- {state_variable.expression}\n"] |
||||
json = self.generate_result(info) |
||||
results.append(json) |
||||
|
||||
return results |
@ -0,0 +1,86 @@ |
||||
""" |
||||
Check for state variables too similar |
||||
Do not check contract inheritance |
||||
""" |
||||
import difflib |
||||
|
||||
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification |
||||
|
||||
|
||||
class SimilarVarsDetection(AbstractDetector): |
||||
""" |
||||
Variable similar detector |
||||
""" |
||||
|
||||
ARGUMENT = "similar-names" |
||||
HELP = "Variable names are too similar" |
||||
IMPACT = DetectorClassification.INFORMATIONAL |
||||
CONFIDENCE = DetectorClassification.MEDIUM |
||||
|
||||
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#variable-names-are-too-similar" |
||||
|
||||
WIKI_TITLE = "Variable names too similar" |
||||
WIKI_DESCRIPTION = "Detect variables with names that are too similar." |
||||
WIKI_EXPLOIT_SCENARIO = "Bob uses several variables with similar names. As a result, his code is difficult to review." |
||||
WIKI_RECOMMENDATION = "Prevent variables from having similar names." |
||||
|
||||
@staticmethod |
||||
def similar(seq1, seq2): |
||||
"""Test the name similarity |
||||
|
||||
Two name are similar if difflib.SequenceMatcher on the lowercase |
||||
version of the name is greater than 0.90 |
||||
See: https://docs.python.org/2/library/difflib.html |
||||
Args: |
||||
seq1 (str): first name |
||||
seq2 (str): second name |
||||
Returns: |
||||
bool: true if names are similar |
||||
""" |
||||
if len(seq1) != len(seq2): |
||||
return False |
||||
val = difflib.SequenceMatcher(a=seq1.lower(), b=seq2.lower()).ratio() |
||||
ret = val > 0.90 |
||||
return ret |
||||
|
||||
@staticmethod |
||||
def detect_sim(contract): |
||||
"""Detect variables with similar name |
||||
|
||||
Returns: |
||||
bool: true if variables have similar name |
||||
""" |
||||
all_var = [x.variables for x in contract.functions] |
||||
all_var = [x for l in all_var for x in l] |
||||
|
||||
contract_var = contract.variables |
||||
|
||||
all_var = set(all_var + contract_var) |
||||
|
||||
ret = [] |
||||
for v1 in all_var: |
||||
for v2 in all_var: |
||||
if v1.name.lower() != v2.name.lower(): |
||||
if SimilarVarsDetection.similar(v1.name, v2.name): |
||||
if (v2, v1) not in ret: |
||||
ret.append((v1, v2)) |
||||
|
||||
return set(ret) |
||||
|
||||
def _detect(self): |
||||
"""Detect similar variables name |
||||
|
||||
Returns: |
||||
list: {'vuln', 'filename,'contract','vars'} |
||||
""" |
||||
results = [] |
||||
for c in self.contracts: |
||||
allVars = self.detect_sim(c) |
||||
if allVars: |
||||
for (v1, v2) in sorted(allVars, key=lambda x: (x[0].name, x[1].name)): |
||||
v_left = v1 if v1.name < v2.name else v2 |
||||
v_right = v2 if v_left == v1 else v1 |
||||
info = ["Variable ", v_left, " is too similar to ", v_right, "\n"] |
||||
json = self.generate_result(info) |
||||
results.append(json) |
||||
return results |
@ -0,0 +1,99 @@ |
||||
pragma experimental ABIEncoderV2; |
||||
|
||||
contract A { |
||||
|
||||
struct S { |
||||
uint i; |
||||
} |
||||
|
||||
uint[2][3] bad_arr = [[1, 2], [3, 4], [5, 6]]; |
||||
uint[3] good_arr = [1, 2, 3]; |
||||
S[3] s; |
||||
|
||||
event event1_bad(uint[2][3] bad_arr); |
||||
event event1_good(uint[3] good_arr); |
||||
event event2_bad(S[3] s); |
||||
|
||||
function bad0_external(uint [2][3] arr1) external { |
||||
} |
||||
|
||||
/* Array of arrays passed to an external function is vulnerable */ |
||||
function bad0() public { |
||||
this.bad0_external(bad_arr); |
||||
} |
||||
|
||||
function bad1_external (S[3] s1) external { |
||||
} |
||||
|
||||
/* Array of structs passed to an external function is vulnerable */ |
||||
function bad1 (S[3] s1) public { |
||||
this.bad1_external(s); |
||||
} |
||||
|
||||
/* Array of arrays passed to abi.encode is vulnerable */ |
||||
function bad2() public { |
||||
bytes memory b = abi.encode(bad_arr); |
||||
} |
||||
|
||||
/* Array of structs passed to abi.encode is vulnerable */ |
||||
function bad3() public { |
||||
bytes memory b = abi.encode(s); |
||||
} |
||||
|
||||
/* Array of arrays passed to an event emit is vulnerable */ |
||||
function bad4() public { |
||||
emit event1_bad(bad_arr); |
||||
} |
||||
|
||||
/* Array of structs passed to an event emit is vulnerable */ |
||||
function bad5() public { |
||||
emit event2_bad(s); |
||||
} |
||||
|
||||
function good0_public (uint[2][3] arr1) public { |
||||
} |
||||
|
||||
/* Array of arrays passed to a public function is benign */ |
||||
function good0() public { |
||||
good0_public(bad_arr); |
||||
} |
||||
|
||||
function good1_public (S[3] s1) public { |
||||
} |
||||
|
||||
/* Array of structs passed to a public function is benign */ |
||||
function good1 (S[3] s1) { |
||||
good1_public(s); |
||||
} |
||||
|
||||
/* Array of arrays in-memory passed to abi.encode is benign */ |
||||
function good2() public { |
||||
uint8 [2][3] memory bad_arr_mem = [[1, 2], [3, 4], [5, 6]]; |
||||
bytes memory b = abi.encode(bad_arr_mem); |
||||
} |
||||
|
||||
/* Array of structs in-memory passed to abi.encode is benign */ |
||||
function good3() public { |
||||
S[3] memory s_mem; |
||||
bytes memory b = abi.encode(s_mem); |
||||
} |
||||
|
||||
function good4_external(uint[3] arr1) external { |
||||
} |
||||
|
||||
/* Array of elementary types passed to external function is benign */ |
||||
function good4() public { |
||||
this.good4_external(good_arr); |
||||
} |
||||
|
||||
/* Array of elementary types passed to abi.encode is benign */ |
||||
function good5() public { |
||||
bytes memory b = abi.encode(good_arr); |
||||
} |
||||
|
||||
/* Array of elementary types passed to event emit is benign */ |
||||
function good6() public { |
||||
emit event1_good(good_arr); |
||||
} |
||||
|
||||
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,51 @@ |
||||
contract C { |
||||
uint[1] public x; |
||||
|
||||
function f() public { |
||||
setByRef(x); // can set x. |
||||
setByValue(x); // cannot set x. |
||||
uint test = 1 + setByValueAndReturn(x); // cannot set x. |
||||
} |
||||
|
||||
function g() public { |
||||
uint[1] storage y = x; |
||||
setByRef(y); // can set y. |
||||
setByValue(y); // cannot set y. |
||||
uint test = 1 + setByValueAndReturn(y); // cannot set y. |
||||
} |
||||
|
||||
function setByRef(uint[1] storage arr) internal { |
||||
arr[0] = 1; |
||||
} |
||||
|
||||
function setByValue(uint[1] arr) public { |
||||
arr[0] = 2; |
||||
} |
||||
|
||||
function setByValueAndReturn(uint[1] arr) public returns(uint) { |
||||
arr[0] = 2; |
||||
return arr[0]; |
||||
} |
||||
} |
||||
|
||||
contract D { |
||||
// Struct definition |
||||
struct TestStruct { |
||||
uint[1] x; |
||||
} |
||||
|
||||
// State Variables |
||||
TestStruct ts; |
||||
uint[1] x; |
||||
|
||||
// Functions |
||||
function f() public { |
||||
C c = new C(); |
||||
c.setByValue(ts.x); // cannot set x. |
||||
uint test = 1 + c.setByValueAndReturn(ts.x); // cannot set x. |
||||
c.setByValue(x); // cannot set x. |
||||
test = 1 + c.setByValueAndReturn(x); // cannot set x. |
||||
} |
||||
|
||||
|
||||
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,39 @@ |
||||
contract A { |
||||
|
||||
uint s_a; |
||||
|
||||
/* Direct state change in assert is NOT ok */ |
||||
function bad0() public { |
||||
assert((s_a += 1) > 10); |
||||
} |
||||
|
||||
/* Direct state change in assert is NOT ok */ |
||||
function bad1(uint256 a) public { |
||||
assert((s_a += a) > 10); |
||||
} |
||||
|
||||
/* State change via functions calls in assert is NOT ok */ |
||||
function bad2_callee() public returns (bool) { |
||||
return (s_a += 1) > 10; |
||||
} |
||||
function bad2() public { |
||||
assert(bad2_callee()); |
||||
} |
||||
|
||||
|
||||
/* Parameter use is ok */ |
||||
function good0(uint256 a) public { |
||||
assert(a > 10); |
||||
} |
||||
|
||||
/* Parameter change is ok */ |
||||
function good1(uint256 a) public { |
||||
assert((a += 1) > 10); |
||||
} |
||||
|
||||
/* State change in require is ok */ |
||||
function good2(uint256 a) public { |
||||
require(a == (s_a += 1)); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,568 @@ |
||||
[ |
||||
[ |
||||
{ |
||||
"elements": [ |
||||
{ |
||||
"type": "function", |
||||
"name": "bad0", |
||||
"source_mapping": { |
||||
"start": 77, |
||||
"length": 57, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/assert-state-change/assert_state_change.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/assert-state-change/assert_state_change.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
6, |
||||
7, |
||||
8 |
||||
], |
||||
"starting_column": 3, |
||||
"ending_column": 4 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "A", |
||||
"source_mapping": { |
||||
"start": 0, |
||||
"length": 759, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/assert-state-change/assert_state_change.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/assert-state-change/assert_state_change.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
1, |
||||
2, |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
10, |
||||
11, |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16, |
||||
17, |
||||
18, |
||||
19, |
||||
20, |
||||
21, |
||||
22, |
||||
23, |
||||
24, |
||||
25, |
||||
26, |
||||
27, |
||||
28, |
||||
29, |
||||
30, |
||||
31, |
||||
32, |
||||
33, |
||||
34, |
||||
35, |
||||
36, |
||||
37, |
||||
38, |
||||
39 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
}, |
||||
"signature": "bad0()" |
||||
} |
||||
}, |
||||
{ |
||||
"type": "node", |
||||
"name": "assert(bool)((s_a += 1) > 10)", |
||||
"source_mapping": { |
||||
"start": 106, |
||||
"length": 23, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/assert-state-change/assert_state_change.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/assert-state-change/assert_state_change.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
7 |
||||
], |
||||
"starting_column": 5, |
||||
"ending_column": 28 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "function", |
||||
"name": "bad0", |
||||
"source_mapping": { |
||||
"start": 77, |
||||
"length": 57, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/assert-state-change/assert_state_change.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/assert-state-change/assert_state_change.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
6, |
||||
7, |
||||
8 |
||||
], |
||||
"starting_column": 3, |
||||
"ending_column": 4 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "A", |
||||
"source_mapping": { |
||||
"start": 0, |
||||
"length": 759, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/assert-state-change/assert_state_change.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/assert-state-change/assert_state_change.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
1, |
||||
2, |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
10, |
||||
11, |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16, |
||||
17, |
||||
18, |
||||
19, |
||||
20, |
||||
21, |
||||
22, |
||||
23, |
||||
24, |
||||
25, |
||||
26, |
||||
27, |
||||
28, |
||||
29, |
||||
30, |
||||
31, |
||||
32, |
||||
33, |
||||
34, |
||||
35, |
||||
36, |
||||
37, |
||||
38, |
||||
39 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
}, |
||||
"signature": "bad0()" |
||||
} |
||||
} |
||||
} |
||||
} |
||||
], |
||||
"description": "A.bad0() (tests/detectors/assert-state-change/assert_state_change.sol#6-8) has an assert() call which possibly changes state.\n\t-assert(bool)((s_a += 1) > 10) (tests/detectors/assert-state-change/assert_state_change.sol#7)\nConsider using require() or change the invariant to not modify the state.\n", |
||||
"markdown": "[A.bad0()](tests/detectors/assert-state-change/assert_state_change.sol#L6-L8) has an assert() call which possibly changes state.\n\t-[assert(bool)((s_a += 1) > 10)](tests/detectors/assert-state-change/assert_state_change.sol#L7)\nConsider using require() or change the invariant to not modify the state.\n", |
||||
"id": "a4f5ea904ad28f8c83aa1bab8284b485e1fe638545b500ca0c8a0fa8e442203e", |
||||
"check": "assert-state-change", |
||||
"impact": "Informational", |
||||
"confidence": "Informational" |
||||
}, |
||||
{ |
||||
"elements": [ |
||||
{ |
||||
"type": "function", |
||||
"name": "bad1", |
||||
"source_mapping": { |
||||
"start": 186, |
||||
"length": 66, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/assert-state-change/assert_state_change.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/assert-state-change/assert_state_change.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
11, |
||||
12, |
||||
13 |
||||
], |
||||
"starting_column": 3, |
||||
"ending_column": 4 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "A", |
||||
"source_mapping": { |
||||
"start": 0, |
||||
"length": 759, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/assert-state-change/assert_state_change.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/assert-state-change/assert_state_change.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
1, |
||||
2, |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
10, |
||||
11, |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16, |
||||
17, |
||||
18, |
||||
19, |
||||
20, |
||||
21, |
||||
22, |
||||
23, |
||||
24, |
||||
25, |
||||
26, |
||||
27, |
||||
28, |
||||
29, |
||||
30, |
||||
31, |
||||
32, |
||||
33, |
||||
34, |
||||
35, |
||||
36, |
||||
37, |
||||
38, |
||||
39 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
}, |
||||
"signature": "bad1(uint256)" |
||||
} |
||||
}, |
||||
{ |
||||
"type": "node", |
||||
"name": "assert(bool)((s_a += a) > 10)", |
||||
"source_mapping": { |
||||
"start": 224, |
||||
"length": 23, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/assert-state-change/assert_state_change.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/assert-state-change/assert_state_change.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
12 |
||||
], |
||||
"starting_column": 5, |
||||
"ending_column": 28 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "function", |
||||
"name": "bad1", |
||||
"source_mapping": { |
||||
"start": 186, |
||||
"length": 66, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/assert-state-change/assert_state_change.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/assert-state-change/assert_state_change.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
11, |
||||
12, |
||||
13 |
||||
], |
||||
"starting_column": 3, |
||||
"ending_column": 4 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "A", |
||||
"source_mapping": { |
||||
"start": 0, |
||||
"length": 759, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/assert-state-change/assert_state_change.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/assert-state-change/assert_state_change.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
1, |
||||
2, |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
10, |
||||
11, |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16, |
||||
17, |
||||
18, |
||||
19, |
||||
20, |
||||
21, |
||||
22, |
||||
23, |
||||
24, |
||||
25, |
||||
26, |
||||
27, |
||||
28, |
||||
29, |
||||
30, |
||||
31, |
||||
32, |
||||
33, |
||||
34, |
||||
35, |
||||
36, |
||||
37, |
||||
38, |
||||
39 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
}, |
||||
"signature": "bad1(uint256)" |
||||
} |
||||
} |
||||
} |
||||
} |
||||
], |
||||
"description": "A.bad1(uint256) (tests/detectors/assert-state-change/assert_state_change.sol#11-13) has an assert() call which possibly changes state.\n\t-assert(bool)((s_a += a) > 10) (tests/detectors/assert-state-change/assert_state_change.sol#12)\nConsider using require() or change the invariant to not modify the state.\n", |
||||
"markdown": "[A.bad1(uint256)](tests/detectors/assert-state-change/assert_state_change.sol#L11-L13) has an assert() call which possibly changes state.\n\t-[assert(bool)((s_a += a) > 10)](tests/detectors/assert-state-change/assert_state_change.sol#L12)\nConsider using require() or change the invariant to not modify the state.\n", |
||||
"id": "2b42e9f701ebd94656a026702bf90f31c62710a301600e0c05cfed04bfefabf9", |
||||
"check": "assert-state-change", |
||||
"impact": "Informational", |
||||
"confidence": "Informational" |
||||
}, |
||||
{ |
||||
"elements": [ |
||||
{ |
||||
"type": "function", |
||||
"name": "bad2", |
||||
"source_mapping": { |
||||
"start": 398, |
||||
"length": 55, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/assert-state-change/assert_state_change.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/assert-state-change/assert_state_change.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
19, |
||||
20, |
||||
21 |
||||
], |
||||
"starting_column": 3, |
||||
"ending_column": 4 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "A", |
||||
"source_mapping": { |
||||
"start": 0, |
||||
"length": 759, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/assert-state-change/assert_state_change.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/assert-state-change/assert_state_change.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
1, |
||||
2, |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
10, |
||||
11, |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16, |
||||
17, |
||||
18, |
||||
19, |
||||
20, |
||||
21, |
||||
22, |
||||
23, |
||||
24, |
||||
25, |
||||
26, |
||||
27, |
||||
28, |
||||
29, |
||||
30, |
||||
31, |
||||
32, |
||||
33, |
||||
34, |
||||
35, |
||||
36, |
||||
37, |
||||
38, |
||||
39 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
}, |
||||
"signature": "bad2()" |
||||
} |
||||
}, |
||||
{ |
||||
"type": "node", |
||||
"name": "assert(bool)(bad2_callee())", |
||||
"source_mapping": { |
||||
"start": 427, |
||||
"length": 21, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/assert-state-change/assert_state_change.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/assert-state-change/assert_state_change.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
20 |
||||
], |
||||
"starting_column": 5, |
||||
"ending_column": 26 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "function", |
||||
"name": "bad2", |
||||
"source_mapping": { |
||||
"start": 398, |
||||
"length": 55, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/assert-state-change/assert_state_change.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/assert-state-change/assert_state_change.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
19, |
||||
20, |
||||
21 |
||||
], |
||||
"starting_column": 3, |
||||
"ending_column": 4 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "A", |
||||
"source_mapping": { |
||||
"start": 0, |
||||
"length": 759, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/assert-state-change/assert_state_change.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/assert-state-change/assert_state_change.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
1, |
||||
2, |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
10, |
||||
11, |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16, |
||||
17, |
||||
18, |
||||
19, |
||||
20, |
||||
21, |
||||
22, |
||||
23, |
||||
24, |
||||
25, |
||||
26, |
||||
27, |
||||
28, |
||||
29, |
||||
30, |
||||
31, |
||||
32, |
||||
33, |
||||
34, |
||||
35, |
||||
36, |
||||
37, |
||||
38, |
||||
39 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
}, |
||||
"signature": "bad2()" |
||||
} |
||||
} |
||||
} |
||||
} |
||||
], |
||||
"description": "A.bad2() (tests/detectors/assert-state-change/assert_state_change.sol#19-21) has an assert() call which possibly changes state.\n\t-assert(bool)(bad2_callee()) (tests/detectors/assert-state-change/assert_state_change.sol#20)\nConsider using require() or change the invariant to not modify the state.\n", |
||||
"markdown": "[A.bad2()](tests/detectors/assert-state-change/assert_state_change.sol#L19-L21) has an assert() call which possibly changes state.\n\t-[assert(bool)(bad2_callee())](tests/detectors/assert-state-change/assert_state_change.sol#L20)\nConsider using require() or change the invariant to not modify the state.\n", |
||||
"id": "a72f3e7eef408be55123fbf5c290bfd20aed4f095d659f5df0857d64d61df011", |
||||
"check": "assert-state-change", |
||||
"impact": "Informational", |
||||
"confidence": "Informational" |
||||
} |
||||
] |
||||
] |
@ -0,0 +1,568 @@ |
||||
[ |
||||
[ |
||||
{ |
||||
"elements": [ |
||||
{ |
||||
"type": "function", |
||||
"name": "bad0", |
||||
"source_mapping": { |
||||
"start": 77, |
||||
"length": 57, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/assert-state-change/assert_state_change.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/assert-state-change/assert_state_change.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
6, |
||||
7, |
||||
8 |
||||
], |
||||
"starting_column": 3, |
||||
"ending_column": 4 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "A", |
||||
"source_mapping": { |
||||
"start": 0, |
||||
"length": 759, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/assert-state-change/assert_state_change.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/assert-state-change/assert_state_change.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
1, |
||||
2, |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
10, |
||||
11, |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16, |
||||
17, |
||||
18, |
||||
19, |
||||
20, |
||||
21, |
||||
22, |
||||
23, |
||||
24, |
||||
25, |
||||
26, |
||||
27, |
||||
28, |
||||
29, |
||||
30, |
||||
31, |
||||
32, |
||||
33, |
||||
34, |
||||
35, |
||||
36, |
||||
37, |
||||
38, |
||||
39 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
}, |
||||
"signature": "bad0()" |
||||
} |
||||
}, |
||||
{ |
||||
"type": "node", |
||||
"name": "assert(bool)((s_a += 1) > 10)", |
||||
"source_mapping": { |
||||
"start": 106, |
||||
"length": 23, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/assert-state-change/assert_state_change.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/assert-state-change/assert_state_change.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
7 |
||||
], |
||||
"starting_column": 5, |
||||
"ending_column": 28 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "function", |
||||
"name": "bad0", |
||||
"source_mapping": { |
||||
"start": 77, |
||||
"length": 57, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/assert-state-change/assert_state_change.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/assert-state-change/assert_state_change.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
6, |
||||
7, |
||||
8 |
||||
], |
||||
"starting_column": 3, |
||||
"ending_column": 4 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "A", |
||||
"source_mapping": { |
||||
"start": 0, |
||||
"length": 759, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/assert-state-change/assert_state_change.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/assert-state-change/assert_state_change.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
1, |
||||
2, |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
10, |
||||
11, |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16, |
||||
17, |
||||
18, |
||||
19, |
||||
20, |
||||
21, |
||||
22, |
||||
23, |
||||
24, |
||||
25, |
||||
26, |
||||
27, |
||||
28, |
||||
29, |
||||
30, |
||||
31, |
||||
32, |
||||
33, |
||||
34, |
||||
35, |
||||
36, |
||||
37, |
||||
38, |
||||
39 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
}, |
||||
"signature": "bad0()" |
||||
} |
||||
} |
||||
} |
||||
} |
||||
], |
||||
"description": "A.bad0() (tests/detectors/assert-state-change/assert_state_change.sol#6-8) has an assert() call which possibly changes state.\n\t-assert(bool)((s_a += 1) > 10) (tests/detectors/assert-state-change/assert_state_change.sol#7)\nConsider using require() or change the invariant to not modify the state.\n", |
||||
"markdown": "[A.bad0()](tests/detectors/assert-state-change/assert_state_change.sol#L6-L8) has an assert() call which possibly changes state.\n\t-[assert(bool)((s_a += 1) > 10)](tests/detectors/assert-state-change/assert_state_change.sol#L7)\nConsider using require() or change the invariant to not modify the state.\n", |
||||
"id": "a4f5ea904ad28f8c83aa1bab8284b485e1fe638545b500ca0c8a0fa8e442203e", |
||||
"check": "assert-state-change", |
||||
"impact": "Informational", |
||||
"confidence": "Informational" |
||||
}, |
||||
{ |
||||
"elements": [ |
||||
{ |
||||
"type": "function", |
||||
"name": "bad1", |
||||
"source_mapping": { |
||||
"start": 186, |
||||
"length": 66, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/assert-state-change/assert_state_change.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/assert-state-change/assert_state_change.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
11, |
||||
12, |
||||
13 |
||||
], |
||||
"starting_column": 3, |
||||
"ending_column": 4 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "A", |
||||
"source_mapping": { |
||||
"start": 0, |
||||
"length": 759, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/assert-state-change/assert_state_change.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/assert-state-change/assert_state_change.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
1, |
||||
2, |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
10, |
||||
11, |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16, |
||||
17, |
||||
18, |
||||
19, |
||||
20, |
||||
21, |
||||
22, |
||||
23, |
||||
24, |
||||
25, |
||||
26, |
||||
27, |
||||
28, |
||||
29, |
||||
30, |
||||
31, |
||||
32, |
||||
33, |
||||
34, |
||||
35, |
||||
36, |
||||
37, |
||||
38, |
||||
39 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
}, |
||||
"signature": "bad1(uint256)" |
||||
} |
||||
}, |
||||
{ |
||||
"type": "node", |
||||
"name": "assert(bool)((s_a += a) > 10)", |
||||
"source_mapping": { |
||||
"start": 224, |
||||
"length": 23, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/assert-state-change/assert_state_change.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/assert-state-change/assert_state_change.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
12 |
||||
], |
||||
"starting_column": 5, |
||||
"ending_column": 28 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "function", |
||||
"name": "bad1", |
||||
"source_mapping": { |
||||
"start": 186, |
||||
"length": 66, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/assert-state-change/assert_state_change.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/assert-state-change/assert_state_change.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
11, |
||||
12, |
||||
13 |
||||
], |
||||
"starting_column": 3, |
||||
"ending_column": 4 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "A", |
||||
"source_mapping": { |
||||
"start": 0, |
||||
"length": 759, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/assert-state-change/assert_state_change.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/assert-state-change/assert_state_change.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
1, |
||||
2, |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
10, |
||||
11, |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16, |
||||
17, |
||||
18, |
||||
19, |
||||
20, |
||||
21, |
||||
22, |
||||
23, |
||||
24, |
||||
25, |
||||
26, |
||||
27, |
||||
28, |
||||
29, |
||||
30, |
||||
31, |
||||
32, |
||||
33, |
||||
34, |
||||
35, |
||||
36, |
||||
37, |
||||
38, |
||||
39 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
}, |
||||
"signature": "bad1(uint256)" |
||||
} |
||||
} |
||||
} |
||||
} |
||||
], |
||||
"description": "A.bad1(uint256) (tests/detectors/assert-state-change/assert_state_change.sol#11-13) has an assert() call which possibly changes state.\n\t-assert(bool)((s_a += a) > 10) (tests/detectors/assert-state-change/assert_state_change.sol#12)\nConsider using require() or change the invariant to not modify the state.\n", |
||||
"markdown": "[A.bad1(uint256)](tests/detectors/assert-state-change/assert_state_change.sol#L11-L13) has an assert() call which possibly changes state.\n\t-[assert(bool)((s_a += a) > 10)](tests/detectors/assert-state-change/assert_state_change.sol#L12)\nConsider using require() or change the invariant to not modify the state.\n", |
||||
"id": "2b42e9f701ebd94656a026702bf90f31c62710a301600e0c05cfed04bfefabf9", |
||||
"check": "assert-state-change", |
||||
"impact": "Informational", |
||||
"confidence": "Informational" |
||||
}, |
||||
{ |
||||
"elements": [ |
||||
{ |
||||
"type": "function", |
||||
"name": "bad2", |
||||
"source_mapping": { |
||||
"start": 398, |
||||
"length": 55, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/assert-state-change/assert_state_change.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/assert-state-change/assert_state_change.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
19, |
||||
20, |
||||
21 |
||||
], |
||||
"starting_column": 3, |
||||
"ending_column": 4 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "A", |
||||
"source_mapping": { |
||||
"start": 0, |
||||
"length": 759, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/assert-state-change/assert_state_change.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/assert-state-change/assert_state_change.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
1, |
||||
2, |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
10, |
||||
11, |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16, |
||||
17, |
||||
18, |
||||
19, |
||||
20, |
||||
21, |
||||
22, |
||||
23, |
||||
24, |
||||
25, |
||||
26, |
||||
27, |
||||
28, |
||||
29, |
||||
30, |
||||
31, |
||||
32, |
||||
33, |
||||
34, |
||||
35, |
||||
36, |
||||
37, |
||||
38, |
||||
39 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
}, |
||||
"signature": "bad2()" |
||||
} |
||||
}, |
||||
{ |
||||
"type": "node", |
||||
"name": "assert(bool)(bad2_callee())", |
||||
"source_mapping": { |
||||
"start": 427, |
||||
"length": 21, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/assert-state-change/assert_state_change.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/assert-state-change/assert_state_change.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
20 |
||||
], |
||||
"starting_column": 5, |
||||
"ending_column": 26 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "function", |
||||
"name": "bad2", |
||||
"source_mapping": { |
||||
"start": 398, |
||||
"length": 55, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/assert-state-change/assert_state_change.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/assert-state-change/assert_state_change.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
19, |
||||
20, |
||||
21 |
||||
], |
||||
"starting_column": 3, |
||||
"ending_column": 4 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "A", |
||||
"source_mapping": { |
||||
"start": 0, |
||||
"length": 759, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/assert-state-change/assert_state_change.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/assert-state-change/assert_state_change.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
1, |
||||
2, |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
10, |
||||
11, |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16, |
||||
17, |
||||
18, |
||||
19, |
||||
20, |
||||
21, |
||||
22, |
||||
23, |
||||
24, |
||||
25, |
||||
26, |
||||
27, |
||||
28, |
||||
29, |
||||
30, |
||||
31, |
||||
32, |
||||
33, |
||||
34, |
||||
35, |
||||
36, |
||||
37, |
||||
38, |
||||
39 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
}, |
||||
"signature": "bad2()" |
||||
} |
||||
} |
||||
} |
||||
} |
||||
], |
||||
"description": "A.bad2() (tests/detectors/assert-state-change/assert_state_change.sol#19-21) has an assert() call which possibly changes state.\n\t-assert(bool)(bad2_callee()) (tests/detectors/assert-state-change/assert_state_change.sol#20)\nConsider using require() or change the invariant to not modify the state.\n", |
||||
"markdown": "[A.bad2()](tests/detectors/assert-state-change/assert_state_change.sol#L19-L21) has an assert() call which possibly changes state.\n\t-[assert(bool)(bad2_callee())](tests/detectors/assert-state-change/assert_state_change.sol#L20)\nConsider using require() or change the invariant to not modify the state.\n", |
||||
"id": "a72f3e7eef408be55123fbf5c290bfd20aed4f095d659f5df0857d64d61df011", |
||||
"check": "assert-state-change", |
||||
"impact": "Informational", |
||||
"confidence": "Informational" |
||||
} |
||||
] |
||||
] |
@ -0,0 +1,168 @@ |
||||
[ |
||||
[ |
||||
{ |
||||
"elements": [ |
||||
{ |
||||
"type": "function", |
||||
"name": "bad1", |
||||
"source_mapping": { |
||||
"start": 134, |
||||
"length": 84, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/boolean-equality/boolean-equality.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/boolean-equality/boolean-equality.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
8, |
||||
9, |
||||
10 |
||||
], |
||||
"starting_column": 5, |
||||
"ending_column": 6 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "MyConc", |
||||
"source_mapping": { |
||||
"start": 0, |
||||
"length": 573, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/boolean-equality/boolean-equality.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/boolean-equality/boolean-equality.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
1, |
||||
2, |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
10, |
||||
11, |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16, |
||||
17, |
||||
18, |
||||
19, |
||||
20, |
||||
21, |
||||
22, |
||||
23, |
||||
24, |
||||
25, |
||||
26, |
||||
27 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
}, |
||||
"signature": "bad1(bool)" |
||||
} |
||||
}, |
||||
{ |
||||
"type": "node", |
||||
"name": "(b == true)", |
||||
"source_mapping": { |
||||
"start": 193, |
||||
"length": 18, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/boolean-equality/boolean-equality.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/boolean-equality/boolean-equality.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
9 |
||||
], |
||||
"starting_column": 9, |
||||
"ending_column": 27 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "function", |
||||
"name": "bad1", |
||||
"source_mapping": { |
||||
"start": 134, |
||||
"length": 84, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/boolean-equality/boolean-equality.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/boolean-equality/boolean-equality.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
8, |
||||
9, |
||||
10 |
||||
], |
||||
"starting_column": 5, |
||||
"ending_column": 6 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "MyConc", |
||||
"source_mapping": { |
||||
"start": 0, |
||||
"length": 573, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/boolean-equality/boolean-equality.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/boolean-equality/boolean-equality.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
1, |
||||
2, |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
10, |
||||
11, |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16, |
||||
17, |
||||
18, |
||||
19, |
||||
20, |
||||
21, |
||||
22, |
||||
23, |
||||
24, |
||||
25, |
||||
26, |
||||
27 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
}, |
||||
"signature": "bad1(bool)" |
||||
} |
||||
} |
||||
} |
||||
} |
||||
], |
||||
"description": "MyConc.bad1(bool) (tests/detectors/boolean-equality/boolean-equality.sol#8-10) compares to a boolean constant:\n\t-(b == true) (tests/detectors/boolean-equality/boolean-equality.sol#9)\n", |
||||
"markdown": "[MyConc.bad1(bool)](tests/detectors/boolean-equality/boolean-equality.sol#L8-L10) compares to a boolean constant:\n\t-[(b == true)](tests/detectors/boolean-equality/boolean-equality.sol#L9)\n", |
||||
"id": "62abb2589dfdb591044c10941ebc076ca56579e64bb3076c82c3acc761805495", |
||||
"check": "boolean-equal", |
||||
"impact": "Informational", |
||||
"confidence": "High" |
||||
} |
||||
] |
||||
] |
@ -0,0 +1,46 @@ |
||||
contract ArrayLengthAssignment { |
||||
uint x; |
||||
uint120[] arr; |
||||
uint120[] arr2; |
||||
uint256[] arr3; |
||||
constructor() public { |
||||
x = 7; |
||||
} |
||||
|
||||
struct TestStructWithArray { |
||||
uint[] x; |
||||
uint[][] y; |
||||
} |
||||
struct TestStructWithStructWithArray { |
||||
TestStructWithArray subStruct; |
||||
uint[] z; |
||||
} |
||||
|
||||
TestStructWithArray a; |
||||
TestStructWithStructWithArray b; |
||||
|
||||
function f(uint param, uint param2) public { |
||||
x += 1; |
||||
if(x > 3) { |
||||
arr.length = 7; |
||||
arr.length = param; |
||||
} |
||||
else{ |
||||
// Array length that is incremented/decremented should not be found. |
||||
x = arr2.length++; |
||||
x = 7 + 3; |
||||
} |
||||
|
||||
// Array length setting in structs should not be detected too. |
||||
a.x.length++; |
||||
a.x.length = param; |
||||
|
||||
|
||||
// Array length setting in embedded structs should not be detected too. |
||||
b.subStruct.x.length--; |
||||
b.subStruct.x.length = param + 1; |
||||
|
||||
arr3[0] = param2; |
||||
arr3.length++; |
||||
} |
||||
} |
@ -0,0 +1,604 @@ |
||||
[ |
||||
[ |
||||
{ |
||||
"elements": [ |
||||
{ |
||||
"type": "contract", |
||||
"name": "ArrayLengthAssignment", |
||||
"source_mapping": { |
||||
"start": 0, |
||||
"length": 1055, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/controlled-array-length/array_length_assignment.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/controlled-array-length/array_length_assignment.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
1, |
||||
2, |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
10, |
||||
11, |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16, |
||||
17, |
||||
18, |
||||
19, |
||||
20, |
||||
21, |
||||
22, |
||||
23, |
||||
24, |
||||
25, |
||||
26, |
||||
27, |
||||
28, |
||||
29, |
||||
30, |
||||
31, |
||||
32, |
||||
33, |
||||
34, |
||||
35, |
||||
36, |
||||
37, |
||||
38, |
||||
39, |
||||
40, |
||||
41, |
||||
42, |
||||
43, |
||||
44, |
||||
45, |
||||
46 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
}, |
||||
{ |
||||
"type": "node", |
||||
"name": "b.subStruct.x.length = param + 1", |
||||
"source_mapping": { |
||||
"start": 964, |
||||
"length": 32, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/controlled-array-length/array_length_assignment.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/controlled-array-length/array_length_assignment.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
41 |
||||
], |
||||
"starting_column": 9, |
||||
"ending_column": 41 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "function", |
||||
"name": "f", |
||||
"source_mapping": { |
||||
"start": 406, |
||||
"length": 647, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/controlled-array-length/array_length_assignment.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/controlled-array-length/array_length_assignment.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
22, |
||||
23, |
||||
24, |
||||
25, |
||||
26, |
||||
27, |
||||
28, |
||||
29, |
||||
30, |
||||
31, |
||||
32, |
||||
33, |
||||
34, |
||||
35, |
||||
36, |
||||
37, |
||||
38, |
||||
39, |
||||
40, |
||||
41, |
||||
42, |
||||
43, |
||||
44, |
||||
45 |
||||
], |
||||
"starting_column": 5, |
||||
"ending_column": 6 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "ArrayLengthAssignment", |
||||
"source_mapping": { |
||||
"start": 0, |
||||
"length": 1055, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/controlled-array-length/array_length_assignment.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/controlled-array-length/array_length_assignment.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
1, |
||||
2, |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
10, |
||||
11, |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16, |
||||
17, |
||||
18, |
||||
19, |
||||
20, |
||||
21, |
||||
22, |
||||
23, |
||||
24, |
||||
25, |
||||
26, |
||||
27, |
||||
28, |
||||
29, |
||||
30, |
||||
31, |
||||
32, |
||||
33, |
||||
34, |
||||
35, |
||||
36, |
||||
37, |
||||
38, |
||||
39, |
||||
40, |
||||
41, |
||||
42, |
||||
43, |
||||
44, |
||||
45, |
||||
46 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
}, |
||||
"signature": "f(uint256,uint256)" |
||||
} |
||||
} |
||||
} |
||||
} |
||||
], |
||||
"description": "ArrayLengthAssignment (tests/detectors/controlled-array-length/array_length_assignment.sol#1-46) contract sets array length with a user-controlled value:\n\t- b.subStruct.x.length = param + 1 (tests/detectors/controlled-array-length/array_length_assignment.sol#41)\n", |
||||
"markdown": "[ArrayLengthAssignment](tests/detectors/controlled-array-length/array_length_assignment.sol#L1-L46) contract sets array length with a user-controlled value:\n\t- [b.subStruct.x.length = param + 1](tests/detectors/controlled-array-length/array_length_assignment.sol#L41)\n", |
||||
"id": "15164b2025ba6106829ae6e7baa9a73e931c0aa3e16a8d95ee30158667b4b7f5", |
||||
"check": "controlled-array-length", |
||||
"impact": "High", |
||||
"confidence": "Medium" |
||||
}, |
||||
{ |
||||
"elements": [ |
||||
{ |
||||
"type": "contract", |
||||
"name": "ArrayLengthAssignment", |
||||
"source_mapping": { |
||||
"start": 0, |
||||
"length": 1055, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/controlled-array-length/array_length_assignment.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/controlled-array-length/array_length_assignment.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
1, |
||||
2, |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
10, |
||||
11, |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16, |
||||
17, |
||||
18, |
||||
19, |
||||
20, |
||||
21, |
||||
22, |
||||
23, |
||||
24, |
||||
25, |
||||
26, |
||||
27, |
||||
28, |
||||
29, |
||||
30, |
||||
31, |
||||
32, |
||||
33, |
||||
34, |
||||
35, |
||||
36, |
||||
37, |
||||
38, |
||||
39, |
||||
40, |
||||
41, |
||||
42, |
||||
43, |
||||
44, |
||||
45, |
||||
46 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
}, |
||||
{ |
||||
"type": "node", |
||||
"name": "arr.length = param", |
||||
"source_mapping": { |
||||
"start": 527, |
||||
"length": 18, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/controlled-array-length/array_length_assignment.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/controlled-array-length/array_length_assignment.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
26 |
||||
], |
||||
"starting_column": 13, |
||||
"ending_column": 31 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "function", |
||||
"name": "f", |
||||
"source_mapping": { |
||||
"start": 406, |
||||
"length": 647, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/controlled-array-length/array_length_assignment.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/controlled-array-length/array_length_assignment.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
22, |
||||
23, |
||||
24, |
||||
25, |
||||
26, |
||||
27, |
||||
28, |
||||
29, |
||||
30, |
||||
31, |
||||
32, |
||||
33, |
||||
34, |
||||
35, |
||||
36, |
||||
37, |
||||
38, |
||||
39, |
||||
40, |
||||
41, |
||||
42, |
||||
43, |
||||
44, |
||||
45 |
||||
], |
||||
"starting_column": 5, |
||||
"ending_column": 6 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "ArrayLengthAssignment", |
||||
"source_mapping": { |
||||
"start": 0, |
||||
"length": 1055, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/controlled-array-length/array_length_assignment.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/controlled-array-length/array_length_assignment.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
1, |
||||
2, |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
10, |
||||
11, |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16, |
||||
17, |
||||
18, |
||||
19, |
||||
20, |
||||
21, |
||||
22, |
||||
23, |
||||
24, |
||||
25, |
||||
26, |
||||
27, |
||||
28, |
||||
29, |
||||
30, |
||||
31, |
||||
32, |
||||
33, |
||||
34, |
||||
35, |
||||
36, |
||||
37, |
||||
38, |
||||
39, |
||||
40, |
||||
41, |
||||
42, |
||||
43, |
||||
44, |
||||
45, |
||||
46 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
}, |
||||
"signature": "f(uint256,uint256)" |
||||
} |
||||
} |
||||
} |
||||
} |
||||
], |
||||
"description": "ArrayLengthAssignment (tests/detectors/controlled-array-length/array_length_assignment.sol#1-46) contract sets array length with a user-controlled value:\n\t- arr.length = param (tests/detectors/controlled-array-length/array_length_assignment.sol#26)\n", |
||||
"markdown": "[ArrayLengthAssignment](tests/detectors/controlled-array-length/array_length_assignment.sol#L1-L46) contract sets array length with a user-controlled value:\n\t- [arr.length = param](tests/detectors/controlled-array-length/array_length_assignment.sol#L26)\n", |
||||
"id": "cb96ef1555863b421997853215ad3533faaffd35215987c6a2ebf21716d9bd1a", |
||||
"check": "controlled-array-length", |
||||
"impact": "High", |
||||
"confidence": "Medium" |
||||
}, |
||||
{ |
||||
"elements": [ |
||||
{ |
||||
"type": "contract", |
||||
"name": "ArrayLengthAssignment", |
||||
"source_mapping": { |
||||
"start": 0, |
||||
"length": 1055, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/controlled-array-length/array_length_assignment.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/controlled-array-length/array_length_assignment.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
1, |
||||
2, |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
10, |
||||
11, |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16, |
||||
17, |
||||
18, |
||||
19, |
||||
20, |
||||
21, |
||||
22, |
||||
23, |
||||
24, |
||||
25, |
||||
26, |
||||
27, |
||||
28, |
||||
29, |
||||
30, |
||||
31, |
||||
32, |
||||
33, |
||||
34, |
||||
35, |
||||
36, |
||||
37, |
||||
38, |
||||
39, |
||||
40, |
||||
41, |
||||
42, |
||||
43, |
||||
44, |
||||
45, |
||||
46 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
}, |
||||
{ |
||||
"type": "node", |
||||
"name": "a.x.length = param", |
||||
"source_mapping": { |
||||
"start": 818, |
||||
"length": 18, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/controlled-array-length/array_length_assignment.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/controlled-array-length/array_length_assignment.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
36 |
||||
], |
||||
"starting_column": 9, |
||||
"ending_column": 27 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "function", |
||||
"name": "f", |
||||
"source_mapping": { |
||||
"start": 406, |
||||
"length": 647, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/controlled-array-length/array_length_assignment.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/controlled-array-length/array_length_assignment.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
22, |
||||
23, |
||||
24, |
||||
25, |
||||
26, |
||||
27, |
||||
28, |
||||
29, |
||||
30, |
||||
31, |
||||
32, |
||||
33, |
||||
34, |
||||
35, |
||||
36, |
||||
37, |
||||
38, |
||||
39, |
||||
40, |
||||
41, |
||||
42, |
||||
43, |
||||
44, |
||||
45 |
||||
], |
||||
"starting_column": 5, |
||||
"ending_column": 6 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "ArrayLengthAssignment", |
||||
"source_mapping": { |
||||
"start": 0, |
||||
"length": 1055, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/controlled-array-length/array_length_assignment.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/controlled-array-length/array_length_assignment.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
1, |
||||
2, |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
10, |
||||
11, |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16, |
||||
17, |
||||
18, |
||||
19, |
||||
20, |
||||
21, |
||||
22, |
||||
23, |
||||
24, |
||||
25, |
||||
26, |
||||
27, |
||||
28, |
||||
29, |
||||
30, |
||||
31, |
||||
32, |
||||
33, |
||||
34, |
||||
35, |
||||
36, |
||||
37, |
||||
38, |
||||
39, |
||||
40, |
||||
41, |
||||
42, |
||||
43, |
||||
44, |
||||
45, |
||||
46 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
}, |
||||
"signature": "f(uint256,uint256)" |
||||
} |
||||
} |
||||
} |
||||
} |
||||
], |
||||
"description": "ArrayLengthAssignment (tests/detectors/controlled-array-length/array_length_assignment.sol#1-46) contract sets array length with a user-controlled value:\n\t- a.x.length = param (tests/detectors/controlled-array-length/array_length_assignment.sol#36)\n", |
||||
"markdown": "[ArrayLengthAssignment](tests/detectors/controlled-array-length/array_length_assignment.sol#L1-L46) contract sets array length with a user-controlled value:\n\t- [a.x.length = param](tests/detectors/controlled-array-length/array_length_assignment.sol#L36)\n", |
||||
"id": "6a72386e40ef24dd02adf92179022559e26da5e66be4bb925d02756f90f38953", |
||||
"check": "controlled-array-length", |
||||
"impact": "High", |
||||
"confidence": "Medium" |
||||
} |
||||
] |
||||
] |
@ -0,0 +1,35 @@ |
||||
pragma solidity ^0.4.24; |
||||
|
||||
contract CostlyOperationsInLoop{ |
||||
|
||||
uint loop_count = 100; |
||||
uint state_variable=0; |
||||
mapping (uint=>uint) map; |
||||
uint[100] arr; |
||||
|
||||
function bad() external{ |
||||
for (uint i=0; i < loop_count; i++){ |
||||
state_variable++; |
||||
} |
||||
} |
||||
|
||||
function ignore_for_now1() external { |
||||
for (uint i=0; i < 100; i++){ |
||||
map[i] = i+1; |
||||
} |
||||
} |
||||
|
||||
function ignore_for_now2() external { |
||||
for (uint i=0; i < 100; i++){ |
||||
arr[i] = i+1; |
||||
} |
||||
} |
||||
|
||||
function good() external{ |
||||
uint local_variable = state_variable; |
||||
for (uint i=0; i < loop_count; i++){ |
||||
local_variable++; |
||||
} |
||||
state_variable = local_variable; |
||||
} |
||||
} |
@ -0,0 +1,184 @@ |
||||
[ |
||||
[ |
||||
{ |
||||
"elements": [ |
||||
{ |
||||
"type": "function", |
||||
"name": "bad", |
||||
"source_mapping": { |
||||
"start": 252, |
||||
"length": 373, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/costly-loop/multiple_costly_operations_in_loop.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/costly-loop/multiple_costly_operations_in_loop.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
10, |
||||
11, |
||||
12, |
||||
13, |
||||
14 |
||||
], |
||||
"starting_column": 3, |
||||
"ending_column": 4 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "CostlyOperationsInLoop", |
||||
"source_mapping": { |
||||
"start": 26, |
||||
"length": 1081, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/costly-loop/multiple_costly_operations_in_loop.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/costly-loop/multiple_costly_operations_in_loop.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
10, |
||||
11, |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16, |
||||
17, |
||||
18, |
||||
19, |
||||
20, |
||||
21, |
||||
22, |
||||
23, |
||||
24, |
||||
25, |
||||
26, |
||||
27, |
||||
28, |
||||
29, |
||||
30, |
||||
31, |
||||
32, |
||||
33, |
||||
34, |
||||
35 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
}, |
||||
"signature": "bad()" |
||||
} |
||||
}, |
||||
{ |
||||
"type": "node", |
||||
"name": "state_variable ++", |
||||
"source_mapping": { |
||||
"start": 410, |
||||
"length": 16, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/costly-loop/multiple_costly_operations_in_loop.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/costly-loop/multiple_costly_operations_in_loop.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
12 |
||||
], |
||||
"starting_column": 7, |
||||
"ending_column": 23 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "function", |
||||
"name": "bad", |
||||
"source_mapping": { |
||||
"start": 252, |
||||
"length": 373, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/costly-loop/multiple_costly_operations_in_loop.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/costly-loop/multiple_costly_operations_in_loop.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
10, |
||||
11, |
||||
12, |
||||
13, |
||||
14 |
||||
], |
||||
"starting_column": 3, |
||||
"ending_column": 4 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "CostlyOperationsInLoop", |
||||
"source_mapping": { |
||||
"start": 26, |
||||
"length": 1081, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/costly-loop/multiple_costly_operations_in_loop.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/costly-loop/multiple_costly_operations_in_loop.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
10, |
||||
11, |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16, |
||||
17, |
||||
18, |
||||
19, |
||||
20, |
||||
21, |
||||
22, |
||||
23, |
||||
24, |
||||
25, |
||||
26, |
||||
27, |
||||
28, |
||||
29, |
||||
30, |
||||
31, |
||||
32, |
||||
33, |
||||
34, |
||||
35 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
}, |
||||
"signature": "bad()" |
||||
} |
||||
} |
||||
} |
||||
} |
||||
], |
||||
"description": "CostlyOperationsInLoop.bad() (tests/detectors/costly-loop/multiple_costly_operations_in_loop.sol#10-14) has costly operations inside a loop:\n\t- state_variable ++ (tests/detectors/costly-loop/multiple_costly_operations_in_loop.sol#12)\n", |
||||
"markdown": "[CostlyOperationsInLoop.bad()](tests/detectors/costly-loop/multiple_costly_operations_in_loop.sol#L10-L14) has costly operations inside a loop:\n\t- [state_variable ++](tests/detectors/costly-loop/multiple_costly_operations_in_loop.sol#L12)\n", |
||||
"id": "245dbe07302f785326efd84e8b711d1691f045726e1098601f7e1058f1e72b2a", |
||||
"check": "costly-loop", |
||||
"impact": "Informational", |
||||
"confidence": "Medium" |
||||
} |
||||
] |
||||
] |
@ -0,0 +1,46 @@ |
||||
// This tests the detection of initializing a state variable using a non-constant function call or state variable. |
||||
|
||||
contract StateVarInitFromFunction { |
||||
|
||||
uint public v = set(); // should be flagged, initialized from function (sets to 77) |
||||
uint public w = 5; |
||||
uint public x = set(); // should be flagged, initialized from function (sets to 88) |
||||
|
||||
uint public y1 = 5 + get(); // should be flagged, initialized from function (in expression) |
||||
uint public y2 = (10 + (5 + get())); // should be flagged, initialized from function (in expression) |
||||
|
||||
uint public z1 = 5 + getPure(); // should not be flagged, is a pure function |
||||
uint public z2 = (10 + (5 + getPure())); // should not be flagged, is a pure function |
||||
|
||||
uint constant public c1 = 40; |
||||
uint public z3 = c1 + 5; // should not be flagged, references a constant |
||||
uint public z4 = z3 + 5; // should be flagged, uses a non-constant state variable. |
||||
|
||||
address public shouldntBeReported = address(8); // should not be flagged, not a *real* function call. |
||||
uint public constructorV; |
||||
uint public constructorX; |
||||
|
||||
constructor(){ |
||||
// By the time this code is hit, all state variable initialization has completed. |
||||
constructorV = v; |
||||
constructorX = x; |
||||
} |
||||
|
||||
function set() public returns(uint) { |
||||
// If this function is being used to initialize a state variable before w, w will be zero. |
||||
// If it is declared after w, w will be set. |
||||
if(w == 0) { |
||||
return 77; |
||||
} |
||||
|
||||
return 88; |
||||
} |
||||
|
||||
function get() public returns(uint) { |
||||
return 55; |
||||
} |
||||
|
||||
function getPure() public pure returns(uint) { |
||||
return 55; |
||||
} |
||||
} |
@ -0,0 +1,464 @@ |
||||
[ |
||||
[ |
||||
{ |
||||
"elements": [ |
||||
{ |
||||
"type": "variable", |
||||
"name": "v", |
||||
"source_mapping": { |
||||
"start": 157, |
||||
"length": 21, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/function-init-state/function_init_state_variables.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/function-init-state/function_init_state_variables.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
5 |
||||
], |
||||
"starting_column": 5, |
||||
"ending_column": 26 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "StateVarInitFromFunction", |
||||
"source_mapping": { |
||||
"start": 116, |
||||
"length": 1567, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/function-init-state/function_init_state_variables.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/function-init-state/function_init_state_variables.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
10, |
||||
11, |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16, |
||||
17, |
||||
18, |
||||
19, |
||||
20, |
||||
21, |
||||
22, |
||||
23, |
||||
24, |
||||
25, |
||||
26, |
||||
27, |
||||
28, |
||||
29, |
||||
30, |
||||
31, |
||||
32, |
||||
33, |
||||
34, |
||||
35, |
||||
36, |
||||
37, |
||||
38, |
||||
39, |
||||
40, |
||||
41, |
||||
42, |
||||
43, |
||||
44, |
||||
45, |
||||
46, |
||||
47 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 0 |
||||
} |
||||
} |
||||
} |
||||
} |
||||
], |
||||
"description": "StateVarInitFromFunction.v (tests/detectors/function-init-state/function_init_state_variables.sol#5) is set pre-construction with a non-constant function or state variable:\n\t- set()\n", |
||||
"markdown": "[StateVarInitFromFunction.v](tests/detectors/function-init-state/function_init_state_variables.sol#L5) is set pre-construction with a non-constant function or state variable:\n\t- set()\n", |
||||
"id": "4b87ea4c0a3b72be79ffde12c56c9dc7440445b79ff4b228e0937b3a05540e4b", |
||||
"check": "function-init-state", |
||||
"impact": "Informational", |
||||
"confidence": "High" |
||||
}, |
||||
{ |
||||
"elements": [ |
||||
{ |
||||
"type": "variable", |
||||
"name": "x", |
||||
"source_mapping": { |
||||
"start": 268, |
||||
"length": 21, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/function-init-state/function_init_state_variables.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/function-init-state/function_init_state_variables.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
7 |
||||
], |
||||
"starting_column": 5, |
||||
"ending_column": 26 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "StateVarInitFromFunction", |
||||
"source_mapping": { |
||||
"start": 116, |
||||
"length": 1567, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/function-init-state/function_init_state_variables.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/function-init-state/function_init_state_variables.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
10, |
||||
11, |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16, |
||||
17, |
||||
18, |
||||
19, |
||||
20, |
||||
21, |
||||
22, |
||||
23, |
||||
24, |
||||
25, |
||||
26, |
||||
27, |
||||
28, |
||||
29, |
||||
30, |
||||
31, |
||||
32, |
||||
33, |
||||
34, |
||||
35, |
||||
36, |
||||
37, |
||||
38, |
||||
39, |
||||
40, |
||||
41, |
||||
42, |
||||
43, |
||||
44, |
||||
45, |
||||
46, |
||||
47 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 0 |
||||
} |
||||
} |
||||
} |
||||
} |
||||
], |
||||
"description": "StateVarInitFromFunction.x (tests/detectors/function-init-state/function_init_state_variables.sol#7) is set pre-construction with a non-constant function or state variable:\n\t- set()\n", |
||||
"markdown": "[StateVarInitFromFunction.x](tests/detectors/function-init-state/function_init_state_variables.sol#L7) is set pre-construction with a non-constant function or state variable:\n\t- set()\n", |
||||
"id": "adfa394934c8669a556cfa10c364fe526dd1e295a63959e1e88fe84a919ef354", |
||||
"check": "function-init-state", |
||||
"impact": "Informational", |
||||
"confidence": "High" |
||||
}, |
||||
{ |
||||
"elements": [ |
||||
{ |
||||
"type": "variable", |
||||
"name": "y1", |
||||
"source_mapping": { |
||||
"start": 357, |
||||
"length": 26, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/function-init-state/function_init_state_variables.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/function-init-state/function_init_state_variables.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
9 |
||||
], |
||||
"starting_column": 5, |
||||
"ending_column": 31 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "StateVarInitFromFunction", |
||||
"source_mapping": { |
||||
"start": 116, |
||||
"length": 1567, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/function-init-state/function_init_state_variables.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/function-init-state/function_init_state_variables.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
10, |
||||
11, |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16, |
||||
17, |
||||
18, |
||||
19, |
||||
20, |
||||
21, |
||||
22, |
||||
23, |
||||
24, |
||||
25, |
||||
26, |
||||
27, |
||||
28, |
||||
29, |
||||
30, |
||||
31, |
||||
32, |
||||
33, |
||||
34, |
||||
35, |
||||
36, |
||||
37, |
||||
38, |
||||
39, |
||||
40, |
||||
41, |
||||
42, |
||||
43, |
||||
44, |
||||
45, |
||||
46, |
||||
47 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 0 |
||||
} |
||||
} |
||||
} |
||||
} |
||||
], |
||||
"description": "StateVarInitFromFunction.y1 (tests/detectors/function-init-state/function_init_state_variables.sol#9) is set pre-construction with a non-constant function or state variable:\n\t- 5 + get()\n", |
||||
"markdown": "[StateVarInitFromFunction.y1](tests/detectors/function-init-state/function_init_state_variables.sol#L9) is set pre-construction with a non-constant function or state variable:\n\t- 5 + get()\n", |
||||
"id": "b26f83c06e9aca87637dea02a0f4080fd4226c1ed90c6c2c63da85cb142d67ab", |
||||
"check": "function-init-state", |
||||
"impact": "Informational", |
||||
"confidence": "High" |
||||
}, |
||||
{ |
||||
"elements": [ |
||||
{ |
||||
"type": "variable", |
||||
"name": "y2", |
||||
"source_mapping": { |
||||
"start": 453, |
||||
"length": 35, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/function-init-state/function_init_state_variables.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/function-init-state/function_init_state_variables.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
10 |
||||
], |
||||
"starting_column": 5, |
||||
"ending_column": 40 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "StateVarInitFromFunction", |
||||
"source_mapping": { |
||||
"start": 116, |
||||
"length": 1567, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/function-init-state/function_init_state_variables.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/function-init-state/function_init_state_variables.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
10, |
||||
11, |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16, |
||||
17, |
||||
18, |
||||
19, |
||||
20, |
||||
21, |
||||
22, |
||||
23, |
||||
24, |
||||
25, |
||||
26, |
||||
27, |
||||
28, |
||||
29, |
||||
30, |
||||
31, |
||||
32, |
||||
33, |
||||
34, |
||||
35, |
||||
36, |
||||
37, |
||||
38, |
||||
39, |
||||
40, |
||||
41, |
||||
42, |
||||
43, |
||||
44, |
||||
45, |
||||
46, |
||||
47 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 0 |
||||
} |
||||
} |
||||
} |
||||
} |
||||
], |
||||
"description": "StateVarInitFromFunction.y2 (tests/detectors/function-init-state/function_init_state_variables.sol#10) is set pre-construction with a non-constant function or state variable:\n\t- (10 + (5 + get()))\n", |
||||
"markdown": "[StateVarInitFromFunction.y2](tests/detectors/function-init-state/function_init_state_variables.sol#L10) is set pre-construction with a non-constant function or state variable:\n\t- (10 + (5 + get()))\n", |
||||
"id": "b6e231b9b735794e00b73dddb86b2ba8f7a738d916c99f302fb32b1095c67472", |
||||
"check": "function-init-state", |
||||
"impact": "Informational", |
||||
"confidence": "High" |
||||
}, |
||||
{ |
||||
"elements": [ |
||||
{ |
||||
"type": "variable", |
||||
"name": "z4", |
||||
"source_mapping": { |
||||
"start": 842, |
||||
"length": 23, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/function-init-state/function_init_state_variables.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/function-init-state/function_init_state_variables.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
17 |
||||
], |
||||
"starting_column": 5, |
||||
"ending_column": 28 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "StateVarInitFromFunction", |
||||
"source_mapping": { |
||||
"start": 116, |
||||
"length": 1567, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/function-init-state/function_init_state_variables.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/function-init-state/function_init_state_variables.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
10, |
||||
11, |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16, |
||||
17, |
||||
18, |
||||
19, |
||||
20, |
||||
21, |
||||
22, |
||||
23, |
||||
24, |
||||
25, |
||||
26, |
||||
27, |
||||
28, |
||||
29, |
||||
30, |
||||
31, |
||||
32, |
||||
33, |
||||
34, |
||||
35, |
||||
36, |
||||
37, |
||||
38, |
||||
39, |
||||
40, |
||||
41, |
||||
42, |
||||
43, |
||||
44, |
||||
45, |
||||
46, |
||||
47 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 0 |
||||
} |
||||
} |
||||
} |
||||
} |
||||
], |
||||
"description": "StateVarInitFromFunction.z4 (tests/detectors/function-init-state/function_init_state_variables.sol#17) is set pre-construction with a non-constant function or state variable:\n\t- z3 + 5\n", |
||||
"markdown": "[StateVarInitFromFunction.z4](tests/detectors/function-init-state/function_init_state_variables.sol#L17) is set pre-construction with a non-constant function or state variable:\n\t- z3 + 5\n", |
||||
"id": "8b7eb9ab16397c2f23479d2c3043a675ab5e2b1da07e2697631812d6d7b68525", |
||||
"check": "function-init-state", |
||||
"impact": "Informational", |
||||
"confidence": "High" |
||||
} |
||||
] |
||||
] |
@ -0,0 +1,43 @@ |
||||
pragma solidity ^0.4.24; |
||||
|
||||
library Lib{ |
||||
|
||||
struct MyStruct{ |
||||
mapping(address => uint) maps; |
||||
} |
||||
|
||||
function deleteSt(MyStruct[1] storage st){ |
||||
delete st[0]; |
||||
} |
||||
|
||||
} |
||||
|
||||
contract Balances { |
||||
|
||||
struct BalancesStruct{ |
||||
address owner; |
||||
mapping(address => uint) balances; |
||||
} |
||||
|
||||
mapping(uint => BalancesStruct) public stackBalance; |
||||
function createBalance(uint idx) public { |
||||
require(stackBalance[idx].owner == 0); |
||||
stackBalance[idx] = BalancesStruct(msg.sender); |
||||
} |
||||
|
||||
function deleteBalance(uint idx) public { |
||||
require(stackBalance[idx].owner == msg.sender); |
||||
delete stackBalance[idx]; |
||||
} |
||||
|
||||
function setBalance(uint idx, address addr, uint val) public { |
||||
require(stackBalance[idx].owner == msg.sender); |
||||
|
||||
stackBalance[idx].balances[addr] = val; |
||||
} |
||||
|
||||
function getBalance(uint idx, address addr) public view returns(uint){ |
||||
return stackBalance[idx].balances[addr]; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,425 @@ |
||||
[ |
||||
[ |
||||
{ |
||||
"elements": [ |
||||
{ |
||||
"type": "function", |
||||
"name": "deleteSt", |
||||
"source_mapping": { |
||||
"start": 111, |
||||
"length": 70, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/mapping-deletion/MappingDeletion.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/mapping-deletion/MappingDeletion.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
9, |
||||
10, |
||||
11 |
||||
], |
||||
"starting_column": 5, |
||||
"ending_column": 6 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "Lib", |
||||
"source_mapping": { |
||||
"start": 26, |
||||
"length": 158, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/mapping-deletion/MappingDeletion.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/mapping-deletion/MappingDeletion.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
10, |
||||
11, |
||||
12, |
||||
13 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
}, |
||||
"signature": "deleteSt(Lib.MyStruct[1])" |
||||
} |
||||
}, |
||||
{ |
||||
"type": "struct", |
||||
"name": "MyStruct", |
||||
"source_mapping": { |
||||
"start": 44, |
||||
"length": 61, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/mapping-deletion/MappingDeletion.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/mapping-deletion/MappingDeletion.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
5, |
||||
6, |
||||
7 |
||||
], |
||||
"starting_column": 5, |
||||
"ending_column": 6 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "Lib", |
||||
"source_mapping": { |
||||
"start": 26, |
||||
"length": 158, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/mapping-deletion/MappingDeletion.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/mapping-deletion/MappingDeletion.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
10, |
||||
11, |
||||
12, |
||||
13 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
} |
||||
} |
||||
}, |
||||
{ |
||||
"type": "node", |
||||
"name": "delete st[0]", |
||||
"source_mapping": { |
||||
"start": 162, |
||||
"length": 12, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/mapping-deletion/MappingDeletion.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/mapping-deletion/MappingDeletion.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
10 |
||||
], |
||||
"starting_column": 9, |
||||
"ending_column": 21 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "function", |
||||
"name": "deleteSt", |
||||
"source_mapping": { |
||||
"start": 111, |
||||
"length": 70, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/mapping-deletion/MappingDeletion.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/mapping-deletion/MappingDeletion.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
9, |
||||
10, |
||||
11 |
||||
], |
||||
"starting_column": 5, |
||||
"ending_column": 6 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "Lib", |
||||
"source_mapping": { |
||||
"start": 26, |
||||
"length": 158, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/mapping-deletion/MappingDeletion.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/mapping-deletion/MappingDeletion.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
10, |
||||
11, |
||||
12, |
||||
13 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
}, |
||||
"signature": "deleteSt(Lib.MyStruct[1])" |
||||
} |
||||
} |
||||
} |
||||
} |
||||
], |
||||
"description": "Lib.deleteSt(Lib.MyStruct[1]) (tests/detectors/mapping-deletion/MappingDeletion.sol#9-11) deletes Lib.MyStruct (tests/detectors/mapping-deletion/MappingDeletion.sol#5-7) which contains a mapping:\n\t-delete st[0] (tests/detectors/mapping-deletion/MappingDeletion.sol#10)\n", |
||||
"markdown": "[Lib.deleteSt(Lib.MyStruct[1])](tests/detectors/mapping-deletion/MappingDeletion.sol#L9-L11) deletes [Lib.MyStruct](tests/detectors/mapping-deletion/MappingDeletion.sol#L5-L7) which contains a mapping:\n\t-[delete st[0]](tests/detectors/mapping-deletion/MappingDeletion.sol#L10)\n", |
||||
"id": "d618551637c257938461c33070c5339207b75de2bb11ff88d92bd9679252f307", |
||||
"check": "mapping-deletion", |
||||
"impact": "Medium", |
||||
"confidence": "High" |
||||
}, |
||||
{ |
||||
"elements": [ |
||||
{ |
||||
"type": "function", |
||||
"name": "deleteBalance", |
||||
"source_mapping": { |
||||
"start": 541, |
||||
"length": 137, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/mapping-deletion/MappingDeletion.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/mapping-deletion/MappingDeletion.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
28, |
||||
29, |
||||
30, |
||||
31 |
||||
], |
||||
"starting_column": 5, |
||||
"ending_column": 6 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "Balances", |
||||
"source_mapping": { |
||||
"start": 186, |
||||
"length": 825, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/mapping-deletion/MappingDeletion.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/mapping-deletion/MappingDeletion.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
15, |
||||
16, |
||||
17, |
||||
18, |
||||
19, |
||||
20, |
||||
21, |
||||
22, |
||||
23, |
||||
24, |
||||
25, |
||||
26, |
||||
27, |
||||
28, |
||||
29, |
||||
30, |
||||
31, |
||||
32, |
||||
33, |
||||
34, |
||||
35, |
||||
36, |
||||
37, |
||||
38, |
||||
39, |
||||
40, |
||||
41, |
||||
42, |
||||
43 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
}, |
||||
"signature": "deleteBalance(uint256)" |
||||
} |
||||
}, |
||||
{ |
||||
"type": "struct", |
||||
"name": "BalancesStruct", |
||||
"source_mapping": { |
||||
"start": 215, |
||||
"length": 94, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/mapping-deletion/MappingDeletion.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/mapping-deletion/MappingDeletion.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
17, |
||||
18, |
||||
19, |
||||
20 |
||||
], |
||||
"starting_column": 5, |
||||
"ending_column": 6 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "Balances", |
||||
"source_mapping": { |
||||
"start": 186, |
||||
"length": 825, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/mapping-deletion/MappingDeletion.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/mapping-deletion/MappingDeletion.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
15, |
||||
16, |
||||
17, |
||||
18, |
||||
19, |
||||
20, |
||||
21, |
||||
22, |
||||
23, |
||||
24, |
||||
25, |
||||
26, |
||||
27, |
||||
28, |
||||
29, |
||||
30, |
||||
31, |
||||
32, |
||||
33, |
||||
34, |
||||
35, |
||||
36, |
||||
37, |
||||
38, |
||||
39, |
||||
40, |
||||
41, |
||||
42, |
||||
43 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
} |
||||
} |
||||
}, |
||||
{ |
||||
"type": "node", |
||||
"name": "delete stackBalance[idx]", |
||||
"source_mapping": { |
||||
"start": 647, |
||||
"length": 24, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/mapping-deletion/MappingDeletion.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/mapping-deletion/MappingDeletion.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
30 |
||||
], |
||||
"starting_column": 9, |
||||
"ending_column": 33 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "function", |
||||
"name": "deleteBalance", |
||||
"source_mapping": { |
||||
"start": 541, |
||||
"length": 137, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/mapping-deletion/MappingDeletion.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/mapping-deletion/MappingDeletion.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
28, |
||||
29, |
||||
30, |
||||
31 |
||||
], |
||||
"starting_column": 5, |
||||
"ending_column": 6 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "Balances", |
||||
"source_mapping": { |
||||
"start": 186, |
||||
"length": 825, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/mapping-deletion/MappingDeletion.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/mapping-deletion/MappingDeletion.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
15, |
||||
16, |
||||
17, |
||||
18, |
||||
19, |
||||
20, |
||||
21, |
||||
22, |
||||
23, |
||||
24, |
||||
25, |
||||
26, |
||||
27, |
||||
28, |
||||
29, |
||||
30, |
||||
31, |
||||
32, |
||||
33, |
||||
34, |
||||
35, |
||||
36, |
||||
37, |
||||
38, |
||||
39, |
||||
40, |
||||
41, |
||||
42, |
||||
43 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
}, |
||||
"signature": "deleteBalance(uint256)" |
||||
} |
||||
} |
||||
} |
||||
} |
||||
], |
||||
"description": "Balances.deleteBalance(uint256) (tests/detectors/mapping-deletion/MappingDeletion.sol#28-31) deletes Balances.BalancesStruct (tests/detectors/mapping-deletion/MappingDeletion.sol#17-20) which contains a mapping:\n\t-delete stackBalance[idx] (tests/detectors/mapping-deletion/MappingDeletion.sol#30)\n", |
||||
"markdown": "[Balances.deleteBalance(uint256)](tests/detectors/mapping-deletion/MappingDeletion.sol#L28-L31) deletes [Balances.BalancesStruct](tests/detectors/mapping-deletion/MappingDeletion.sol#L17-L20) which contains a mapping:\n\t-[delete stackBalance[idx]](tests/detectors/mapping-deletion/MappingDeletion.sol#L30)\n", |
||||
"id": "a1e8bc34ec8ef7969409701b3c851749c4ba00dcbbef2cabcdf7e3f49724034e", |
||||
"check": "mapping-deletion", |
||||
"impact": "Medium", |
||||
"confidence": "High" |
||||
} |
||||
] |
||||
] |
@ -0,0 +1,72 @@ |
||||
/* Interfaces */ |
||||
interface ISomething0 { |
||||
function sth1(uint256) external; |
||||
} |
||||
|
||||
interface ISomething1 { |
||||
function sth1(uint256) external; |
||||
function sth2(bytes calldata) external; |
||||
} |
||||
|
||||
interface ISomething2 { |
||||
function sth(uint256) external; |
||||
} |
||||
|
||||
interface ISomething3 { |
||||
function sth1(uint256) external; |
||||
function sth2(bool) external; |
||||
} |
||||
|
||||
interface ISomething4 { |
||||
function sth1(uint256) external; |
||||
function sth2(bool) external; |
||||
function sth3(bytes calldata) external; |
||||
} |
||||
|
||||
interface ISomething5 { |
||||
function sth(uint256) external; |
||||
function sth1(uint256) external; |
||||
} |
||||
|
||||
|
||||
|
||||
/* Contracts */ |
||||
|
||||
contract bad0 { // forgets to say it is ISomething1 |
||||
function sth1(uint256 x) external {} |
||||
function sth2(bytes calldata y) external {} |
||||
} |
||||
|
||||
contract bad1 { // forgets to say it is ISomething4 |
||||
function sth1(uint256 x) external {} |
||||
function sth2(bool b) external {} |
||||
function sth3(bytes calldata y) external {} |
||||
} |
||||
|
||||
contract bad2 is ISomething3 { // forgets to say it is ISomething4 which is a superset of ISomething3 |
||||
function sth1(uint256 x) external {} |
||||
function sth2(bool b) external {} |
||||
function sth3(bytes calldata y) external {} |
||||
} |
||||
|
||||
contract good0 is ISomething2 { |
||||
function sth(uint256 x) external {} |
||||
} |
||||
|
||||
/* Implements ISomething5 which is a superset of ISomething0 and ISomething2 */ |
||||
contract good1 is ISomething5 { |
||||
function sth(uint256 x) external {} |
||||
function sth1(uint256 x) external {} |
||||
} |
||||
|
||||
/* good2_i is not an Interface because sth5 is not external */ |
||||
contract bad3_i { |
||||
function sth4(uint256 x) external; |
||||
function sth5(uint256 x) public; |
||||
} |
||||
|
||||
contract bad3 { |
||||
function sth4(uint256 x) external {} |
||||
function sth5(uint256 x) public {} |
||||
} |
||||
|
@ -0,0 +1,3 @@ |
||||
[ |
||||
[] |
||||
] |
@ -0,0 +1,785 @@ |
||||
JSON AST (compact format): |
||||
|
||||
|
||||
======= multiple-constructors.sol ======= |
||||
{ |
||||
"absolutePath" : "multiple-constructors.sol", |
||||
"exportedSymbols" : |
||||
{ |
||||
"A" : |
||||
[ |
||||
54 |
||||
] |
||||
}, |
||||
"id" : 55, |
||||
"nodeType" : "SourceUnit", |
||||
"nodes" : |
||||
[ |
||||
{ |
||||
"id" : 1, |
||||
"literals" : |
||||
[ |
||||
"solidity", |
||||
"0.4", |
||||
".22" |
||||
], |
||||
"nodeType" : "PragmaDirective", |
||||
"src" : "0:23:0" |
||||
}, |
||||
{ |
||||
"baseContracts" : [], |
||||
"contractDependencies" : [], |
||||
"contractKind" : "contract", |
||||
"documentation" : null, |
||||
"fullyImplemented" : true, |
||||
"id" : 54, |
||||
"linearizedBaseContracts" : |
||||
[ |
||||
54 |
||||
], |
||||
"name" : "A", |
||||
"nodeType" : "ContractDefinition", |
||||
"nodes" : |
||||
[ |
||||
{ |
||||
"constant" : false, |
||||
"id" : 5, |
||||
"name" : "x", |
||||
"nodeType" : "VariableDeclaration", |
||||
"scope" : 54, |
||||
"src" : "41:9:0", |
||||
"stateVariable" : true, |
||||
"storageLocation" : "default", |
||||
"typeDescriptions" : |
||||
{ |
||||
"typeIdentifier" : "t_array$_t_uint256_$2_storage", |
||||
"typeString" : "uint256[2]" |
||||
}, |
||||
"typeName" : |
||||
{ |
||||
"baseType" : |
||||
{ |
||||
"id" : 2, |
||||
"name" : "uint", |
||||
"nodeType" : "ElementaryTypeName", |
||||
"src" : "41:4:0", |
||||
"typeDescriptions" : |
||||
{ |
||||
"typeIdentifier" : "t_uint256", |
||||
"typeString" : "uint256" |
||||
} |
||||
}, |
||||
"id" : 4, |
||||
"length" : |
||||
{ |
||||
"argumentTypes" : null, |
||||
"hexValue" : "32", |
||||
"id" : 3, |
||||
"isConstant" : false, |
||||
"isLValue" : false, |
||||
"isPure" : false, |
||||
"kind" : "number", |
||||
"lValueRequested" : false, |
||||
"nodeType" : "Literal", |
||||
"src" : "46:1:0", |
||||
"subdenomination" : null, |
||||
"typeDescriptions" : |
||||
{ |
||||
"typeIdentifier" : null, |
||||
"typeString" : null |
||||
}, |
||||
"value" : "2" |
||||
}, |
||||
"nodeType" : "ArrayTypeName", |
||||
"src" : "41:7:0", |
||||
"typeDescriptions" : |
||||
{ |
||||
"typeIdentifier" : "t_array$_t_uint256_$2_storage_ptr", |
||||
"typeString" : "uint256[2]" |
||||
} |
||||
}, |
||||
"value" : null, |
||||
"visibility" : "internal" |
||||
}, |
||||
{ |
||||
"body" : |
||||
{ |
||||
"id" : 20, |
||||
"nodeType" : "Block", |
||||
"src" : "76:45:0", |
||||
"statements" : |
||||
[ |
||||
{ |
||||
"expression" : |
||||
{ |
||||
"argumentTypes" : null, |
||||
"id" : 12, |
||||
"isConstant" : false, |
||||
"isLValue" : false, |
||||
"isPure" : false, |
||||
"lValueRequested" : false, |
||||
"leftHandSide" : |
||||
{ |
||||
"argumentTypes" : null, |
||||
"baseExpression" : |
||||
{ |
||||
"argumentTypes" : null, |
||||
"id" : 8, |
||||
"name" : "x", |
||||
"nodeType" : "Identifier", |
||||
"overloadedDeclarations" : [], |
||||
"referencedDeclaration" : 5, |
||||
"src" : "86:1:0", |
||||
"typeDescriptions" : |
||||
{ |
||||
"typeIdentifier" : "t_array$_t_uint256_$2_storage", |
||||
"typeString" : "uint256[2] storage ref" |
||||
} |
||||
}, |
||||
"id" : 10, |
||||
"indexExpression" : |
||||
{ |
||||
"argumentTypes" : null, |
||||
"hexValue" : "30", |
||||
"id" : 9, |
||||
"isConstant" : false, |
||||
"isLValue" : false, |
||||
"isPure" : true, |
||||
"kind" : "number", |
||||
"lValueRequested" : false, |
||||
"nodeType" : "Literal", |
||||
"src" : "88:1:0", |
||||
"subdenomination" : null, |
||||
"typeDescriptions" : |
||||
{ |
||||
"typeIdentifier" : "t_rational_0_by_1", |
||||
"typeString" : "int_const 0" |
||||
}, |
||||
"value" : "0" |
||||
}, |
||||
"isConstant" : false, |
||||
"isLValue" : true, |
||||
"isPure" : false, |
||||
"lValueRequested" : true, |
||||
"nodeType" : "IndexAccess", |
||||
"src" : "86:4:0", |
||||
"typeDescriptions" : |
||||
{ |
||||
"typeIdentifier" : "t_uint256", |
||||
"typeString" : "uint256" |
||||
} |
||||
}, |
||||
"nodeType" : "Assignment", |
||||
"operator" : "=", |
||||
"rightHandSide" : |
||||
{ |
||||
"argumentTypes" : null, |
||||
"hexValue" : "3838", |
||||
"id" : 11, |
||||
"isConstant" : false, |
||||
"isLValue" : false, |
||||
"isPure" : true, |
||||
"kind" : "number", |
||||
"lValueRequested" : false, |
||||
"nodeType" : "Literal", |
||||
"src" : "93:2:0", |
||||
"subdenomination" : null, |
||||
"typeDescriptions" : |
||||
{ |
||||
"typeIdentifier" : "t_rational_88_by_1", |
||||
"typeString" : "int_const 88" |
||||
}, |
||||
"value" : "88" |
||||
}, |
||||
"src" : "86:9:0", |
||||
"typeDescriptions" : |
||||
{ |
||||
"typeIdentifier" : "t_uint256", |
||||
"typeString" : "uint256" |
||||
} |
||||
}, |
||||
"id" : 13, |
||||
"nodeType" : "ExpressionStatement", |
||||
"src" : "86:9:0" |
||||
}, |
||||
{ |
||||
"expression" : |
||||
{ |
||||
"argumentTypes" : null, |
||||
"id" : 18, |
||||
"isConstant" : false, |
||||
"isLValue" : false, |
||||
"isPure" : false, |
||||
"lValueRequested" : false, |
||||
"leftHandSide" : |
||||
{ |
||||
"argumentTypes" : null, |
||||
"baseExpression" : |
||||
{ |
||||
"argumentTypes" : null, |
||||
"id" : 14, |
||||
"name" : "x", |
||||
"nodeType" : "Identifier", |
||||
"overloadedDeclarations" : [], |
||||
"referencedDeclaration" : 5, |
||||
"src" : "105:1:0", |
||||
"typeDescriptions" : |
||||
{ |
||||
"typeIdentifier" : "t_array$_t_uint256_$2_storage", |
||||
"typeString" : "uint256[2] storage ref" |
||||
} |
||||
}, |
||||
"id" : 16, |
||||
"indexExpression" : |
||||
{ |
||||
"argumentTypes" : null, |
||||
"hexValue" : "31", |
||||
"id" : 15, |
||||
"isConstant" : false, |
||||
"isLValue" : false, |
||||
"isPure" : true, |
||||
"kind" : "number", |
||||
"lValueRequested" : false, |
||||
"nodeType" : "Literal", |
||||
"src" : "107:1:0", |
||||
"subdenomination" : null, |
||||
"typeDescriptions" : |
||||
{ |
||||
"typeIdentifier" : "t_rational_1_by_1", |
||||
"typeString" : "int_const 1" |
||||
}, |
||||
"value" : "1" |
||||
}, |
||||
"isConstant" : false, |
||||
"isLValue" : true, |
||||
"isPure" : false, |
||||
"lValueRequested" : true, |
||||
"nodeType" : "IndexAccess", |
||||
"src" : "105:4:0", |
||||
"typeDescriptions" : |
||||
{ |
||||
"typeIdentifier" : "t_uint256", |
||||
"typeString" : "uint256" |
||||
} |
||||
}, |
||||
"nodeType" : "Assignment", |
||||
"operator" : "=", |
||||
"rightHandSide" : |
||||
{ |
||||
"argumentTypes" : null, |
||||
"hexValue" : "3939", |
||||
"id" : 17, |
||||
"isConstant" : false, |
||||
"isLValue" : false, |
||||
"isPure" : true, |
||||
"kind" : "number", |
||||
"lValueRequested" : false, |
||||
"nodeType" : "Literal", |
||||
"src" : "112:2:0", |
||||
"subdenomination" : null, |
||||
"typeDescriptions" : |
||||
{ |
||||
"typeIdentifier" : "t_rational_99_by_1", |
||||
"typeString" : "int_const 99" |
||||
}, |
||||
"value" : "99" |
||||
}, |
||||
"src" : "105:9:0", |
||||
"typeDescriptions" : |
||||
{ |
||||
"typeIdentifier" : "t_uint256", |
||||
"typeString" : "uint256" |
||||
} |
||||
}, |
||||
"id" : 19, |
||||
"nodeType" : "ExpressionStatement", |
||||
"src" : "105:9:0" |
||||
} |
||||
] |
||||
}, |
||||
"documentation" : null, |
||||
"id" : 21, |
||||
"implemented" : true, |
||||
"isConstructor" : true, |
||||
"isDeclaredConst" : false, |
||||
"modifiers" : [], |
||||
"name" : "A", |
||||
"nodeType" : "FunctionDefinition", |
||||
"parameters" : |
||||
{ |
||||
"id" : 6, |
||||
"nodeType" : "ParameterList", |
||||
"parameters" : [], |
||||
"src" : "66:2:0" |
||||
}, |
||||
"payable" : false, |
||||
"returnParameters" : |
||||
{ |
||||
"id" : 7, |
||||
"nodeType" : "ParameterList", |
||||
"parameters" : [], |
||||
"src" : "76:0:0" |
||||
}, |
||||
"scope" : 54, |
||||
"src" : "56:65:0", |
||||
"stateMutability" : "nonpayable", |
||||
"superFunction" : null, |
||||
"visibility" : "public" |
||||
}, |
||||
{ |
||||
"body" : |
||||
{ |
||||
"id" : 36, |
||||
"nodeType" : "Block", |
||||
"src" : "147:45:0", |
||||
"statements" : |
||||
[ |
||||
{ |
||||
"expression" : |
||||
{ |
||||
"argumentTypes" : null, |
||||
"id" : 28, |
||||
"isConstant" : false, |
||||
"isLValue" : false, |
||||
"isPure" : false, |
||||
"lValueRequested" : false, |
||||
"leftHandSide" : |
||||
{ |
||||
"argumentTypes" : null, |
||||
"baseExpression" : |
||||
{ |
||||
"argumentTypes" : null, |
||||
"id" : 24, |
||||
"name" : "x", |
||||
"nodeType" : "Identifier", |
||||
"overloadedDeclarations" : [], |
||||
"referencedDeclaration" : 5, |
||||
"src" : "157:1:0", |
||||
"typeDescriptions" : |
||||
{ |
||||
"typeIdentifier" : "t_array$_t_uint256_$2_storage", |
||||
"typeString" : "uint256[2] storage ref" |
||||
} |
||||
}, |
||||
"id" : 26, |
||||
"indexExpression" : |
||||
{ |
||||
"argumentTypes" : null, |
||||
"hexValue" : "30", |
||||
"id" : 25, |
||||
"isConstant" : false, |
||||
"isLValue" : false, |
||||
"isPure" : true, |
||||
"kind" : "number", |
||||
"lValueRequested" : false, |
||||
"nodeType" : "Literal", |
||||
"src" : "159:1:0", |
||||
"subdenomination" : null, |
||||
"typeDescriptions" : |
||||
{ |
||||
"typeIdentifier" : "t_rational_0_by_1", |
||||
"typeString" : "int_const 0" |
||||
}, |
||||
"value" : "0" |
||||
}, |
||||
"isConstant" : false, |
||||
"isLValue" : true, |
||||
"isPure" : false, |
||||
"lValueRequested" : true, |
||||
"nodeType" : "IndexAccess", |
||||
"src" : "157:4:0", |
||||
"typeDescriptions" : |
||||
{ |
||||
"typeIdentifier" : "t_uint256", |
||||
"typeString" : "uint256" |
||||
} |
||||
}, |
||||
"nodeType" : "Assignment", |
||||
"operator" : "=", |
||||
"rightHandSide" : |
||||
{ |
||||
"argumentTypes" : null, |
||||
"hexValue" : "3636", |
||||
"id" : 27, |
||||
"isConstant" : false, |
||||
"isLValue" : false, |
||||
"isPure" : true, |
||||
"kind" : "number", |
||||
"lValueRequested" : false, |
||||
"nodeType" : "Literal", |
||||
"src" : "164:2:0", |
||||
"subdenomination" : null, |
||||
"typeDescriptions" : |
||||
{ |
||||
"typeIdentifier" : "t_rational_66_by_1", |
||||
"typeString" : "int_const 66" |
||||
}, |
||||
"value" : "66" |
||||
}, |
||||
"src" : "157:9:0", |
||||
"typeDescriptions" : |
||||
{ |
||||
"typeIdentifier" : "t_uint256", |
||||
"typeString" : "uint256" |
||||
} |
||||
}, |
||||
"id" : 29, |
||||
"nodeType" : "ExpressionStatement", |
||||
"src" : "157:9:0" |
||||
}, |
||||
{ |
||||
"expression" : |
||||
{ |
||||
"argumentTypes" : null, |
||||
"id" : 34, |
||||
"isConstant" : false, |
||||
"isLValue" : false, |
||||
"isPure" : false, |
||||
"lValueRequested" : false, |
||||
"leftHandSide" : |
||||
{ |
||||
"argumentTypes" : null, |
||||
"baseExpression" : |
||||
{ |
||||
"argumentTypes" : null, |
||||
"id" : 30, |
||||
"name" : "x", |
||||
"nodeType" : "Identifier", |
||||
"overloadedDeclarations" : [], |
||||
"referencedDeclaration" : 5, |
||||
"src" : "176:1:0", |
||||
"typeDescriptions" : |
||||
{ |
||||
"typeIdentifier" : "t_array$_t_uint256_$2_storage", |
||||
"typeString" : "uint256[2] storage ref" |
||||
} |
||||
}, |
||||
"id" : 32, |
||||
"indexExpression" : |
||||
{ |
||||
"argumentTypes" : null, |
||||
"hexValue" : "31", |
||||
"id" : 31, |
||||
"isConstant" : false, |
||||
"isLValue" : false, |
||||
"isPure" : true, |
||||
"kind" : "number", |
||||
"lValueRequested" : false, |
||||
"nodeType" : "Literal", |
||||
"src" : "178:1:0", |
||||
"subdenomination" : null, |
||||
"typeDescriptions" : |
||||
{ |
||||
"typeIdentifier" : "t_rational_1_by_1", |
||||
"typeString" : "int_const 1" |
||||
}, |
||||
"value" : "1" |
||||
}, |
||||
"isConstant" : false, |
||||
"isLValue" : true, |
||||
"isPure" : false, |
||||
"lValueRequested" : true, |
||||
"nodeType" : "IndexAccess", |
||||
"src" : "176:4:0", |
||||
"typeDescriptions" : |
||||
{ |
||||
"typeIdentifier" : "t_uint256", |
||||
"typeString" : "uint256" |
||||
} |
||||
}, |
||||
"nodeType" : "Assignment", |
||||
"operator" : "=", |
||||
"rightHandSide" : |
||||
{ |
||||
"argumentTypes" : null, |
||||
"hexValue" : "3737", |
||||
"id" : 33, |
||||
"isConstant" : false, |
||||
"isLValue" : false, |
||||
"isPure" : true, |
||||
"kind" : "number", |
||||
"lValueRequested" : false, |
||||
"nodeType" : "Literal", |
||||
"src" : "183:2:0", |
||||
"subdenomination" : null, |
||||
"typeDescriptions" : |
||||
{ |
||||
"typeIdentifier" : "t_rational_77_by_1", |
||||
"typeString" : "int_const 77" |
||||
}, |
||||
"value" : "77" |
||||
}, |
||||
"src" : "176:9:0", |
||||
"typeDescriptions" : |
||||
{ |
||||
"typeIdentifier" : "t_uint256", |
||||
"typeString" : "uint256" |
||||
} |
||||
}, |
||||
"id" : 35, |
||||
"nodeType" : "ExpressionStatement", |
||||
"src" : "176:9:0" |
||||
} |
||||
] |
||||
}, |
||||
"documentation" : null, |
||||
"id" : 37, |
||||
"implemented" : true, |
||||
"isConstructor" : true, |
||||
"isDeclaredConst" : false, |
||||
"modifiers" : [], |
||||
"name" : "", |
||||
"nodeType" : "FunctionDefinition", |
||||
"parameters" : |
||||
{ |
||||
"id" : 22, |
||||
"nodeType" : "ParameterList", |
||||
"parameters" : [], |
||||
"src" : "137:2:0" |
||||
}, |
||||
"payable" : false, |
||||
"returnParameters" : |
||||
{ |
||||
"id" : 23, |
||||
"nodeType" : "ParameterList", |
||||
"parameters" : [], |
||||
"src" : "147:0:0" |
||||
}, |
||||
"scope" : 54, |
||||
"src" : "126:66:0", |
||||
"stateMutability" : "nonpayable", |
||||
"superFunction" : null, |
||||
"visibility" : "public" |
||||
}, |
||||
{ |
||||
"body" : |
||||
{ |
||||
"id" : 52, |
||||
"nodeType" : "Block", |
||||
"src" : "241:36:0", |
||||
"statements" : |
||||
[ |
||||
{ |
||||
"expression" : |
||||
{ |
||||
"argumentTypes" : null, |
||||
"components" : |
||||
[ |
||||
{ |
||||
"argumentTypes" : null, |
||||
"baseExpression" : |
||||
{ |
||||
"argumentTypes" : null, |
||||
"id" : 44, |
||||
"name" : "x", |
||||
"nodeType" : "Identifier", |
||||
"overloadedDeclarations" : [], |
||||
"referencedDeclaration" : 5, |
||||
"src" : "259:1:0", |
||||
"typeDescriptions" : |
||||
{ |
||||
"typeIdentifier" : "t_array$_t_uint256_$2_storage", |
||||
"typeString" : "uint256[2] storage ref" |
||||
} |
||||
}, |
||||
"id" : 46, |
||||
"indexExpression" : |
||||
{ |
||||
"argumentTypes" : null, |
||||
"hexValue" : "30", |
||||
"id" : 45, |
||||
"isConstant" : false, |
||||
"isLValue" : false, |
||||
"isPure" : true, |
||||
"kind" : "number", |
||||
"lValueRequested" : false, |
||||
"nodeType" : "Literal", |
||||
"src" : "261:1:0", |
||||
"subdenomination" : null, |
||||
"typeDescriptions" : |
||||
{ |
||||
"typeIdentifier" : "t_rational_0_by_1", |
||||
"typeString" : "int_const 0" |
||||
}, |
||||
"value" : "0" |
||||
}, |
||||
"isConstant" : false, |
||||
"isLValue" : true, |
||||
"isPure" : false, |
||||
"lValueRequested" : false, |
||||
"nodeType" : "IndexAccess", |
||||
"src" : "259:4:0", |
||||
"typeDescriptions" : |
||||
{ |
||||
"typeIdentifier" : "t_uint256", |
||||
"typeString" : "uint256" |
||||
} |
||||
}, |
||||
{ |
||||
"argumentTypes" : null, |
||||
"baseExpression" : |
||||
{ |
||||
"argumentTypes" : null, |
||||
"id" : 47, |
||||
"name" : "x", |
||||
"nodeType" : "Identifier", |
||||
"overloadedDeclarations" : [], |
||||
"referencedDeclaration" : 5, |
||||
"src" : "265:1:0", |
||||
"typeDescriptions" : |
||||
{ |
||||
"typeIdentifier" : "t_array$_t_uint256_$2_storage", |
||||
"typeString" : "uint256[2] storage ref" |
||||
} |
||||
}, |
||||
"id" : 49, |
||||
"indexExpression" : |
||||
{ |
||||
"argumentTypes" : null, |
||||
"hexValue" : "31", |
||||
"id" : 48, |
||||
"isConstant" : false, |
||||
"isLValue" : false, |
||||
"isPure" : true, |
||||
"kind" : "number", |
||||
"lValueRequested" : false, |
||||
"nodeType" : "Literal", |
||||
"src" : "267:1:0", |
||||
"subdenomination" : null, |
||||
"typeDescriptions" : |
||||
{ |
||||
"typeIdentifier" : "t_rational_1_by_1", |
||||
"typeString" : "int_const 1" |
||||
}, |
||||
"value" : "1" |
||||
}, |
||||
"isConstant" : false, |
||||
"isLValue" : true, |
||||
"isPure" : false, |
||||
"lValueRequested" : false, |
||||
"nodeType" : "IndexAccess", |
||||
"src" : "265:4:0", |
||||
"typeDescriptions" : |
||||
{ |
||||
"typeIdentifier" : "t_uint256", |
||||
"typeString" : "uint256" |
||||
} |
||||
} |
||||
], |
||||
"id" : 50, |
||||
"isConstant" : false, |
||||
"isInlineArray" : false, |
||||
"isLValue" : false, |
||||
"isPure" : false, |
||||
"lValueRequested" : false, |
||||
"nodeType" : "TupleExpression", |
||||
"src" : "258:12:0", |
||||
"typeDescriptions" : |
||||
{ |
||||
"typeIdentifier" : "t_tuple$_t_uint256_$_t_uint256_$", |
||||
"typeString" : "tuple(uint256,uint256)" |
||||
} |
||||
}, |
||||
"functionReturnParameters" : 43, |
||||
"id" : 51, |
||||
"nodeType" : "Return", |
||||
"src" : "251:19:0" |
||||
} |
||||
] |
||||
}, |
||||
"documentation" : null, |
||||
"id" : 53, |
||||
"implemented" : true, |
||||
"isConstructor" : false, |
||||
"isDeclaredConst" : false, |
||||
"modifiers" : [], |
||||
"name" : "test", |
||||
"nodeType" : "FunctionDefinition", |
||||
"parameters" : |
||||
{ |
||||
"id" : 38, |
||||
"nodeType" : "ParameterList", |
||||
"parameters" : [], |
||||
"src" : "211:2:0" |
||||
}, |
||||
"payable" : false, |
||||
"returnParameters" : |
||||
{ |
||||
"id" : 43, |
||||
"nodeType" : "ParameterList", |
||||
"parameters" : |
||||
[ |
||||
{ |
||||
"constant" : false, |
||||
"id" : 40, |
||||
"name" : "", |
||||
"nodeType" : "VariableDeclaration", |
||||
"scope" : 53, |
||||
"src" : "229:4:0", |
||||
"stateVariable" : false, |
||||
"storageLocation" : "default", |
||||
"typeDescriptions" : |
||||
{ |
||||
"typeIdentifier" : "t_uint256", |
||||
"typeString" : "uint256" |
||||
}, |
||||
"typeName" : |
||||
{ |
||||
"id" : 39, |
||||
"name" : "uint", |
||||
"nodeType" : "ElementaryTypeName", |
||||
"src" : "229:4:0", |
||||
"typeDescriptions" : |
||||
{ |
||||
"typeIdentifier" : "t_uint256", |
||||
"typeString" : "uint256" |
||||
} |
||||
}, |
||||
"value" : null, |
||||
"visibility" : "internal" |
||||
}, |
||||
{ |
||||
"constant" : false, |
||||
"id" : 42, |
||||
"name" : "", |
||||
"nodeType" : "VariableDeclaration", |
||||
"scope" : 53, |
||||
"src" : "235:4:0", |
||||
"stateVariable" : false, |
||||
"storageLocation" : "default", |
||||
"typeDescriptions" : |
||||
{ |
||||
"typeIdentifier" : "t_uint256", |
||||
"typeString" : "uint256" |
||||
}, |
||||
"typeName" : |
||||
{ |
||||
"id" : 41, |
||||
"name" : "uint", |
||||
"nodeType" : "ElementaryTypeName", |
||||
"src" : "235:4:0", |
||||
"typeDescriptions" : |
||||
{ |
||||
"typeIdentifier" : "t_uint256", |
||||
"typeString" : "uint256" |
||||
} |
||||
}, |
||||
"value" : null, |
||||
"visibility" : "internal" |
||||
} |
||||
], |
||||
"src" : "228:12:0" |
||||
}, |
||||
"scope" : 54, |
||||
"src" : "198:79:0", |
||||
"stateMutability" : "nonpayable", |
||||
"superFunction" : null, |
||||
"visibility" : "public" |
||||
} |
||||
], |
||||
"scope" : 55, |
||||
"src" : "24:255:0" |
||||
} |
||||
], |
||||
"src" : "0:280:0" |
||||
} |
@ -0,0 +1,29 @@ |
||||
// This is used to test detection of public mappings with nested variables. This was an issue in Solidity 0.4.x. |
||||
pragma solidity ^0.4.0; |
||||
|
||||
contract Bug { |
||||
|
||||
struct innerStruct { |
||||
uint x; |
||||
} |
||||
|
||||
struct outerStruct { |
||||
innerStruct inner; |
||||
} |
||||
|
||||
mapping(uint => outerStruct) public testMapping; |
||||
mapping(uint => uint) public testMapping2; |
||||
mapping(uint => address) public testMapping3; |
||||
|
||||
constructor() public { |
||||
testMapping[0].inner.x = 42; |
||||
} |
||||
} |
||||
|
||||
contract Test{ |
||||
|
||||
function f() public returns(uint){ |
||||
Bug b = new Bug(); |
||||
return b.testMapping(0).x; |
||||
} |
||||
} |
@ -0,0 +1,69 @@ |
||||
[ |
||||
[ |
||||
{ |
||||
"elements": [ |
||||
{ |
||||
"type": "variable", |
||||
"name": "testMapping", |
||||
"source_mapping": { |
||||
"start": 265, |
||||
"length": 47, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/public-mappings-nested/public_mappings_nested.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/public-mappings-nested/public_mappings_nested.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
14 |
||||
], |
||||
"starting_column": 5, |
||||
"ending_column": 52 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "Bug", |
||||
"source_mapping": { |
||||
"start": 138, |
||||
"length": 345, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/public-mappings-nested/public_mappings_nested.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/public-mappings-nested/public_mappings_nested.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
10, |
||||
11, |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16, |
||||
17, |
||||
18, |
||||
19, |
||||
20, |
||||
21 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
} |
||||
} |
||||
} |
||||
], |
||||
"description": "Bug.testMapping (tests/detectors/public-mappings-nested/public_mappings_nested.sol#14) is a public mapping with nested variables\n", |
||||
"markdown": "[Bug.testMapping](tests/detectors/public-mappings-nested/public_mappings_nested.sol#L14) is a public mapping with nested variables\n", |
||||
"id": "100978112524def620b003331f34b2b51eb78cae6f7eb2793d9671b4b7bb858a", |
||||
"check": "public-mappings-nested", |
||||
"impact": "High", |
||||
"confidence": "High" |
||||
} |
||||
] |
||||
] |
@ -0,0 +1,17 @@ |
||||
// This tests for redundant top-level expressions in statements. |
||||
|
||||
contract RedundantStatementsContract { |
||||
|
||||
constructor() public { |
||||
uint; |
||||
bool; |
||||
RedundantStatementsContract; |
||||
} |
||||
|
||||
function test() public returns (uint) { |
||||
uint; |
||||
assert; |
||||
test; |
||||
return 777; |
||||
} |
||||
} |
@ -0,0 +1,733 @@ |
||||
[ |
||||
[ |
||||
{ |
||||
"elements": [ |
||||
{ |
||||
"type": "node", |
||||
"name": "uint256", |
||||
"source_mapping": { |
||||
"start": 141, |
||||
"length": 4, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/redundant-statements/redundant_statements.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/redundant-statements/redundant_statements.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
6 |
||||
], |
||||
"starting_column": 9, |
||||
"ending_column": 13 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "function", |
||||
"name": "constructor", |
||||
"source_mapping": { |
||||
"start": 110, |
||||
"length": 93, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/redundant-statements/redundant_statements.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/redundant-statements/redundant_statements.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9 |
||||
], |
||||
"starting_column": 5, |
||||
"ending_column": 6 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "RedundantStatementsContract", |
||||
"source_mapping": { |
||||
"start": 66, |
||||
"length": 254, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/redundant-statements/redundant_statements.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/redundant-statements/redundant_statements.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
10, |
||||
11, |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16, |
||||
17, |
||||
18 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 0 |
||||
} |
||||
}, |
||||
"signature": "constructor()" |
||||
} |
||||
} |
||||
} |
||||
}, |
||||
{ |
||||
"type": "contract", |
||||
"name": "RedundantStatementsContract", |
||||
"source_mapping": { |
||||
"start": 66, |
||||
"length": 254, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/redundant-statements/redundant_statements.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/redundant-statements/redundant_statements.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
10, |
||||
11, |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16, |
||||
17, |
||||
18 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 0 |
||||
} |
||||
} |
||||
], |
||||
"description": "Redundant expression \"uint256 (tests/detectors/redundant-statements/redundant_statements.sol#6)\" inRedundantStatementsContract (tests/detectors/redundant-statements/redundant_statements.sol#3-18)\n", |
||||
"markdown": "Redundant expression \"[uint256](tests/detectors/redundant-statements/redundant_statements.sol#L6)\" in[RedundantStatementsContract](tests/detectors/redundant-statements/redundant_statements.sol#L3-L18)\n", |
||||
"id": "cff54481eae76053f9cae0d4f77a2e5092461dc3fcb9e4e2f8605afb6aa832aa", |
||||
"check": "redundant-statements", |
||||
"impact": "Informational", |
||||
"confidence": "High" |
||||
}, |
||||
{ |
||||
"elements": [ |
||||
{ |
||||
"type": "node", |
||||
"name": "bool", |
||||
"source_mapping": { |
||||
"start": 155, |
||||
"length": 4, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/redundant-statements/redundant_statements.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/redundant-statements/redundant_statements.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
7 |
||||
], |
||||
"starting_column": 9, |
||||
"ending_column": 13 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "function", |
||||
"name": "constructor", |
||||
"source_mapping": { |
||||
"start": 110, |
||||
"length": 93, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/redundant-statements/redundant_statements.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/redundant-statements/redundant_statements.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9 |
||||
], |
||||
"starting_column": 5, |
||||
"ending_column": 6 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "RedundantStatementsContract", |
||||
"source_mapping": { |
||||
"start": 66, |
||||
"length": 254, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/redundant-statements/redundant_statements.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/redundant-statements/redundant_statements.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
10, |
||||
11, |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16, |
||||
17, |
||||
18 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 0 |
||||
} |
||||
}, |
||||
"signature": "constructor()" |
||||
} |
||||
} |
||||
} |
||||
}, |
||||
{ |
||||
"type": "contract", |
||||
"name": "RedundantStatementsContract", |
||||
"source_mapping": { |
||||
"start": 66, |
||||
"length": 254, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/redundant-statements/redundant_statements.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/redundant-statements/redundant_statements.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
10, |
||||
11, |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16, |
||||
17, |
||||
18 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 0 |
||||
} |
||||
} |
||||
], |
||||
"description": "Redundant expression \"bool (tests/detectors/redundant-statements/redundant_statements.sol#7)\" inRedundantStatementsContract (tests/detectors/redundant-statements/redundant_statements.sol#3-18)\n", |
||||
"markdown": "Redundant expression \"[bool](tests/detectors/redundant-statements/redundant_statements.sol#L7)\" in[RedundantStatementsContract](tests/detectors/redundant-statements/redundant_statements.sol#L3-L18)\n", |
||||
"id": "bd643774adde96fa093cf2ec70d9a80fc2999dba8b61b60d0df19366003d74d5", |
||||
"check": "redundant-statements", |
||||
"impact": "Informational", |
||||
"confidence": "High" |
||||
}, |
||||
{ |
||||
"elements": [ |
||||
{ |
||||
"type": "node", |
||||
"name": "RedundantStatementsContract", |
||||
"source_mapping": { |
||||
"start": 169, |
||||
"length": 27, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/redundant-statements/redundant_statements.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/redundant-statements/redundant_statements.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
8 |
||||
], |
||||
"starting_column": 9, |
||||
"ending_column": 36 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "function", |
||||
"name": "constructor", |
||||
"source_mapping": { |
||||
"start": 110, |
||||
"length": 93, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/redundant-statements/redundant_statements.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/redundant-statements/redundant_statements.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9 |
||||
], |
||||
"starting_column": 5, |
||||
"ending_column": 6 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "RedundantStatementsContract", |
||||
"source_mapping": { |
||||
"start": 66, |
||||
"length": 254, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/redundant-statements/redundant_statements.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/redundant-statements/redundant_statements.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
10, |
||||
11, |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16, |
||||
17, |
||||
18 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 0 |
||||
} |
||||
}, |
||||
"signature": "constructor()" |
||||
} |
||||
} |
||||
} |
||||
}, |
||||
{ |
||||
"type": "contract", |
||||
"name": "RedundantStatementsContract", |
||||
"source_mapping": { |
||||
"start": 66, |
||||
"length": 254, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/redundant-statements/redundant_statements.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/redundant-statements/redundant_statements.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
10, |
||||
11, |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16, |
||||
17, |
||||
18 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 0 |
||||
} |
||||
} |
||||
], |
||||
"description": "Redundant expression \"RedundantStatementsContract (tests/detectors/redundant-statements/redundant_statements.sol#8)\" inRedundantStatementsContract (tests/detectors/redundant-statements/redundant_statements.sol#3-18)\n", |
||||
"markdown": "Redundant expression \"[RedundantStatementsContract](tests/detectors/redundant-statements/redundant_statements.sol#L8)\" in[RedundantStatementsContract](tests/detectors/redundant-statements/redundant_statements.sol#L3-L18)\n", |
||||
"id": "d93991180e8fe3accc3157f286d3a6781ed5c03398d68c0b9fde918a01d65ede", |
||||
"check": "redundant-statements", |
||||
"impact": "Informational", |
||||
"confidence": "High" |
||||
}, |
||||
{ |
||||
"elements": [ |
||||
{ |
||||
"type": "node", |
||||
"name": "uint256", |
||||
"source_mapping": { |
||||
"start": 257, |
||||
"length": 4, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/redundant-statements/redundant_statements.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/redundant-statements/redundant_statements.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
12 |
||||
], |
||||
"starting_column": 9, |
||||
"ending_column": 13 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "function", |
||||
"name": "test", |
||||
"source_mapping": { |
||||
"start": 209, |
||||
"length": 109, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/redundant-statements/redundant_statements.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/redundant-statements/redundant_statements.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
11, |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16 |
||||
], |
||||
"starting_column": 5, |
||||
"ending_column": 6 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "RedundantStatementsContract", |
||||
"source_mapping": { |
||||
"start": 66, |
||||
"length": 254, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/redundant-statements/redundant_statements.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/redundant-statements/redundant_statements.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
10, |
||||
11, |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16, |
||||
17, |
||||
18 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 0 |
||||
} |
||||
}, |
||||
"signature": "test()" |
||||
} |
||||
} |
||||
} |
||||
}, |
||||
{ |
||||
"type": "contract", |
||||
"name": "RedundantStatementsContract", |
||||
"source_mapping": { |
||||
"start": 66, |
||||
"length": 254, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/redundant-statements/redundant_statements.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/redundant-statements/redundant_statements.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
10, |
||||
11, |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16, |
||||
17, |
||||
18 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 0 |
||||
} |
||||
} |
||||
], |
||||
"description": "Redundant expression \"uint256 (tests/detectors/redundant-statements/redundant_statements.sol#12)\" inRedundantStatementsContract (tests/detectors/redundant-statements/redundant_statements.sol#3-18)\n", |
||||
"markdown": "Redundant expression \"[uint256](tests/detectors/redundant-statements/redundant_statements.sol#L12)\" in[RedundantStatementsContract](tests/detectors/redundant-statements/redundant_statements.sol#L3-L18)\n", |
||||
"id": "262267538723f822ebe065e5976738ef3f564c791aaddb26867d202602de1eea", |
||||
"check": "redundant-statements", |
||||
"impact": "Informational", |
||||
"confidence": "High" |
||||
}, |
||||
{ |
||||
"elements": [ |
||||
{ |
||||
"type": "node", |
||||
"name": "assert(bool)", |
||||
"source_mapping": { |
||||
"start": 271, |
||||
"length": 6, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/redundant-statements/redundant_statements.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/redundant-statements/redundant_statements.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
13 |
||||
], |
||||
"starting_column": 9, |
||||
"ending_column": 15 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "function", |
||||
"name": "test", |
||||
"source_mapping": { |
||||
"start": 209, |
||||
"length": 109, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/redundant-statements/redundant_statements.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/redundant-statements/redundant_statements.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
11, |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16 |
||||
], |
||||
"starting_column": 5, |
||||
"ending_column": 6 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "RedundantStatementsContract", |
||||
"source_mapping": { |
||||
"start": 66, |
||||
"length": 254, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/redundant-statements/redundant_statements.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/redundant-statements/redundant_statements.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
10, |
||||
11, |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16, |
||||
17, |
||||
18 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 0 |
||||
} |
||||
}, |
||||
"signature": "test()" |
||||
} |
||||
} |
||||
} |
||||
}, |
||||
{ |
||||
"type": "contract", |
||||
"name": "RedundantStatementsContract", |
||||
"source_mapping": { |
||||
"start": 66, |
||||
"length": 254, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/redundant-statements/redundant_statements.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/redundant-statements/redundant_statements.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
10, |
||||
11, |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16, |
||||
17, |
||||
18 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 0 |
||||
} |
||||
} |
||||
], |
||||
"description": "Redundant expression \"assert(bool) (tests/detectors/redundant-statements/redundant_statements.sol#13)\" inRedundantStatementsContract (tests/detectors/redundant-statements/redundant_statements.sol#3-18)\n", |
||||
"markdown": "Redundant expression \"[assert(bool)](tests/detectors/redundant-statements/redundant_statements.sol#L13)\" in[RedundantStatementsContract](tests/detectors/redundant-statements/redundant_statements.sol#L3-L18)\n", |
||||
"id": "00295b0d55ceb6d73eec5a4905d137edf751e11c951252b54cd42c43ace68ffd", |
||||
"check": "redundant-statements", |
||||
"impact": "Informational", |
||||
"confidence": "High" |
||||
}, |
||||
{ |
||||
"elements": [ |
||||
{ |
||||
"type": "node", |
||||
"name": "test", |
||||
"source_mapping": { |
||||
"start": 287, |
||||
"length": 4, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/redundant-statements/redundant_statements.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/redundant-statements/redundant_statements.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
14 |
||||
], |
||||
"starting_column": 9, |
||||
"ending_column": 13 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "function", |
||||
"name": "test", |
||||
"source_mapping": { |
||||
"start": 209, |
||||
"length": 109, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/redundant-statements/redundant_statements.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/redundant-statements/redundant_statements.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
11, |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16 |
||||
], |
||||
"starting_column": 5, |
||||
"ending_column": 6 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "RedundantStatementsContract", |
||||
"source_mapping": { |
||||
"start": 66, |
||||
"length": 254, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/redundant-statements/redundant_statements.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/redundant-statements/redundant_statements.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
10, |
||||
11, |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16, |
||||
17, |
||||
18 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 0 |
||||
} |
||||
}, |
||||
"signature": "test()" |
||||
} |
||||
} |
||||
} |
||||
}, |
||||
{ |
||||
"type": "contract", |
||||
"name": "RedundantStatementsContract", |
||||
"source_mapping": { |
||||
"start": 66, |
||||
"length": 254, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/redundant-statements/redundant_statements.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/redundant-statements/redundant_statements.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
10, |
||||
11, |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16, |
||||
17, |
||||
18 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 0 |
||||
} |
||||
} |
||||
], |
||||
"description": "Redundant expression \"test (tests/detectors/redundant-statements/redundant_statements.sol#14)\" inRedundantStatementsContract (tests/detectors/redundant-statements/redundant_statements.sol#3-18)\n", |
||||
"markdown": "Redundant expression \"[test](tests/detectors/redundant-statements/redundant_statements.sol#L14)\" in[RedundantStatementsContract](tests/detectors/redundant-statements/redundant_statements.sol#L3-L18)\n", |
||||
"id": "ac50e063af6ebd33a702aa136415f7babc5fef3dc5212730b054d8a089b04e23", |
||||
"check": "redundant-statements", |
||||
"impact": "Informational", |
||||
"confidence": "High" |
||||
} |
||||
] |
||||
] |
@ -0,0 +1,37 @@ |
||||
contract A{ |
||||
uint num = 5; |
||||
constructor(uint x) public{ |
||||
num += x; |
||||
} |
||||
} |
||||
|
||||
contract B is A{ |
||||
constructor(uint y) A(y * 3) public{ |
||||
|
||||
} |
||||
} |
||||
|
||||
contract C is B{ |
||||
constructor(uint y) A(y * 2) public{ |
||||
|
||||
} |
||||
} |
||||
|
||||
contract D is B(1), C(1) { |
||||
constructor() B(3) C(2) public { |
||||
|
||||
} |
||||
} |
||||
|
||||
contract E is B(1), C, D() { |
||||
constructor() B(1) C(2) D() public { |
||||
|
||||
} |
||||
} |
||||
|
||||
|
||||
contract F is B { |
||||
constructor() A(1) public { |
||||
|
||||
} |
||||
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,45 @@ |
||||
pragma solidity ^0.5.8; |
||||
|
||||
contract A { |
||||
|
||||
int[3] intArray; // storage signed integer array |
||||
uint[3] uintArray; // storage unsigned integer array |
||||
|
||||
|
||||
/* Signed integer array initializations with literal arrays are vulnerable */ |
||||
function bad0() public { |
||||
intArray = [-1, -2, -3]; |
||||
} |
||||
|
||||
/* Signed integer array assignments are vulnerable if the base types are different e.g. int256 vs int128 */ |
||||
function bad1(int128[3] memory userArray) public { |
||||
intArray = userArray; |
||||
} |
||||
|
||||
/* Unsigned Int array initializations are not vulnerable */ |
||||
function good0() public { |
||||
uintArray = [0, 1, 2]; |
||||
} |
||||
|
||||
/* Unsigned Int array assignments are not vulnerable */ |
||||
function good1(uint[3] memory userArray) public { |
||||
uintArray = userArray; |
||||
} |
||||
|
||||
/* Assigning individual array elements are not vulnerable */ |
||||
function good2() public { |
||||
intArray[1] = -1; |
||||
} |
||||
|
||||
/* Assignment between two signed integer arrays of same base type int256 are not vulnerable */ |
||||
function good3(int[3] memory userArray) public { |
||||
intArray = userArray; |
||||
} |
||||
|
||||
/* Array literal initialization of in-memory signed integer arrays are not vulnerable */ |
||||
function good4() public { |
||||
int8[3] memory memIntArray; |
||||
memIntArray = [-1, -2, -3]; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,3 @@ |
||||
[ |
||||
[] |
||||
] |
@ -0,0 +1,516 @@ |
||||
[ |
||||
[ |
||||
{ |
||||
"elements": [ |
||||
{ |
||||
"type": "contract", |
||||
"name": "A", |
||||
"source_mapping": { |
||||
"start": 25, |
||||
"length": 2256, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/storage-array/storage_signed_integer_array.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/storage-array/storage_signed_integer_array.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
10, |
||||
11, |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16, |
||||
17, |
||||
18, |
||||
19, |
||||
20, |
||||
21, |
||||
22, |
||||
23, |
||||
24, |
||||
25, |
||||
26, |
||||
27, |
||||
28, |
||||
29, |
||||
30, |
||||
31, |
||||
32, |
||||
33, |
||||
34, |
||||
35, |
||||
36, |
||||
37, |
||||
38, |
||||
39, |
||||
40, |
||||
41, |
||||
42, |
||||
43, |
||||
44, |
||||
45 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
}, |
||||
{ |
||||
"type": "function", |
||||
"name": "bad0", |
||||
"source_mapping": { |
||||
"start": 355, |
||||
"length": 132, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/storage-array/storage_signed_integer_array.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/storage-array/storage_signed_integer_array.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
10, |
||||
11, |
||||
12 |
||||
], |
||||
"starting_column": 3, |
||||
"ending_column": 4 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "A", |
||||
"source_mapping": { |
||||
"start": 25, |
||||
"length": 2256, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/storage-array/storage_signed_integer_array.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/storage-array/storage_signed_integer_array.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
10, |
||||
11, |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16, |
||||
17, |
||||
18, |
||||
19, |
||||
20, |
||||
21, |
||||
22, |
||||
23, |
||||
24, |
||||
25, |
||||
26, |
||||
27, |
||||
28, |
||||
29, |
||||
30, |
||||
31, |
||||
32, |
||||
33, |
||||
34, |
||||
35, |
||||
36, |
||||
37, |
||||
38, |
||||
39, |
||||
40, |
||||
41, |
||||
42, |
||||
43, |
||||
44, |
||||
45 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
}, |
||||
"signature": "bad0()" |
||||
} |
||||
}, |
||||
{ |
||||
"type": "node", |
||||
"name": "intArray = (- 1,- 2,- 3)", |
||||
"source_mapping": { |
||||
"start": 384, |
||||
"length": 23, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/storage-array/storage_signed_integer_array.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/storage-array/storage_signed_integer_array.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
11 |
||||
], |
||||
"starting_column": 5, |
||||
"ending_column": 28 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "function", |
||||
"name": "bad0", |
||||
"source_mapping": { |
||||
"start": 355, |
||||
"length": 132, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/storage-array/storage_signed_integer_array.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/storage-array/storage_signed_integer_array.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
10, |
||||
11, |
||||
12 |
||||
], |
||||
"starting_column": 3, |
||||
"ending_column": 4 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "A", |
||||
"source_mapping": { |
||||
"start": 25, |
||||
"length": 2256, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/storage-array/storage_signed_integer_array.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/storage-array/storage_signed_integer_array.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
10, |
||||
11, |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16, |
||||
17, |
||||
18, |
||||
19, |
||||
20, |
||||
21, |
||||
22, |
||||
23, |
||||
24, |
||||
25, |
||||
26, |
||||
27, |
||||
28, |
||||
29, |
||||
30, |
||||
31, |
||||
32, |
||||
33, |
||||
34, |
||||
35, |
||||
36, |
||||
37, |
||||
38, |
||||
39, |
||||
40, |
||||
41, |
||||
42, |
||||
43, |
||||
44, |
||||
45 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
}, |
||||
"signature": "bad0()" |
||||
} |
||||
} |
||||
} |
||||
} |
||||
], |
||||
"description": "Contract A (tests/detectors/storage-array/storage_signed_integer_array.sol#3-45) \n\t- Function A.bad0() (tests/detectors/storage-array/storage_signed_integer_array.sol#10-12)\n\t\t- intArray = (- 1,- 2,- 3) (tests/detectors/storage-array/storage_signed_integer_array.sol#11) has a storage signed integer array assignment\n", |
||||
"markdown": "Contract [A](tests/detectors/storage-array/storage_signed_integer_array.sol#L3-L45) \n\t- Function [A.bad0()](tests/detectors/storage-array/storage_signed_integer_array.sol#L10-L12)\n\t\t- [intArray = (- 1,- 2,- 3)](tests/detectors/storage-array/storage_signed_integer_array.sol#L11) has a storage signed integer array assignment\n", |
||||
"id": "9301f6205d07f9bc40477e940ab7093092a8616caab1c78a2b84412ff6dd2eb1", |
||||
"check": "storage-array", |
||||
"impact": "High", |
||||
"confidence": "Medium" |
||||
}, |
||||
{ |
||||
"elements": [ |
||||
{ |
||||
"type": "contract", |
||||
"name": "A", |
||||
"source_mapping": { |
||||
"start": 25, |
||||
"length": 2256, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/storage-array/storage_signed_integer_array.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/storage-array/storage_signed_integer_array.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
10, |
||||
11, |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16, |
||||
17, |
||||
18, |
||||
19, |
||||
20, |
||||
21, |
||||
22, |
||||
23, |
||||
24, |
||||
25, |
||||
26, |
||||
27, |
||||
28, |
||||
29, |
||||
30, |
||||
31, |
||||
32, |
||||
33, |
||||
34, |
||||
35, |
||||
36, |
||||
37, |
||||
38, |
||||
39, |
||||
40, |
||||
41, |
||||
42, |
||||
43, |
||||
44, |
||||
45 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
}, |
||||
{ |
||||
"type": "function", |
||||
"name": "bad1", |
||||
"source_mapping": { |
||||
"start": 601, |
||||
"length": 170, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/storage-array/storage_signed_integer_array.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/storage-array/storage_signed_integer_array.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
15, |
||||
16, |
||||
17 |
||||
], |
||||
"starting_column": 3, |
||||
"ending_column": 4 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "A", |
||||
"source_mapping": { |
||||
"start": 25, |
||||
"length": 2256, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/storage-array/storage_signed_integer_array.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/storage-array/storage_signed_integer_array.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
10, |
||||
11, |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16, |
||||
17, |
||||
18, |
||||
19, |
||||
20, |
||||
21, |
||||
22, |
||||
23, |
||||
24, |
||||
25, |
||||
26, |
||||
27, |
||||
28, |
||||
29, |
||||
30, |
||||
31, |
||||
32, |
||||
33, |
||||
34, |
||||
35, |
||||
36, |
||||
37, |
||||
38, |
||||
39, |
||||
40, |
||||
41, |
||||
42, |
||||
43, |
||||
44, |
||||
45 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
}, |
||||
"signature": "bad1(int128[3])" |
||||
} |
||||
}, |
||||
{ |
||||
"type": "node", |
||||
"name": "intArray = userArray", |
||||
"source_mapping": { |
||||
"start": 746, |
||||
"length": 20, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/storage-array/storage_signed_integer_array.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/storage-array/storage_signed_integer_array.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
16 |
||||
], |
||||
"starting_column": 5, |
||||
"ending_column": 25 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "function", |
||||
"name": "bad1", |
||||
"source_mapping": { |
||||
"start": 601, |
||||
"length": 170, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/storage-array/storage_signed_integer_array.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/storage-array/storage_signed_integer_array.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
15, |
||||
16, |
||||
17 |
||||
], |
||||
"starting_column": 3, |
||||
"ending_column": 4 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "A", |
||||
"source_mapping": { |
||||
"start": 25, |
||||
"length": 2256, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/storage-array/storage_signed_integer_array.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/storage-array/storage_signed_integer_array.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
10, |
||||
11, |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16, |
||||
17, |
||||
18, |
||||
19, |
||||
20, |
||||
21, |
||||
22, |
||||
23, |
||||
24, |
||||
25, |
||||
26, |
||||
27, |
||||
28, |
||||
29, |
||||
30, |
||||
31, |
||||
32, |
||||
33, |
||||
34, |
||||
35, |
||||
36, |
||||
37, |
||||
38, |
||||
39, |
||||
40, |
||||
41, |
||||
42, |
||||
43, |
||||
44, |
||||
45 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
}, |
||||
"signature": "bad1(int128[3])" |
||||
} |
||||
} |
||||
} |
||||
} |
||||
], |
||||
"description": "Contract A (tests/detectors/storage-array/storage_signed_integer_array.sol#3-45) \n\t- Function A.bad1(int128[3]) (tests/detectors/storage-array/storage_signed_integer_array.sol#15-17)\n\t\t- intArray = userArray (tests/detectors/storage-array/storage_signed_integer_array.sol#16) has a storage signed integer array assignment\n", |
||||
"markdown": "Contract [A](tests/detectors/storage-array/storage_signed_integer_array.sol#L3-L45) \n\t- Function [A.bad1(int128[3])](tests/detectors/storage-array/storage_signed_integer_array.sol#L15-L17)\n\t\t- [intArray = userArray](tests/detectors/storage-array/storage_signed_integer_array.sol#L16) has a storage signed integer array assignment\n", |
||||
"id": "e91a19803d53092184a9c091054f1ef371c8e5f9db15c5be6979bc4d06b70362", |
||||
"check": "storage-array", |
||||
"impact": "High", |
||||
"confidence": "Medium" |
||||
} |
||||
] |
||||
] |
@ -0,0 +1,41 @@ |
||||
interface BaseInterface { |
||||
function f1() external returns(uint); |
||||
function f2() external returns(uint); |
||||
} |
||||
|
||||
interface BaseInterface2 { |
||||
function f3() external returns(uint); |
||||
} |
||||
|
||||
contract DerivedContract_bad0 is BaseInterface, BaseInterface2 { |
||||
function f1() external returns(uint){ |
||||
return 42; |
||||
} |
||||
} |
||||
|
||||
contract AbstractContract_bad1 { |
||||
function f1() external returns(uint); |
||||
function f2() external returns(uint){ |
||||
return 42; |
||||
} |
||||
} |
||||
|
||||
contract BaseInterface3 { |
||||
function get(uint) external returns(uint); |
||||
} |
||||
|
||||
contract DerivedContract_bad2 is BaseInterface3 { |
||||
// the mapping type get(uint => bool) does NOT match the function get(uint) => uint |
||||
mapping(uint => bool) public get; |
||||
function f1() external returns(uint){ |
||||
return 42; |
||||
} |
||||
} |
||||
|
||||
contract DerivedContract_good is BaseInterface3 { |
||||
// In solc >= 0.5.1, the mapping type get(uint => uint) matches the function get(uint) => uint |
||||
mapping(uint => uint) public get; |
||||
function f1() external returns(uint){ |
||||
return 42; |
||||
} |
||||
} |
@ -0,0 +1,346 @@ |
||||
[ |
||||
[ |
||||
{ |
||||
"elements": [ |
||||
{ |
||||
"type": "contract", |
||||
"name": "DerivedContract_bad0", |
||||
"source_mapping": { |
||||
"start": 185, |
||||
"length": 133, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/unimplemented-functions/unimplemented.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/unimplemented-functions/unimplemented.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
10, |
||||
11, |
||||
12, |
||||
13, |
||||
14 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
}, |
||||
{ |
||||
"type": "function", |
||||
"name": "f2", |
||||
"source_mapping": { |
||||
"start": 72, |
||||
"length": 37, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/unimplemented-functions/unimplemented.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/unimplemented-functions/unimplemented.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
3 |
||||
], |
||||
"starting_column": 5, |
||||
"ending_column": 42 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "BaseInterface", |
||||
"source_mapping": { |
||||
"start": 0, |
||||
"length": 111, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/unimplemented-functions/unimplemented.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/unimplemented-functions/unimplemented.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
1, |
||||
2, |
||||
3, |
||||
4 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
}, |
||||
"signature": "f2()" |
||||
} |
||||
}, |
||||
{ |
||||
"type": "function", |
||||
"name": "f3", |
||||
"source_mapping": { |
||||
"start": 144, |
||||
"length": 37, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/unimplemented-functions/unimplemented.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/unimplemented-functions/unimplemented.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
7 |
||||
], |
||||
"starting_column": 5, |
||||
"ending_column": 42 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "BaseInterface2", |
||||
"source_mapping": { |
||||
"start": 113, |
||||
"length": 70, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/unimplemented-functions/unimplemented.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/unimplemented-functions/unimplemented.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
6, |
||||
7, |
||||
8 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
}, |
||||
"signature": "f3()" |
||||
} |
||||
} |
||||
], |
||||
"description": "DerivedContract_bad0 (tests/detectors/unimplemented-functions/unimplemented.sol#10-14) does not implement functions:\n\t- BaseInterface.f2() (tests/detectors/unimplemented-functions/unimplemented.sol#3)\n\t- BaseInterface2.f3() (tests/detectors/unimplemented-functions/unimplemented.sol#7)\n", |
||||
"markdown": "[DerivedContract_bad0](tests/detectors/unimplemented-functions/unimplemented.sol#L10-L14) does not implement functions:\n\t- [BaseInterface.f2()](tests/detectors/unimplemented-functions/unimplemented.sol#L3)\n\t- [BaseInterface2.f3()](tests/detectors/unimplemented-functions/unimplemented.sol#L7)\n", |
||||
"id": "8614d351f7aac0c05e8df6ef7c89c6b46a2b8acf6295c9d5a886ff6489c74a41", |
||||
"check": "unimplemented-functions", |
||||
"impact": "Informational", |
||||
"confidence": "High" |
||||
}, |
||||
{ |
||||
"elements": [ |
||||
{ |
||||
"type": "contract", |
||||
"name": "AbstractContract_bad1", |
||||
"source_mapping": { |
||||
"start": 320, |
||||
"length": 143, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/unimplemented-functions/unimplemented.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/unimplemented-functions/unimplemented.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
16, |
||||
17, |
||||
18, |
||||
19, |
||||
20, |
||||
21 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
}, |
||||
{ |
||||
"type": "function", |
||||
"name": "f1", |
||||
"source_mapping": { |
||||
"start": 357, |
||||
"length": 37, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/unimplemented-functions/unimplemented.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/unimplemented-functions/unimplemented.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
17 |
||||
], |
||||
"starting_column": 5, |
||||
"ending_column": 42 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "AbstractContract_bad1", |
||||
"source_mapping": { |
||||
"start": 320, |
||||
"length": 143, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/unimplemented-functions/unimplemented.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/unimplemented-functions/unimplemented.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
16, |
||||
17, |
||||
18, |
||||
19, |
||||
20, |
||||
21 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
}, |
||||
"signature": "f1()" |
||||
} |
||||
} |
||||
], |
||||
"description": "AbstractContract_bad1 (tests/detectors/unimplemented-functions/unimplemented.sol#16-21) does not implement functions:\n\t- AbstractContract_bad1.f1() (tests/detectors/unimplemented-functions/unimplemented.sol#17)\n", |
||||
"markdown": "[AbstractContract_bad1](tests/detectors/unimplemented-functions/unimplemented.sol#L16-L21) does not implement functions:\n\t- [AbstractContract_bad1.f1()](tests/detectors/unimplemented-functions/unimplemented.sol#L17)\n", |
||||
"id": "adc202df4717efc4e19b549c0e623a79fac759a36bffb5d5e4aac401e33375d7", |
||||
"check": "unimplemented-functions", |
||||
"impact": "Informational", |
||||
"confidence": "High" |
||||
}, |
||||
{ |
||||
"elements": [ |
||||
{ |
||||
"type": "contract", |
||||
"name": "DerivedContract_bad2", |
||||
"source_mapping": { |
||||
"start": 541, |
||||
"length": 232, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/unimplemented-functions/unimplemented.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/unimplemented-functions/unimplemented.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
27, |
||||
28, |
||||
29, |
||||
30, |
||||
31, |
||||
32, |
||||
33 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
}, |
||||
{ |
||||
"type": "function", |
||||
"name": "get", |
||||
"source_mapping": { |
||||
"start": 495, |
||||
"length": 42, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/unimplemented-functions/unimplemented.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/unimplemented-functions/unimplemented.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
24 |
||||
], |
||||
"starting_column": 5, |
||||
"ending_column": 47 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "BaseInterface3", |
||||
"source_mapping": { |
||||
"start": 465, |
||||
"length": 74, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/unimplemented-functions/unimplemented.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/unimplemented-functions/unimplemented.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
23, |
||||
24, |
||||
25 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
}, |
||||
"signature": "get(uint256)" |
||||
} |
||||
} |
||||
], |
||||
"description": "DerivedContract_bad2 (tests/detectors/unimplemented-functions/unimplemented.sol#27-33) does not implement functions:\n\t- BaseInterface3.get(uint256) (tests/detectors/unimplemented-functions/unimplemented.sol#24)\n", |
||||
"markdown": "[DerivedContract_bad2](tests/detectors/unimplemented-functions/unimplemented.sol#L27-L33) does not implement functions:\n\t- [BaseInterface3.get(uint256)](tests/detectors/unimplemented-functions/unimplemented.sol#L24)\n", |
||||
"id": "31915d2f480e24ddd054de973440a02abdac0ccd6332c47cd4eb8d836d3fddda", |
||||
"check": "unimplemented-functions", |
||||
"impact": "Informational", |
||||
"confidence": "High" |
||||
}, |
||||
{ |
||||
"elements": [ |
||||
{ |
||||
"type": "contract", |
||||
"name": "DerivedContract_good", |
||||
"source_mapping": { |
||||
"start": 775, |
||||
"length": 243, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/unimplemented-functions/unimplemented.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/unimplemented-functions/unimplemented.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
35, |
||||
36, |
||||
37, |
||||
38, |
||||
39, |
||||
40, |
||||
41 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
}, |
||||
{ |
||||
"type": "function", |
||||
"name": "get", |
||||
"source_mapping": { |
||||
"start": 495, |
||||
"length": 42, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/unimplemented-functions/unimplemented.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/unimplemented-functions/unimplemented.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
24 |
||||
], |
||||
"starting_column": 5, |
||||
"ending_column": 47 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "BaseInterface3", |
||||
"source_mapping": { |
||||
"start": 465, |
||||
"length": 74, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/unimplemented-functions/unimplemented.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/unimplemented-functions/unimplemented.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
23, |
||||
24, |
||||
25 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
}, |
||||
"signature": "get(uint256)" |
||||
} |
||||
} |
||||
], |
||||
"description": "DerivedContract_good (tests/detectors/unimplemented-functions/unimplemented.sol#35-41) does not implement functions:\n\t- BaseInterface3.get(uint256) (tests/detectors/unimplemented-functions/unimplemented.sol#24)\n", |
||||
"markdown": "[DerivedContract_good](tests/detectors/unimplemented-functions/unimplemented.sol#L35-L41) does not implement functions:\n\t- [BaseInterface3.get(uint256)](tests/detectors/unimplemented-functions/unimplemented.sol#L24)\n", |
||||
"id": "08d3e8a72b5da6d189acb46ecd36f00787a87812727526a0cae248a2bac348fc", |
||||
"check": "unimplemented-functions", |
||||
"impact": "Informational", |
||||
"confidence": "High" |
||||
} |
||||
] |
||||
] |
@ -0,0 +1,136 @@ |
||||
pragma solidity 0.5.8; |
||||
|
||||
contract bad0 { |
||||
constructor() public { |
||||
/* Uninitialized function pointer */ |
||||
function(uint256) internal returns(uint256) a; |
||||
a(10); |
||||
} |
||||
} |
||||
|
||||
contract bad1 { |
||||
constructor() public { |
||||
/* Uninitialized function pointer but external visibility */ |
||||
/* Although the Solidity bug report does not specify external visibility, we believe both internal/external may be vulnerable */ |
||||
function(uint256) external returns(uint256) b; |
||||
b(10); |
||||
} |
||||
} |
||||
|
||||
contract bad2 { |
||||
struct S { |
||||
/* Uninitialized function pointer within a struct*/ |
||||
function(uint256) internal returns(uint256) a; |
||||
} |
||||
constructor() public { |
||||
S memory s; |
||||
s.a(10); |
||||
} |
||||
} |
||||
|
||||
contract bad3 { |
||||
/* Uninitialized state variable function pointer written-to after call */ |
||||
function(uint256) internal returns(uint256) a; |
||||
|
||||
constructor() public { |
||||
a(10); |
||||
a = foo; |
||||
} |
||||
function foo(uint256 i) internal returns(uint256) { |
||||
return(i); |
||||
} |
||||
} |
||||
|
||||
contract good0 { |
||||
constructor() public { |
||||
/* Uninitialized function pointer but not called */ |
||||
function(uint256) internal returns(uint256) a; |
||||
} |
||||
} |
||||
|
||||
contract good1 { |
||||
constructor() public { |
||||
/* Initialized function pointer */ |
||||
function(uint256) internal returns(uint256) a = foo; |
||||
a(10); |
||||
} |
||||
function foo(uint256 i) internal returns(uint256) { |
||||
return(i); |
||||
} |
||||
} |
||||
|
||||
contract good2 { |
||||
constructor() public { |
||||
} |
||||
function foo(uint256 i) internal returns(uint256) { |
||||
/* Uninitialized function pointer but not in constructor */ |
||||
function(uint256) internal returns(uint256) a; |
||||
a(10); |
||||
return(i); |
||||
} |
||||
} |
||||
|
||||
contract good3 { |
||||
constructor() public { |
||||
/* Normal function call */ |
||||
foo(10); |
||||
} |
||||
function foo(uint256 i) internal returns(uint256) { |
||||
return(i); |
||||
} |
||||
} |
||||
|
||||
contract good4 { |
||||
struct S { |
||||
uint S_i; |
||||
} |
||||
constructor() public { |
||||
/* Uninitialized variables of other types but not function pointer */ |
||||
uint i; |
||||
address addr; |
||||
uint[] memory arr; |
||||
S memory s; |
||||
} |
||||
} |
||||
|
||||
contract good5 { |
||||
constructor() public { |
||||
/* Uninitialized local function pointer written to later */ |
||||
function(uint256) internal returns(uint256) a; |
||||
a = foo; |
||||
a(10); |
||||
} |
||||
function foo(uint256 i) internal returns(uint256) { |
||||
return(i); |
||||
} |
||||
} |
||||
|
||||
contract good6 { |
||||
/* Uninitialized state variable function pointer written to later */ |
||||
function(uint256) internal returns(uint256) a; |
||||
|
||||
constructor() public { |
||||
a = foo; |
||||
a(10); |
||||
} |
||||
function foo(uint256 i) internal returns(uint256) { |
||||
return(i); |
||||
} |
||||
} |
||||
|
||||
contract good7 { |
||||
struct S { |
||||
/* Uninitialized function pointer within a struct*/ |
||||
function(uint256) internal returns(uint256) a; |
||||
} |
||||
|
||||
constructor() public { |
||||
S memory s; |
||||
s.a = foo; |
||||
s.a(10); |
||||
} |
||||
|
||||
function foo(uint256 i) internal returns(uint256) { |
||||
return(i); |
||||
} |
||||
} |
@ -0,0 +1,325 @@ |
||||
[ |
||||
[ |
||||
{ |
||||
"elements": [ |
||||
{ |
||||
"type": "contract", |
||||
"name": "bad0", |
||||
"source_mapping": { |
||||
"start": 24, |
||||
"length": 149, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
}, |
||||
{ |
||||
"type": "node", |
||||
"name": "a(10)", |
||||
"source_mapping": { |
||||
"start": 161, |
||||
"length": 5, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
7 |
||||
], |
||||
"starting_column": 5, |
||||
"ending_column": 10 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "function", |
||||
"name": "constructor", |
||||
"source_mapping": { |
||||
"start": 42, |
||||
"length": 129, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8 |
||||
], |
||||
"starting_column": 3, |
||||
"ending_column": 4 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "bad0", |
||||
"source_mapping": { |
||||
"start": 24, |
||||
"length": 149, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
}, |
||||
"signature": "constructor()" |
||||
} |
||||
} |
||||
} |
||||
} |
||||
], |
||||
"description": "Contract bad0 (tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol#3-9) \n\t a(10) (tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol#7) is an unintialized function pointer call in a constructor\n", |
||||
"markdown": "Contract [bad0](tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol#L3-L9) \n\t [a(10)](tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol#L7) is an unintialized function pointer call in a constructor\n", |
||||
"id": "6e9480c70e9d054243bb478398b26663f05444b4b9b858109d67f9c63dbbc3e2", |
||||
"check": "uninitialized-fptr-cst", |
||||
"impact": "Low", |
||||
"confidence": "High" |
||||
}, |
||||
{ |
||||
"elements": [ |
||||
{ |
||||
"type": "contract", |
||||
"name": "bad1", |
||||
"source_mapping": { |
||||
"start": 175, |
||||
"length": 306, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
11, |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16, |
||||
17, |
||||
18 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
}, |
||||
{ |
||||
"type": "node", |
||||
"name": "b(10)", |
||||
"source_mapping": { |
||||
"start": 469, |
||||
"length": 5, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
16 |
||||
], |
||||
"starting_column": 5, |
||||
"ending_column": 10 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "function", |
||||
"name": "constructor", |
||||
"source_mapping": { |
||||
"start": 193, |
||||
"length": 286, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16, |
||||
17 |
||||
], |
||||
"starting_column": 3, |
||||
"ending_column": 4 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "bad1", |
||||
"source_mapping": { |
||||
"start": 175, |
||||
"length": 306, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
11, |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16, |
||||
17, |
||||
18 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
}, |
||||
"signature": "constructor()" |
||||
} |
||||
} |
||||
} |
||||
} |
||||
], |
||||
"description": "Contract bad1 (tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol#11-18) \n\t b(10) (tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol#16) is an unintialized function pointer call in a constructor\n", |
||||
"markdown": "Contract [bad1](tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol#L11-L18) \n\t [b(10)](tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol#L16) is an unintialized function pointer call in a constructor\n", |
||||
"id": "b0a15c051d9962762902c5565802334898e572e98018b42b85a89b45208c50d2", |
||||
"check": "uninitialized-fptr-cst", |
||||
"impact": "Low", |
||||
"confidence": "High" |
||||
}, |
||||
{ |
||||
"elements": [ |
||||
{ |
||||
"type": "contract", |
||||
"name": "bad3", |
||||
"source_mapping": { |
||||
"start": 684, |
||||
"length": 269, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
31, |
||||
32, |
||||
33, |
||||
34, |
||||
35, |
||||
36, |
||||
37, |
||||
38, |
||||
39, |
||||
40, |
||||
41, |
||||
42 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
}, |
||||
{ |
||||
"type": "node", |
||||
"name": "a(10)", |
||||
"source_mapping": { |
||||
"start": 855, |
||||
"length": 5, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
36 |
||||
], |
||||
"starting_column": 5, |
||||
"ending_column": 10 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "function", |
||||
"name": "constructor", |
||||
"source_mapping": { |
||||
"start": 828, |
||||
"length": 50, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
35, |
||||
36, |
||||
37, |
||||
38 |
||||
], |
||||
"starting_column": 3, |
||||
"ending_column": 4 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "bad3", |
||||
"source_mapping": { |
||||
"start": 684, |
||||
"length": 269, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
31, |
||||
32, |
||||
33, |
||||
34, |
||||
35, |
||||
36, |
||||
37, |
||||
38, |
||||
39, |
||||
40, |
||||
41, |
||||
42 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
}, |
||||
"signature": "constructor()" |
||||
} |
||||
} |
||||
} |
||||
} |
||||
], |
||||
"description": "Contract bad3 (tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol#31-42) \n\t a(10) (tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol#36) is an unintialized function pointer call in a constructor\n", |
||||
"markdown": "Contract [bad3](tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol#L31-L42) \n\t [a(10)](tests/detectors/uninitialized-fptr-cst/uninitialized_function_ptr_constructor.sol#L36) is an unintialized function pointer call in a constructor\n", |
||||
"id": "1f12cc039e869f6f13be8a85e2d98a53212dc95e859908a9188dd6b152fb804f", |
||||
"check": "uninitialized-fptr-cst", |
||||
"impact": "Low", |
||||
"confidence": "High" |
||||
} |
||||
] |
||||
] |
@ -0,0 +1,28 @@ |
||||
contract BadPRNG{ |
||||
event Time(uint); |
||||
|
||||
function bad0() external{ |
||||
uint i = block.timestamp % 10; |
||||
} |
||||
|
||||
function bad1() external{ |
||||
uint i = now % 10; |
||||
} |
||||
|
||||
function bad2() external{ |
||||
uint i = uint256(blockhash(10000)) % 10; |
||||
} |
||||
|
||||
function foo() public returns (uint) { |
||||
return(uint256(blockhash(10000))); |
||||
} |
||||
|
||||
function bad3() external{ |
||||
uint i = foo() % 10; |
||||
} |
||||
|
||||
function good() external{ |
||||
emit Time(block.timestamp); |
||||
} |
||||
} |
||||
|
@ -0,0 +1,660 @@ |
||||
[ |
||||
[ |
||||
{ |
||||
"elements": [ |
||||
{ |
||||
"type": "function", |
||||
"name": "bad0", |
||||
"source_mapping": { |
||||
"start": 45, |
||||
"length": 68, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/weak-prng/bad_prng.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/weak-prng/bad_prng.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
4, |
||||
5, |
||||
6 |
||||
], |
||||
"starting_column": 5, |
||||
"ending_column": 6 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "BadPRNG", |
||||
"source_mapping": { |
||||
"start": 0, |
||||
"length": 499, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/weak-prng/bad_prng.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/weak-prng/bad_prng.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
1, |
||||
2, |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
10, |
||||
11, |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16, |
||||
17, |
||||
18, |
||||
19, |
||||
20, |
||||
21, |
||||
22, |
||||
23, |
||||
24, |
||||
25, |
||||
26, |
||||
27 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
}, |
||||
"signature": "bad0()" |
||||
} |
||||
}, |
||||
{ |
||||
"type": "node", |
||||
"name": "i = block.timestamp % 10", |
||||
"source_mapping": { |
||||
"start": 77, |
||||
"length": 29, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/weak-prng/bad_prng.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/weak-prng/bad_prng.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
5 |
||||
], |
||||
"starting_column": 7, |
||||
"ending_column": 36 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "function", |
||||
"name": "bad0", |
||||
"source_mapping": { |
||||
"start": 45, |
||||
"length": 68, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/weak-prng/bad_prng.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/weak-prng/bad_prng.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
4, |
||||
5, |
||||
6 |
||||
], |
||||
"starting_column": 5, |
||||
"ending_column": 6 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "BadPRNG", |
||||
"source_mapping": { |
||||
"start": 0, |
||||
"length": 499, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/weak-prng/bad_prng.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/weak-prng/bad_prng.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
1, |
||||
2, |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
10, |
||||
11, |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16, |
||||
17, |
||||
18, |
||||
19, |
||||
20, |
||||
21, |
||||
22, |
||||
23, |
||||
24, |
||||
25, |
||||
26, |
||||
27 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
}, |
||||
"signature": "bad0()" |
||||
} |
||||
} |
||||
} |
||||
} |
||||
], |
||||
"description": "BadPRNG.bad0() (tests/detectors/weak-prng/bad_prng.sol#4-6) uses a weak PRNG: \"i = block.timestamp % 10 (tests/detectors/weak-prng/bad_prng.sol#5)\" \n", |
||||
"markdown": "[BadPRNG.bad0()](tests/detectors/weak-prng/bad_prng.sol#L4-L6) uses a weak PRNG: \"[i = block.timestamp % 10](tests/detectors/weak-prng/bad_prng.sol#L5)\" \n", |
||||
"id": "af624d9c7f3f688c1bad5ecaee81085e0d5cde4e6a55de34ff93684527619748", |
||||
"check": "weak-prng", |
||||
"impact": "High", |
||||
"confidence": "Medium" |
||||
}, |
||||
{ |
||||
"elements": [ |
||||
{ |
||||
"type": "function", |
||||
"name": "bad1", |
||||
"source_mapping": { |
||||
"start": 122, |
||||
"length": 56, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/weak-prng/bad_prng.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/weak-prng/bad_prng.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
8, |
||||
9, |
||||
10 |
||||
], |
||||
"starting_column": 5, |
||||
"ending_column": 6 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "BadPRNG", |
||||
"source_mapping": { |
||||
"start": 0, |
||||
"length": 499, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/weak-prng/bad_prng.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/weak-prng/bad_prng.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
1, |
||||
2, |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
10, |
||||
11, |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16, |
||||
17, |
||||
18, |
||||
19, |
||||
20, |
||||
21, |
||||
22, |
||||
23, |
||||
24, |
||||
25, |
||||
26, |
||||
27 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
}, |
||||
"signature": "bad1()" |
||||
} |
||||
}, |
||||
{ |
||||
"type": "node", |
||||
"name": "i = now % 10", |
||||
"source_mapping": { |
||||
"start": 154, |
||||
"length": 17, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/weak-prng/bad_prng.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/weak-prng/bad_prng.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
9 |
||||
], |
||||
"starting_column": 7, |
||||
"ending_column": 24 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "function", |
||||
"name": "bad1", |
||||
"source_mapping": { |
||||
"start": 122, |
||||
"length": 56, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/weak-prng/bad_prng.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/weak-prng/bad_prng.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
8, |
||||
9, |
||||
10 |
||||
], |
||||
"starting_column": 5, |
||||
"ending_column": 6 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "BadPRNG", |
||||
"source_mapping": { |
||||
"start": 0, |
||||
"length": 499, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/weak-prng/bad_prng.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/weak-prng/bad_prng.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
1, |
||||
2, |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
10, |
||||
11, |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16, |
||||
17, |
||||
18, |
||||
19, |
||||
20, |
||||
21, |
||||
22, |
||||
23, |
||||
24, |
||||
25, |
||||
26, |
||||
27 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
}, |
||||
"signature": "bad1()" |
||||
} |
||||
} |
||||
} |
||||
} |
||||
], |
||||
"description": "BadPRNG.bad1() (tests/detectors/weak-prng/bad_prng.sol#8-10) uses a weak PRNG: \"i = now % 10 (tests/detectors/weak-prng/bad_prng.sol#9)\" \n", |
||||
"markdown": "[BadPRNG.bad1()](tests/detectors/weak-prng/bad_prng.sol#L8-L10) uses a weak PRNG: \"[i = now % 10](tests/detectors/weak-prng/bad_prng.sol#L9)\" \n", |
||||
"id": "fe07d1e4f27274570cfb85530c1cbf7fb7a9004f475b91d1a3762452b017e1b9", |
||||
"check": "weak-prng", |
||||
"impact": "High", |
||||
"confidence": "Medium" |
||||
}, |
||||
{ |
||||
"elements": [ |
||||
{ |
||||
"type": "function", |
||||
"name": "bad2", |
||||
"source_mapping": { |
||||
"start": 184, |
||||
"length": 78, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/weak-prng/bad_prng.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/weak-prng/bad_prng.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
12, |
||||
13, |
||||
14 |
||||
], |
||||
"starting_column": 5, |
||||
"ending_column": 6 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "BadPRNG", |
||||
"source_mapping": { |
||||
"start": 0, |
||||
"length": 499, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/weak-prng/bad_prng.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/weak-prng/bad_prng.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
1, |
||||
2, |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
10, |
||||
11, |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16, |
||||
17, |
||||
18, |
||||
19, |
||||
20, |
||||
21, |
||||
22, |
||||
23, |
||||
24, |
||||
25, |
||||
26, |
||||
27 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
}, |
||||
"signature": "bad2()" |
||||
} |
||||
}, |
||||
{ |
||||
"type": "node", |
||||
"name": "i = uint256(blockhash(uint256)(10000)) % 10", |
||||
"source_mapping": { |
||||
"start": 216, |
||||
"length": 39, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/weak-prng/bad_prng.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/weak-prng/bad_prng.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
13 |
||||
], |
||||
"starting_column": 7, |
||||
"ending_column": 46 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "function", |
||||
"name": "bad2", |
||||
"source_mapping": { |
||||
"start": 184, |
||||
"length": 78, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/weak-prng/bad_prng.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/weak-prng/bad_prng.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
12, |
||||
13, |
||||
14 |
||||
], |
||||
"starting_column": 5, |
||||
"ending_column": 6 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "BadPRNG", |
||||
"source_mapping": { |
||||
"start": 0, |
||||
"length": 499, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/weak-prng/bad_prng.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/weak-prng/bad_prng.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
1, |
||||
2, |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
10, |
||||
11, |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16, |
||||
17, |
||||
18, |
||||
19, |
||||
20, |
||||
21, |
||||
22, |
||||
23, |
||||
24, |
||||
25, |
||||
26, |
||||
27 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
}, |
||||
"signature": "bad2()" |
||||
} |
||||
} |
||||
} |
||||
} |
||||
], |
||||
"description": "BadPRNG.bad2() (tests/detectors/weak-prng/bad_prng.sol#12-14) uses a weak PRNG: \"i = uint256(blockhash(uint256)(10000)) % 10 (tests/detectors/weak-prng/bad_prng.sol#13)\" \n", |
||||
"markdown": "[BadPRNG.bad2()](tests/detectors/weak-prng/bad_prng.sol#L12-L14) uses a weak PRNG: \"[i = uint256(blockhash(uint256)(10000)) % 10](tests/detectors/weak-prng/bad_prng.sol#L13)\" \n", |
||||
"id": "100d285386f797a469c6797fcce41350b1984f7e7aab1532580d9b69a774b6f5", |
||||
"check": "weak-prng", |
||||
"impact": "High", |
||||
"confidence": "Medium" |
||||
}, |
||||
{ |
||||
"elements": [ |
||||
{ |
||||
"type": "function", |
||||
"name": "bad3", |
||||
"source_mapping": { |
||||
"start": 363, |
||||
"length": 58, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/weak-prng/bad_prng.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/weak-prng/bad_prng.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
20, |
||||
21, |
||||
22 |
||||
], |
||||
"starting_column": 5, |
||||
"ending_column": 6 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "BadPRNG", |
||||
"source_mapping": { |
||||
"start": 0, |
||||
"length": 499, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/weak-prng/bad_prng.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/weak-prng/bad_prng.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
1, |
||||
2, |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
10, |
||||
11, |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16, |
||||
17, |
||||
18, |
||||
19, |
||||
20, |
||||
21, |
||||
22, |
||||
23, |
||||
24, |
||||
25, |
||||
26, |
||||
27 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
}, |
||||
"signature": "bad3()" |
||||
} |
||||
}, |
||||
{ |
||||
"type": "node", |
||||
"name": "i = foo() % 10", |
||||
"source_mapping": { |
||||
"start": 395, |
||||
"length": 19, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/weak-prng/bad_prng.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/weak-prng/bad_prng.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
21 |
||||
], |
||||
"starting_column": 7, |
||||
"ending_column": 26 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "function", |
||||
"name": "bad3", |
||||
"source_mapping": { |
||||
"start": 363, |
||||
"length": 58, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/weak-prng/bad_prng.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/weak-prng/bad_prng.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
20, |
||||
21, |
||||
22 |
||||
], |
||||
"starting_column": 5, |
||||
"ending_column": 6 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "BadPRNG", |
||||
"source_mapping": { |
||||
"start": 0, |
||||
"length": 499, |
||||
"filename_used": "/GENERIC_PATH", |
||||
"filename_relative": "tests/detectors/weak-prng/bad_prng.sol", |
||||
"filename_absolute": "/GENERIC_PATH", |
||||
"filename_short": "tests/detectors/weak-prng/bad_prng.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
1, |
||||
2, |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
10, |
||||
11, |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16, |
||||
17, |
||||
18, |
||||
19, |
||||
20, |
||||
21, |
||||
22, |
||||
23, |
||||
24, |
||||
25, |
||||
26, |
||||
27 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
}, |
||||
"signature": "bad3()" |
||||
} |
||||
} |
||||
} |
||||
} |
||||
], |
||||
"description": "BadPRNG.bad3() (tests/detectors/weak-prng/bad_prng.sol#20-22) uses a weak PRNG: \"i = foo() % 10 (tests/detectors/weak-prng/bad_prng.sol#21)\" \n", |
||||
"markdown": "[BadPRNG.bad3()](tests/detectors/weak-prng/bad_prng.sol#L20-L22) uses a weak PRNG: \"[i = foo() % 10](tests/detectors/weak-prng/bad_prng.sol#L21)\" \n", |
||||
"id": "a382f093e54d2c7beb2c10b3537790371f4b95545c48d1300fd25d20717d137a", |
||||
"check": "weak-prng", |
||||
"impact": "High", |
||||
"confidence": "Medium" |
||||
} |
||||
] |
||||
] |
Loading…
Reference in new issue