Skip to content

Commit

Permalink
Merge pull request #305 from crytic/dev-late-subdenomination-conversion
Browse files Browse the repository at this point in the history
Late subdenomination conversion
  • Loading branch information
montyly committed Jul 30, 2019
2 parents aec680c + 13528d2 commit 54241c0
Show file tree
Hide file tree
Showing 11 changed files with 104 additions and 169 deletions.
2 changes: 1 addition & 1 deletion scripts/tests_generate_expected_json_5.sh
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ generate_expected_json(){
sed "s|$CURRENT_PATH|$TRAVIS_PATH|g" "$output_filename_txt" -i
}

generate_expected_json tests/void-cst.sol "void-cst"
#generate_expected_json tests/void-cst.sol "void-cst"
#generate_expected_json tests/solc_version_incorrect_05.ast.json "solc-version"
#generate_expected_json tests/uninitialized-0.5.1.sol "uninitialized-state"
#generate_expected_json tests/backdoor.sol "backdoor"
Expand Down
10 changes: 9 additions & 1 deletion slither/core/expressions/literal.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
from slither.core.expressions.expression import Expression
from slither.utils.arithmetic import convert_subdenomination

class Literal(Expression):

def __init__(self, value, type):
def __init__(self, value, type, subdenomination=None):
super(Literal, self).__init__()
self._value = value
self._type = type
self._subdenomination = subdenomination

@property
def value(self):
Expand All @@ -15,6 +17,12 @@ def value(self):
def type(self):
return self._type

@property
def subdenomination(self):
return self._subdenomination

def __str__(self):
if self.subdenomination:
return str(convert_subdenomination(self._value, self.subdenomination))
# be sure to handle any character
return str(self._value)
1 change: 0 additions & 1 deletion slither/detectors/statements/too_many_digits.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ def _detect_too_many_digits(f):
if isinstance(read, Constant):
# read.value can return an int or a str. Convert it to str
value_as_str = read.original_value
line_of_code = str(node.expression)
if '00000' in value_as_str:
# Info to be printed
ret.append(node)
Expand Down
8 changes: 6 additions & 2 deletions slither/slithir/variables/constant.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
from .variable import SlithIRVariable
from slither.core.solidity_types.elementary_type import ElementaryType, Int, Uint

from slither.utils.arithmetic import convert_subdenomination

class Constant(SlithIRVariable):

def __init__(self, val, type=None):
def __init__(self, val, type=None, subdenomination=None):
super(Constant, self).__init__()
assert isinstance(val, str)

self._original_value = val
self._subdenomination = subdenomination

if subdenomination:
val = str(convert_subdenomination(val, subdenomination))

if type:
assert isinstance(type, ElementaryType)
Expand Down
49 changes: 8 additions & 41 deletions slither/solc_parsing/expressions/expression_parsing.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,45 +220,7 @@ def filter_name(value):
return value

# endregion
###################################################################################
###################################################################################
# region Conversion
###################################################################################
###################################################################################

def convert_subdenomination(value, sub):
if sub is None:
return value
# to allow 0.1 ether conversion
if value[0:2] == "0x":
value = float(int(value, 16))
else:
value = float(value)
if sub == 'wei':
return int(value)
if sub == 'szabo':
return int(value * int(1e12))
if sub == 'finney':
return int(value * int(1e15))
if sub == 'ether':
return int(value * int(1e18))
if sub == 'seconds':
return int(value)
if sub == 'minutes':
return int(value * 60)
if sub == 'hours':
return int(value * 60 * 60)
if sub == 'days':
return int(value * 60 * 60 * 24)
if sub == 'weeks':
return int(value * 60 * 60 * 24 * 7)
if sub == 'years':
return int(value * 60 * 60 * 24 * 7 * 365)

logger.error('Subdemoniation not found {}'.format(sub))
return int(value)

# endregion
###################################################################################
###################################################################################
# region Parsing
Expand Down Expand Up @@ -489,14 +451,19 @@ def parse_expression(expression, caller_context):
assignement = AssignmentOperation(left_expression, right_expression, operation_type, operation_return_type)
return assignement



elif name == 'Literal':

subdenomination = None

assert 'children' not in expression

if is_compact_ast:
value = expression['value']
if value:
if 'subdenomination' in expression and expression['subdenomination']:
value = str(convert_subdenomination(value, expression['subdenomination']))
subdenomination = expression['subdenomination']
elif not value and value != "":
value = '0x'+expression['hexValue']
type = expression['typeDescriptions']['typeString']
Expand All @@ -509,7 +476,7 @@ def parse_expression(expression, caller_context):
value = expression['attributes']['value']
if value:
if 'subdenomination' in expression['attributes'] and expression['attributes']['subdenomination']:
value = str(convert_subdenomination(value, expression['attributes']['subdenomination']))
subdenomination = expression['attributes']['subdenomination']
elif value is None:
# for literal declared as hex
# see https://solidity.readthedocs.io/en/v0.4.25/types.html?highlight=hex#hexadecimal-literals
Expand All @@ -530,7 +497,7 @@ def parse_expression(expression, caller_context):
type = ElementaryType('address')
else:
type = ElementaryType('string')
literal = Literal(value, type)
literal = Literal(value, type, subdenomination)
return literal

elif name == 'Identifier':
Expand Down
10 changes: 5 additions & 5 deletions slither/solc_parsing/slitherSolc.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,11 +224,11 @@ def _analyze_contracts(self):
else:
father_constructors.append(self._contracts_by_id[i])

except KeyError:
txt = 'A contract was not found, it is likely that your codebase contains muliple contracts with the same name'
txt += 'Truffle does not handle this case during compilation'
txt += 'Please read https://github.com/trailofbits/slither/wiki#keyerror-or-nonetype-error'
txt += 'And update your code to remove the duplicate'
except KeyError as e:
txt = f'A contract was not found (id {e}), it is likely that your codebase contains muliple contracts with the same name. '
txt += 'Truffle does not handle this case during compilation. '
txt += 'Please read https://github.com/trailofbits/slither/wiki#keyerror-or-nonetype-error, '
txt += 'and update your code to remove the duplicate'
raise ParsingContractNotFound(txt)
contract.setInheritance(ancestors, fathers, father_constructors)

Expand Down
32 changes: 32 additions & 0 deletions slither/utils/arithmetic.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
from slither.exceptions import SlitherException


def convert_subdenomination(value, sub):

# to allow 0.1 ether conversion
if value[0:2] == "0x":
value = float(int(value, 16))
else:
value = float(value)
if sub == 'wei':
return int(value)
if sub == 'szabo':
return int(value * int(1e12))
if sub == 'finney':
return int(value * int(1e15))
if sub == 'ether':
return int(value * int(1e18))
if sub == 'seconds':
return int(value)
if sub == 'minutes':
return int(value * 60)
if sub == 'hours':
return int(value * 60 * 60)
if sub == 'days':
return int(value * 60 * 60 * 24)
if sub == 'weeks':
return int(value * 60 * 60 * 24 * 7)
if sub == 'years':
return int(value * 60 * 60 * 24 * 7 * 365)

raise SlitherException(f'Subdemonination conversion impossible {value} {sub}')
2 changes: 1 addition & 1 deletion slither/visitors/slithir/expression_to_slithir.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ def _post_index_access(self, expression):
set_val(expression, val)

def _post_literal(self, expression):
cst = Constant(expression.value, expression.type)
cst = Constant(expression.value, expression.type, expression.subdenomination)
set_val(expression, cst)

def _post_member_access(self, expression):
Expand Down
Loading

0 comments on commit 54241c0

Please sign in to comment.