Merge branch 'dev' into dev-improve-reentrancy

pull/1351/head
Josselin Feist 2 years ago
commit 303ed83736
  1. 20
      slither/core/declarations/custom_error.py
  2. 5
      slither/core/expressions/literal.py
  3. 13
      slither/detectors/statements/unprotected_upgradeable.py
  4. 3
      slither/slithir/variables/constant.py
  5. 2
      slither/solc_parsing/expressions/find_variable.py
  6. BIN
      tests/ast-parsing/compile/custom_error-0.8.4.sol-0.8.10-compact.zip
  7. BIN
      tests/ast-parsing/compile/custom_error-0.8.4.sol-0.8.11-compact.zip
  8. BIN
      tests/ast-parsing/compile/custom_error-0.8.4.sol-0.8.12-compact.zip
  9. BIN
      tests/ast-parsing/compile/custom_error-0.8.4.sol-0.8.13-compact.zip
  10. BIN
      tests/ast-parsing/compile/custom_error-0.8.4.sol-0.8.14-compact.zip
  11. BIN
      tests/ast-parsing/compile/custom_error-0.8.4.sol-0.8.15-compact.zip
  12. BIN
      tests/ast-parsing/compile/custom_error-0.8.4.sol-0.8.4-compact.zip
  13. BIN
      tests/ast-parsing/compile/custom_error-0.8.4.sol-0.8.5-compact.zip
  14. BIN
      tests/ast-parsing/compile/custom_error-0.8.4.sol-0.8.6-compact.zip
  15. BIN
      tests/ast-parsing/compile/custom_error-0.8.4.sol-0.8.7-compact.zip
  16. BIN
      tests/ast-parsing/compile/custom_error-0.8.4.sol-0.8.8-compact.zip
  17. BIN
      tests/ast-parsing/compile/custom_error-0.8.4.sol-0.8.9-compact.zip
  18. 17
      tests/ast-parsing/custom_error-0.8.4.sol
  19. 23
      tests/ast-parsing/expected/custom_error-0.8.4.sol-0.8.10-compact.json
  20. 23
      tests/ast-parsing/expected/custom_error-0.8.4.sol-0.8.11-compact.json
  21. 23
      tests/ast-parsing/expected/custom_error-0.8.4.sol-0.8.12-compact.json
  22. 23
      tests/ast-parsing/expected/custom_error-0.8.4.sol-0.8.13-compact.json
  23. 23
      tests/ast-parsing/expected/custom_error-0.8.4.sol-0.8.14-compact.json
  24. 23
      tests/ast-parsing/expected/custom_error-0.8.4.sol-0.8.15-compact.json
  25. 5
      tests/ast-parsing/expected/custom_error-0.8.4.sol-0.8.4-compact.json
  26. 5
      tests/ast-parsing/expected/custom_error-0.8.4.sol-0.8.5-compact.json
  27. 5
      tests/ast-parsing/expected/custom_error-0.8.4.sol-0.8.6-compact.json
  28. 5
      tests/ast-parsing/expected/custom_error-0.8.4.sol-0.8.7-compact.json
  29. 5
      tests/ast-parsing/expected/custom_error-0.8.4.sol-0.8.8-compact.json
  30. 5
      tests/ast-parsing/expected/custom_error-0.8.4.sol-0.8.9-compact.json
  31. 18
      tests/detectors/unprotected-upgrade/0.7.6/Fixed.sol
  32. 10
      tests/detectors/unprotected-upgrade/0.7.6/Initializable.sol
  33. 14
      tests/detectors/unprotected-upgrade/0.8.15/Buggy.sol
  34. 145
      tests/detectors/unprotected-upgrade/0.8.15/Buggy.sol.0.8.15.UnprotectedUpgradeable.json
  35. 73
      tests/detectors/unprotected-upgrade/0.8.15/Fixed.sol
  36. 3
      tests/detectors/unprotected-upgrade/0.8.15/Fixed.sol.0.8.15.UnprotectedUpgradeable.json
  37. 15
      tests/detectors/unprotected-upgrade/0.8.15/Initializable.sol
  38. 5
      tests/detectors/unprotected-upgrade/0.8.15/OnlyProxy.sol
  39. 15
      tests/detectors/unprotected-upgrade/0.8.15/whitelisted.sol
  40. 3
      tests/detectors/unprotected-upgrade/0.8.15/whitelisted.sol.0.8.15.UnprotectedUpgradeable.json
  41. 2
      tests/test_ast_parsing.py
  42. 15
      tests/test_detectors.py

@ -16,6 +16,7 @@ class CustomError(SourceMapping):
self._compilation_unit = compilation_unit
self._solidity_signature: Optional[str] = None
self._full_name: Optional[str] = None
@property
def name(self) -> str:
@ -50,7 +51,7 @@ class CustomError(SourceMapping):
return str(t)
@property
def solidity_signature(self) -> str:
def solidity_signature(self) -> Optional[str]:
"""
Return a signature following the Solidity Standard
Contract and converted into address
@ -71,8 +72,21 @@ class CustomError(SourceMapping):
Returns:
"""
parameters = [self._convert_type_for_solidity_signature(x.type) for x in self.parameters]
self._solidity_signature = self.name + "(" + ",".join(parameters) + ")"
parameters = [x.type for x in self.parameters]
self._full_name = self.name + "(" + ",".join(map(str, parameters)) + ")"
solidity_parameters = map(self._convert_type_for_solidity_signature, parameters)
self._solidity_signature = self.name + "(" + ",".join(solidity_parameters) + ")"
@property
def full_name(self) -> Optional[str]:
"""
Return the error signature without
converting contract into address
:return: the error signature
"""
if self._full_name is None:
raise ValueError("Custom Error not yet built")
return self._full_name
# endregion
###################################################################################

@ -31,3 +31,8 @@ class Literal(Expression):
return str(convert_subdenomination(self._value, self.subdenomination))
# be sure to handle any character
return str(self._value)
def __eq__(self, other):
if not isinstance(other, Literal):
return False
return (self.value, self.subdenomination) == (other.value, other.subdenomination)

@ -22,11 +22,20 @@ def _can_be_destroyed(contract: Contract) -> List[Function]:
return targets
def _has_initializer_modifier(functions: List[Function]) -> bool:
def _has_initializing_protection(functions: List[Function]) -> bool:
# Detects "initializer" constructor modifiers and "_disableInitializers()" constructor internal calls
# https://docs.openzeppelin.com/upgrades-plugins/1.x/writing-upgradeable#initializing_the_implementation_contract
for f in functions:
for m in f.modifiers:
if m.name == "initializer":
return True
for ifc in f.all_internal_calls():
if ifc.name == "_disableInitializers":
return True
# to avoid future FPs in different modifier + function naming implementations, we can also implement a broader check for state var "_initialized" being written to in the constructor
# though this is still subject to naming false positives...
return False
@ -82,7 +91,7 @@ class UnprotectedUpgradeable(AbstractDetector):
for contract in self.compilation_unit.contracts_derived:
if contract.is_upgradeable:
if not _has_initializer_modifier(contract.constructors):
if not _has_initializing_protection(contract.constructors):
functions_that_can_destroy = _can_be_destroyed(contract)
if functions_that_can_destroy:
initialize_functions = _initialize_functions(contract)

@ -75,3 +75,6 @@ class Constant(SlithIRVariable):
def __repr__(self):
return f"{str(self.value)}"
def __hash__(self) -> int:
return self._val.__hash__()

@ -224,7 +224,7 @@ def _find_in_contract(
custom_errors = contract.custom_errors
try:
for custom_error in custom_errors:
if var_name == custom_error.solidity_signature:
if var_name in [custom_error.solidity_signature, custom_error.full_name]:
return custom_error
except ValueError:
# This can happen as custom error sol signature might not have been built

@ -52,4 +52,21 @@ contract B is A{
}
}
contract ContractArgCustomError {
error E(ContractArgCustomError a);
function f() payable external {
g();
}
function g() private {
bool something = h();
if (something) {
revert E(this);
}
}
function h() private returns (bool something) {
}
}

@ -0,0 +1,23 @@
{
"I": {},
"VendingMachine": {
"err0()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
"err1()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n",
"err2()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n",
"err3()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
"err4()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n"
},
"A": {
"f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n"
},
"B": {
"f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
"g()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
"h()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n"
},
"ContractArgCustomError": {
"f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
"g()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: IF 2\n\"];\n2->3[label=\"True\"];\n2->4[label=\"False\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END_IF 4\n\"];\n}\n",
"h()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n"
}
}

@ -0,0 +1,23 @@
{
"I": {},
"VendingMachine": {
"err0()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
"err1()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n",
"err2()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n",
"err3()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
"err4()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n"
},
"A": {
"f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n"
},
"B": {
"f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
"g()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
"h()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n"
},
"ContractArgCustomError": {
"f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
"g()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: IF 2\n\"];\n2->3[label=\"True\"];\n2->4[label=\"False\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END_IF 4\n\"];\n}\n",
"h()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n"
}
}

@ -0,0 +1,23 @@
{
"I": {},
"VendingMachine": {
"err0()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
"err1()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n",
"err2()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n",
"err3()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
"err4()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n"
},
"A": {
"f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n"
},
"B": {
"f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
"g()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
"h()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n"
},
"ContractArgCustomError": {
"f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
"g()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: IF 2\n\"];\n2->3[label=\"True\"];\n2->4[label=\"False\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END_IF 4\n\"];\n}\n",
"h()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n"
}
}

@ -0,0 +1,23 @@
{
"I": {},
"VendingMachine": {
"err0()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
"err1()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n",
"err2()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n",
"err3()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
"err4()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n"
},
"A": {
"f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n"
},
"B": {
"f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
"g()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
"h()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n"
},
"ContractArgCustomError": {
"f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
"g()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: IF 2\n\"];\n2->3[label=\"True\"];\n2->4[label=\"False\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END_IF 4\n\"];\n}\n",
"h()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n"
}
}

@ -0,0 +1,23 @@
{
"I": {},
"VendingMachine": {
"err0()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
"err1()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n",
"err2()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n",
"err3()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
"err4()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n"
},
"A": {
"f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n"
},
"B": {
"f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
"g()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
"h()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n"
},
"ContractArgCustomError": {
"f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
"g()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: IF 2\n\"];\n2->3[label=\"True\"];\n2->4[label=\"False\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END_IF 4\n\"];\n}\n",
"h()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n"
}
}

@ -0,0 +1,23 @@
{
"I": {},
"VendingMachine": {
"err0()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
"err1()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n",
"err2()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n",
"err3()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
"err4()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n"
},
"A": {
"f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n"
},
"B": {
"f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
"g()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
"h()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n"
},
"ContractArgCustomError": {
"f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
"g()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: IF 2\n\"];\n2->3[label=\"True\"];\n2->4[label=\"False\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END_IF 4\n\"];\n}\n",
"h()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n"
}
}

@ -14,5 +14,10 @@
"f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
"g()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
"h()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n"
},
"ContractArgCustomError": {
"f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
"g()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: IF 2\n\"];\n2->3[label=\"True\"];\n2->4[label=\"False\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END_IF 4\n\"];\n}\n",
"h()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n"
}
}

@ -14,5 +14,10 @@
"f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
"g()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
"h()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n"
},
"ContractArgCustomError": {
"f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
"g()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: IF 2\n\"];\n2->3[label=\"True\"];\n2->4[label=\"False\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END_IF 4\n\"];\n}\n",
"h()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n"
}
}

@ -14,5 +14,10 @@
"f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
"g()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
"h()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n"
},
"ContractArgCustomError": {
"f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
"g()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: IF 2\n\"];\n2->3[label=\"True\"];\n2->4[label=\"False\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END_IF 4\n\"];\n}\n",
"h()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n"
}
}

@ -14,5 +14,10 @@
"f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
"g()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
"h()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n"
},
"ContractArgCustomError": {
"f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
"g()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: IF 2\n\"];\n2->3[label=\"True\"];\n2->4[label=\"False\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END_IF 4\n\"];\n}\n",
"h()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n"
}
}

@ -14,5 +14,10 @@
"f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
"g()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
"h()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n"
},
"ContractArgCustomError": {
"f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
"g()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: IF 2\n\"];\n2->3[label=\"True\"];\n2->4[label=\"False\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END_IF 4\n\"];\n}\n",
"h()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n"
}
}

@ -14,5 +14,10 @@
"f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
"g()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
"h()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n"
},
"ContractArgCustomError": {
"f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
"g()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: IF 2\n\"];\n2->3[label=\"True\"];\n2->4[label=\"False\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END_IF 4\n\"];\n}\n",
"h()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n"
}
}

@ -52,3 +52,21 @@ contract Fixed2 is Initializable {
selfdestruct(owner);
}
}
contract Fixed3 is Initializable {
address payable owner;
constructor() {
_disableInitializers();
}
function initialize() external initializer {
require(owner == address(0));
owner = payable(msg.sender);
}
function kill() external {
require(msg.sender == owner);
selfdestruct(owner);
}
}

@ -1,5 +1,15 @@
contract Initializable{
uint8 private _initialized;
bool private _initializing;
modifier initializer() {
_;
}
function _disableInitializers() internal virtual {
require(!_initializing, "Initializable: contract is initializing");
if (_initialized < type(uint8).max) {
_initialized = type(uint8).max;
}
}
}

@ -0,0 +1,14 @@
import "./Initializable.sol";
contract Buggy is Initializable{
address payable owner;
function initialize() external initializer{
require(owner == address(0));
owner = payable(msg.sender);
}
function kill() external{
require(msg.sender == owner);
selfdestruct(owner);
}
}

@ -0,0 +1,145 @@
[
[
{
"elements": [
{
"type": "contract",
"name": "Buggy",
"source_mapping": {
"start": 31,
"length": 294,
"filename_relative": "tests/detectors/unprotected-upgrade/0.8.15/Buggy.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/unprotected-upgrade/0.8.15/Buggy.sol",
"is_dependency": false,
"lines": [
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14
],
"starting_column": 1,
"ending_column": 2
}
},
{
"type": "function",
"name": "initialize",
"source_mapping": {
"start": 96,
"length": 124,
"filename_relative": "tests/detectors/unprotected-upgrade/0.8.15/Buggy.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/unprotected-upgrade/0.8.15/Buggy.sol",
"is_dependency": false,
"lines": [
6,
7,
8,
9
],
"starting_column": 5,
"ending_column": 6
},
"type_specific_fields": {
"parent": {
"type": "contract",
"name": "Buggy",
"source_mapping": {
"start": 31,
"length": 294,
"filename_relative": "tests/detectors/unprotected-upgrade/0.8.15/Buggy.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/unprotected-upgrade/0.8.15/Buggy.sol",
"is_dependency": false,
"lines": [
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14
],
"starting_column": 1,
"ending_column": 2
}
},
"signature": "initialize()"
}
},
{
"type": "function",
"name": "kill",
"source_mapping": {
"start": 225,
"length": 98,
"filename_relative": "tests/detectors/unprotected-upgrade/0.8.15/Buggy.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/unprotected-upgrade/0.8.15/Buggy.sol",
"is_dependency": false,
"lines": [
10,
11,
12,
13
],
"starting_column": 5,
"ending_column": 6
},
"type_specific_fields": {
"parent": {
"type": "contract",
"name": "Buggy",
"source_mapping": {
"start": 31,
"length": 294,
"filename_relative": "tests/detectors/unprotected-upgrade/0.8.15/Buggy.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/unprotected-upgrade/0.8.15/Buggy.sol",
"is_dependency": false,
"lines": [
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14
],
"starting_column": 1,
"ending_column": 2
}
},
"signature": "kill()"
}
}
],
"description": "Buggy (tests/detectors/unprotected-upgrade/0.8.15/Buggy.sol#3-14) is an upgradeable contract that does not protect its initialize functions: Buggy.initialize() (tests/detectors/unprotected-upgrade/0.8.15/Buggy.sol#6-9). Anyone can delete the contract with: Buggy.kill() (tests/detectors/unprotected-upgrade/0.8.15/Buggy.sol#10-13)",
"markdown": "[Buggy](tests/detectors/unprotected-upgrade/0.8.15/Buggy.sol#L3-L14) is an upgradeable contract that does not protect its initialize functions: [Buggy.initialize()](tests/detectors/unprotected-upgrade/0.8.15/Buggy.sol#L6-L9). Anyone can delete the contract with: [Buggy.kill()](tests/detectors/unprotected-upgrade/0.8.15/Buggy.sol#L10-L13)",
"first_markdown_element": "tests/detectors/unprotected-upgrade/0.8.15/Buggy.sol#L3-L14",
"id": "d85b90230632a30f7ffb5140a791d4a9ae8b0be045c5b27175f3c477e189c08c",
"check": "unprotected-upgrade",
"impact": "High",
"confidence": "High"
}
]
]

@ -0,0 +1,73 @@
import "./Initializable.sol";
contract Fixed is Initializable{
address payable owner;
constructor() {
owner = payable(msg.sender);
}
function initialize() external initializer{
require(owner == address(0));
owner = payable(msg.sender);
}
function kill() external{
require(msg.sender == owner);
selfdestruct(owner);
}
function other_function() external{
}
}
contract Not_Upgradeable{
}
contract UpgradeableNoDestruct is Initializable{
address payable owner;
constructor() {
owner = payable(msg.sender);
}
function initialize() external initializer{
require(owner == address(0));
owner = payable(msg.sender);
}
}
contract Fixed2 is Initializable {
address payable owner;
constructor() initializer {}
function initialize() external initializer {
require(owner == address(0));
owner = payable(msg.sender);
}
function kill() external {
require(msg.sender == owner);
selfdestruct(owner);
}
}
contract Fixed3 is Initializable {
address payable owner;
constructor() {
_disableInitializers();
}
function initialize() external initializer {
require(owner == address(0));
owner = payable(msg.sender);
}
function kill() external {
require(msg.sender == owner);
selfdestruct(owner);
}
}

@ -0,0 +1,15 @@
contract Initializable {
uint8 private _initialized;
bool private _initializing;
modifier initializer() {
_;
}
function _disableInitializers() internal virtual {
require(!_initializing, "Initializable: contract is initializing");
if (_initialized < type(uint8).max) {
_initialized = type(uint8).max;
}
}
}

@ -0,0 +1,5 @@
contract OnlyProxy {
modifier onlyProxy() {
_;
}
}

@ -0,0 +1,15 @@
import "./Initializable.sol";
import "./OnlyProxy.sol";
contract Whitelisted is Initializable, OnlyProxy{
address payable owner;
function initialize() external initializer onlyProxy {
owner = payable(msg.sender);
}
function kill() external {
require(msg.sender == owner);
selfdestruct(owner);
}
}

@ -323,7 +323,7 @@ ALL_TESTS = [
"custom_error-0.4.0.sol",
ALL_VERSIONS,
),
Test("custom_error-0.8.4.sol", make_version(8, 4, 9)),
Test("custom_error-0.8.4.sol", make_version(8, 4, 15)),
Test(
"top-level-0.4.0.sol",
VERSIONS_04 + VERSIONS_05 + VERSIONS_06 + ["0.7.0"],

@ -929,6 +929,21 @@ ALL_TEST_OBJECTS = [
"whitelisted.sol",
"0.7.6",
),
Test(
all_detectors.UnprotectedUpgradeable,
"Buggy.sol",
"0.8.15",
),
Test(
all_detectors.UnprotectedUpgradeable,
"Fixed.sol",
"0.8.15",
),
Test(
all_detectors.UnprotectedUpgradeable,
"whitelisted.sol",
"0.8.15",
),
Test(
all_detectors.ABIEncoderV2Array,
"storage_ABIEncoderV2_array.sol",

Loading…
Cancel
Save