slither-format: simplify loop iteration on contracts

pull/238/head
Josselin 6 years ago
parent aecd47c7d3
commit 7f8289aad0
  1. 582
      utils/slither_format/formatters/naming_convention.py

@ -23,7 +23,8 @@ def format(slither, patches, elements):
for element in elements: for element in elements:
target = element['additional_fields']['target'] target = element['additional_fields']['target']
if (target == "parameter"): if (target == "parameter"):
_patch(slither, patches, _patch(slither,
patches,
element['additional_fields']['target'], element['additional_fields']['target'],
element['name'], element['name'],
element['type_specific_fields']['parent']['name'], element['type_specific_fields']['parent']['name'],
@ -36,16 +37,23 @@ def format(slither, patches, elements):
elif target in ["modifier", "function", "event", elif target in ["modifier", "function", "event",
"variable", "variable_constant", "enum" "variable", "variable_constant", "enum"
"structure"]: "structure"]:
_patch(slither, patches, target, _patch(slither,
element['name'], element['name'], patches,
target,
element['name'],
element['name'],
element['type_specific_fields']['parent']['name'], element['type_specific_fields']['parent']['name'],
element['source_mapping']['filename_absolute'], element['source_mapping']['filename_absolute'],
element['source_mapping']['filename_relative'], element['source_mapping']['filename_relative'],
element['source_mapping']['start'], element['source_mapping']['start'],
(element['source_mapping']['start'] + element['source_mapping']['length'])) (element['source_mapping']['start'] + element['source_mapping']['length']))
else: else:
_patch(slither, patches, element['additional_fields']['target'], _patch(slither,
element['name'], element['name'], element['name'], patches,
element['additional_fields']['target'],
element['name'],
element['name'],
element['name'],
element['source_mapping']['filename_absolute'], element['source_mapping']['filename_absolute'],
element['source_mapping']['filename_relative'], element['source_mapping']['filename_relative'],
element['source_mapping']['start'], element['source_mapping']['start'],
@ -457,75 +465,74 @@ def _create_patch_parameter_uses(format_info):
contract_name = format_info.contract_name contract_name = format_info.contract_name
function_name = format_info.function_name function_name = format_info.function_name
for contract in slither.contracts: target_contract = slither.get_contract_from_name(contract_name)
if (contract.name == contract_name): for function in target_contract.functions:
for function in contract.functions: if (function.name == function_name):
if (function.name == function_name): in_file_str = slither.source_code[in_file].encode('utf-8')
in_file_str = slither.source_code[in_file].encode('utf-8') for node in function.nodes:
for node in function.nodes: vars = node._expression_vars_written + node._expression_vars_read
vars = node._expression_vars_written + node._expression_vars_read for v in vars:
for v in vars: if isinstance(v, Identifier) and str(v) == name and [str(lv) for lv in
if isinstance(v, Identifier) and str(v) == name and [str(lv) for lv in (node._local_vars_read +
(node._local_vars_read + node._local_vars_written)
node._local_vars_written) if str(lv) == name]:
if str(lv) == name]: modify_loc_start = int(v.source_mapping['start'])
modify_loc_start = int(v.source_mapping['start']) modify_loc_end = int(v.source_mapping['start']) + int(v.source_mapping['length'])
modify_loc_end = int(v.source_mapping['start']) + int(v.source_mapping['length']) old_str_of_interest = in_file_str[modify_loc_start:modify_loc_end]
old_str_of_interest = in_file_str[modify_loc_start:modify_loc_end] if(name[0] == '_'):
if(name[0] == '_'): (new_str_of_interest, num_repl) = re.subn(r'(.*)'+name+r'(.*)',
(new_str_of_interest, num_repl) = re.subn(r'(.*)'+name+r'(.*)', r'\1'+name[0]+name[1].upper()+name[2:] +
r'\1'+name[0]+name[1].upper()+name[2:] + r'\2', old_str_of_interest.decode('utf-8'),
r'\2', old_str_of_interest.decode('utf-8'), 1)
1) else:
else: (new_str_of_interest, num_repl) = re.subn(r'(.*)'+name+r'(.*)', r'\1'+'_' +
(new_str_of_interest, num_repl) = re.subn(r'(.*)'+name+r'(.*)', r'\1'+'_' + name[0].upper()+name[1:]+r'\2',
name[0].upper()+name[1:]+r'\2', old_str_of_interest.decode('utf-8'), 1)
old_str_of_interest.decode('utf-8'), 1) if num_repl != 0:
if num_repl != 0: patch = {
patch = { "file" : in_file,
"file" : in_file, "detector" : "naming-convention (parameter uses)",
"detector" : "naming-convention (parameter uses)", "start" : modify_loc_start,
"start" : modify_loc_start, "end" : modify_loc_end,
"end" : modify_loc_end, "old_string" : old_str_of_interest.decode('utf-8'),
"old_string" : old_str_of_interest.decode('utf-8'), "new_string" : new_str_of_interest
"new_string" : new_str_of_interest }
} if not patch in patches[in_file_relative]:
if not patch in patches[in_file_relative]: patches[in_file_relative].append(patch)
patches[in_file_relative].append(patch) else:
else: raise SlitherException("Could not find parameter use?!")
raise SlitherException("Could not find parameter use?!")
# Process function parameters passed to modifiers
# Process function parameters passed to modifiers for modifier in function._expression_modifiers:
for modifier in function._expression_modifiers: for arg in modifier.arguments:
for arg in modifier.arguments: if str(arg) == name:
if str(arg) == name: old_str_of_interest = in_file_str[modifier.source_mapping['start']:
old_str_of_interest = in_file_str[modifier.source_mapping['start']: modifier.source_mapping['start'] +
modifier.source_mapping['start'] + modifier.source_mapping['length']]
modifier.source_mapping['length']] old_str_of_interest_beyond_modifier_name = old_str_of_interest.decode('utf-8')\
old_str_of_interest_beyond_modifier_name = old_str_of_interest.decode('utf-8')\ .split('(')[1]
.split('(')[1] if(name[0] == '_'):
if(name[0] == '_'): (new_str_of_interest, num_repl) = re.subn(r'(.*)'+name+r'(.*)', r'\1'+name[0]+
(new_str_of_interest, num_repl) = re.subn(r'(.*)'+name+r'(.*)', r'\1'+name[0]+ name[1].upper()+name[2:]+r'\2',
name[1].upper()+name[2:]+r'\2', old_str_of_interest_beyond_modifier_name, 1)
old_str_of_interest_beyond_modifier_name, 1) else:
else: (new_str_of_interest, num_repl) = re.subn(r'(.*)'+name+r'(.*)', r'\1'+'_'+
(new_str_of_interest, num_repl) = re.subn(r'(.*)'+name+r'(.*)', r'\1'+'_'+ name[0].upper()+name[1:]+r'\2',
name[0].upper()+name[1:]+r'\2', old_str_of_interest_beyond_modifier_name, 1)
old_str_of_interest_beyond_modifier_name, 1) if num_repl != 0:
if num_repl != 0: patch = {
patch = { "file" : in_file,
"file" : in_file, "detector" : "naming-convention (parameter uses)",
"detector" : "naming-convention (parameter uses)", "start" : modifier.source_mapping['start'] +
"start" : modifier.source_mapping['start'] + len(old_str_of_interest.decode('utf-8').split('(')[0]) + 1,
len(old_str_of_interest.decode('utf-8').split('(')[0]) + 1, "end" : modifier.source_mapping['start'] + modifier.source_mapping['length'],
"end" : modifier.source_mapping['start'] + modifier.source_mapping['length'], "old_string" : old_str_of_interest_beyond_modifier_name,
"old_string" : old_str_of_interest_beyond_modifier_name, "new_string" : new_str_of_interest
"new_string" : new_str_of_interest }
} if not patch in patches[in_file_relative]:
if not patch in patches[in_file_relative]: patches[in_file_relative].append(patch)
patches[in_file_relative].append(patch) else:
else: raise SlitherException("Could not find parameter use in modifier?!")
raise SlitherException("Could not find parameter use in modifier?!")
def _create_patch_state_variable_declaration(format_info): def _create_patch_state_variable_declaration(format_info):
@ -535,28 +542,33 @@ def _create_patch_state_variable_declaration(format_info):
modify_loc_start, modify_loc_end = format_info.loc_start, format_info.loc_end modify_loc_start, modify_loc_end = format_info.loc_start, format_info.loc_end
_target = format_info.target _target = format_info.target
for contract in slither.contracts: target_contract = slither.get_contract_from_name(contract_name)
if (contract.name == contract_name): if not target_contract:
for var in contract.state_variables: raise SlitherException(f"Contract not found {contract_name}")
if (var.name == name): target_var = target_contract.get_state_variable_from_name(name)
in_file_str = slither.source_code[in_file].encode('utf-8') if not target_var:
old_str_of_interest = in_file_str[modify_loc_start:modify_loc_end] raise SlitherException(f"Contract not found {name}")
m = re.search(name, old_str_of_interest.decode('utf-8'))
if (_target == "variable_constant"): # TODO (JF) target_var is not used, the above checks could be removed?
new_string = old_str_of_interest.decode('utf-8')[m.span()[0]:m.span()[1]].upper()
else: in_file_str = slither.source_code[in_file].encode('utf-8')
new_string = old_str_of_interest.decode('utf-8')[m.span()[0]:m.span()[1]] old_str_of_interest = in_file_str[modify_loc_start:modify_loc_end]
new_string = new_string[0].lower()+new_string[1:] m = re.search(name, old_str_of_interest.decode('utf-8'))
patch = { if (_target == "variable_constant"):
"file" : in_file, new_string = old_str_of_interest.decode('utf-8')[m.span()[0]:m.span()[1]].upper()
"detector" : "naming-convention (state variable declaration)", else:
"start" : modify_loc_start+m.span()[0], new_string = old_str_of_interest.decode('utf-8')[m.span()[0]:m.span()[1]]
"end" : modify_loc_start+m.span()[1], new_string = new_string[0].lower()+new_string[1:]
"old_string" : old_str_of_interest.decode('utf-8')[m.span()[0]:m.span()[1]], patch = {
"new_string" : new_string "file" : in_file,
} "detector" : "naming-convention (state variable declaration)",
if not patch in patches[in_file_relative]: "start" : modify_loc_start+m.span()[0],
patches[in_file_relative].append(patch) "end" : modify_loc_start+m.span()[1],
"old_string" : old_str_of_interest.decode('utf-8')[m.span()[0]:m.span()[1]],
"new_string" : new_string
}
if not patch in patches[in_file_relative]:
patches[in_file_relative].append(patch)
def _create_patch_state_variable_uses(format_info): def _create_patch_state_variable_uses(format_info):
@ -566,60 +578,32 @@ def _create_patch_state_variable_uses(format_info):
_target = format_info.target _target = format_info.target
# To-do: Check cross-contract state variable uses # To-do: Check cross-contract state variable uses
for contract in slither.contracts: target_contract = slither.get_contract_from_name(contract_name)
if (contract.name == contract_name): if not target_contract:
target_contract = contract raise SlitherException(f"Contract not found {contract_name}")
for contract in slither.contracts:
if (contract == target_contract or (contract in target_contract.derived_contracts)):
fms = contract.functions + contract.modifiers
for fm in fms:
for node in fm.nodes:
vars = node._expression_vars_written + node._expression_vars_read
for v in vars:
if isinstance(v, Identifier) and str(v) == name and [str(sv) for sv in
(node._state_vars_read +
node._state_vars_written)
if str(sv) == name]:
modify_loc_start = int(v.source_mapping['start'])
modify_loc_end = int(v.source_mapping['start']) + int(v.source_mapping['length'])
in_file_str = slither.source_code[in_file].encode('utf-8')
old_str_of_interest = in_file_str[modify_loc_start:modify_loc_end]
if (_target == "variable_constant"):
new_str_of_interest = old_str_of_interest.decode('utf-8').upper()
else:
new_str_of_interest = old_str_of_interest.decode('utf-8')
new_str_of_interest = new_str_of_interest[0].lower()+new_str_of_interest[1:]
patch = {
"file" : in_file,
"detector" : "naming-convention (state variable uses)",
"start" : modify_loc_start,
"end" : modify_loc_end,
"old_string" : old_str_of_interest.decode('utf-8'),
"new_string" : new_str_of_interest
}
if not patch in patches[in_file_relative]:
patches[in_file_relative].append(patch)
def _create_patch_enum_definition(format_info):
slither, patches, name = format_info.slither, format_info.patches, format_info.name
in_file, in_file_relative = format_info.in_file, format_info.in_file_relative
contract_name = format_info.contract_name
modify_loc_start, modify_loc_end = format_info.loc_start, format_info.loc_end
for contract in slither.contracts: for contract in [target_contract] + target_contract.derived_contracts:
if (contract.name == contract_name): fms = contract.functions + contract.modifiers
for enum in contract.enums: for fm in fms:
if (enum.name == name): for node in fm.nodes:
in_file_str = slither.source_code[in_file].encode('utf-8') vars = node._expression_vars_written + node._expression_vars_read
old_str_of_interest = in_file_str[modify_loc_start:modify_loc_end] for v in vars:
(new_str_of_interest, num_repl) = re.subn(r'(.*)'+"enum"+r'(.*)'+name, r'\1'+"enum"+r'\2'+ if isinstance(v, Identifier) and str(v) == name and [str(sv) for sv in
name[0].capitalize()+name[1:], (node._state_vars_read +
old_str_of_interest.decode('utf-8'), 1) node._state_vars_written)
if num_repl != 0: if str(sv) == name]:
modify_loc_start = int(v.source_mapping['start'])
modify_loc_end = int(v.source_mapping['start']) + int(v.source_mapping['length'])
in_file_str = slither.source_code[in_file].encode('utf-8')
old_str_of_interest = in_file_str[modify_loc_start:modify_loc_end]
if (_target == "variable_constant"):
new_str_of_interest = old_str_of_interest.decode('utf-8').upper()
else:
new_str_of_interest = old_str_of_interest.decode('utf-8')
new_str_of_interest = new_str_of_interest[0].lower()+new_str_of_interest[1:]
patch = { patch = {
"file" : in_file, "file" : in_file,
"detector" : "naming-convention (enum definition)", "detector" : "naming-convention (state variable uses)",
"start" : modify_loc_start, "start" : modify_loc_start,
"end" : modify_loc_end, "end" : modify_loc_end,
"old_string" : old_str_of_interest.decode('utf-8'), "old_string" : old_str_of_interest.decode('utf-8'),
@ -627,8 +611,42 @@ def _create_patch_enum_definition(format_info):
} }
if not patch in patches[in_file_relative]: if not patch in patches[in_file_relative]:
patches[in_file_relative].append(patch) patches[in_file_relative].append(patch)
else:
raise SlitherException("Could not find enum?!")
def _create_patch_enum_definition(format_info):
slither, patches, name = format_info.slither, format_info.patches, format_info.name
in_file, in_file_relative = format_info.in_file, format_info.in_file_relative
contract_name = format_info.contract_name
modify_loc_start, modify_loc_end = format_info.loc_start, format_info.loc_end
target_contract = slither.get_contract_from_name(contract_name)
if not target_contract:
raise SlitherException(f"Contract not found {contract_name}")
target_enum = slither.get_enum_from_name(name)
if not target_enum:
raise SlitherException(f"Enum not found {name}")
# TODO (JF) target_enum is not used, the above checks could be removed?
in_file_str = slither.source_code[in_file].encode('utf-8')
old_str_of_interest = in_file_str[modify_loc_start:modify_loc_end]
(new_str_of_interest, num_repl) = re.subn(r'(.*)'+"enum"+r'(.*)'+name, r'\1'+"enum"+r'\2'+
name[0].capitalize()+name[1:],
old_str_of_interest.decode('utf-8'), 1)
if num_repl != 0:
patch = {
"file" : in_file,
"detector" : "naming-convention (enum definition)",
"start" : modify_loc_start,
"end" : modify_loc_end,
"old_string" : old_str_of_interest.decode('utf-8'),
"new_string" : new_str_of_interest
}
if not patch in patches[in_file_relative]:
patches[in_file_relative].append(patch)
else:
raise SlitherException("Could not find enum?!")
def _create_patch_enum_uses(format_info): def _create_patch_enum_uses(format_info):
@ -636,87 +654,87 @@ def _create_patch_enum_uses(format_info):
in_file, in_file_relative = format_info.in_file, format_info.in_file_relative in_file, in_file_relative = format_info.in_file, format_info.in_file_relative
contract_name = format_info.contract_name contract_name = format_info.contract_name
for contract in slither.contracts: target_contract = slither.get_contract_from_name(contract_name)
if (contract.name == contract_name): if not target_contract:
target_contract = contract raise SlitherException(f"Contract not found {contract_name}")
for contract in slither.contracts:
if (contract == target_contract or (contract in target_contract.derived_contracts)): for contract in [target_contract] + target_contract.derived_contracts:
in_file_str = slither.source_code[in_file].encode('utf-8') in_file_str = slither.source_code[in_file].encode('utf-8')
# Check state variable declarations of enum type # Check state variable declarations of enum type
# To-do: Deep-check aggregate types (struct and mapping) # To-do: Deep-check aggregate types (struct and mapping)
svs = contract.variables svs = contract.variables
for sv in svs: for sv in svs:
if (str(sv.type) == contract_name + "." + name): if (str(sv.type) == contract_name + "." + name):
old_str_of_interest = in_file_str[sv.source_mapping['start']:(sv.source_mapping['start']+ old_str_of_interest = in_file_str[sv.source_mapping['start']:(sv.source_mapping['start']+
sv.source_mapping['length'])] sv.source_mapping['length'])]
(new_str_of_interest, num_repl) = re.subn(name, name.capitalize(),
old_str_of_interest.decode('utf-8'), 1)
patch = {
"file" : in_file,
"detector" : "naming-convention (enum use)",
"start" : sv.source_mapping['start'],
"end" : sv.source_mapping['start'] + sv.source_mapping['length'],
"old_string" : old_str_of_interest.decode('utf-8'),
"new_string" : new_str_of_interest
}
if not patch in patches[in_file_relative]:
patches[in_file_relative].append(patch)
# Check function+modifier locals+parameters+returns
# To-do: Deep-check aggregate types (struct and mapping)
fms = contract.functions + contract.modifiers
for fm in fms:
# Enum declarations
for v in fm.variables:
if (str(v.type) == contract_name + "." + name):
old_str_of_interest = in_file_str[v.source_mapping['start']:(v.source_mapping['start']+
v.source_mapping['length'])]
(new_str_of_interest, num_repl) = re.subn(name, name.capitalize(), (new_str_of_interest, num_repl) = re.subn(name, name.capitalize(),
old_str_of_interest.decode('utf-8'), 1) old_str_of_interest.decode('utf-8'), 1)
patch = { patch = {
"file" : in_file, "file" : in_file,
"detector" : "naming-convention (enum use)", "detector" : "naming-convention (enum use)",
"start" : sv.source_mapping['start'], "start" : v.source_mapping['start'],
"end" : sv.source_mapping['start'] + sv.source_mapping['length'], "end" : v.source_mapping['start'] + v.source_mapping['length'],
"old_string" : old_str_of_interest.decode('utf-8'), "old_string" : old_str_of_interest.decode('utf-8'),
"new_string" : new_str_of_interest "new_string" : new_str_of_interest
} }
if not patch in patches[in_file_relative]: if not patch in patches[in_file_relative]:
patches[in_file_relative].append(patch) patches[in_file_relative].append(patch)
# Check function+modifier locals+parameters+returns # Capture enum uses such as "num = numbers.ONE;"
# To-do: Deep-check aggregate types (struct and mapping) for function in contract.functions:
fms = contract.functions + contract.modifiers for node in function.nodes:
for fm in fms: for ir in node.irs:
# Enum declarations if isinstance(ir, Member):
for v in fm.variables: if str(ir.variable_left) == name:
if (str(v.type) == contract_name + "." + name): old_str_of_interest = in_file_str[node.source_mapping['start']:
old_str_of_interest = in_file_str[v.source_mapping['start']:(v.source_mapping['start']+ (node.source_mapping['start']+
v.source_mapping['length'])] node.source_mapping['length'])].decode('utf-8')\
(new_str_of_interest, num_repl) = re.subn(name, name.capitalize(), .split('=')[1]
old_str_of_interest.decode('utf-8'), 1) m = re.search(r'(.*)'+name, old_str_of_interest)
patch = { old_str_of_interest = old_str_of_interest[m.span()[0]:]
"file" : in_file, (new_str_of_interest, num_repl) = re.subn(r'(.*)'+name, r'\1'+name[0].upper()+name[1:],
"detector" : "naming-convention (enum use)", old_str_of_interest, 1)
"start" : v.source_mapping['start'], if num_repl != 0:
"end" : v.source_mapping['start'] + v.source_mapping['length'], patch = {
"old_string" : old_str_of_interest.decode('utf-8'), "file" : in_file,
"new_string" : new_str_of_interest "detector" : "naming-convention (enum use)",
} "start" : node.source_mapping['start'] +
if not patch in patches[in_file_relative]: len(in_file_str[node.source_mapping['start']:
patches[in_file_relative].append(patch) (node.source_mapping['start']+
# Capture enum uses such as "num = numbers.ONE;" node.source_mapping['length'])].decode('utf-8').split('=')[0]) +
for function in contract.functions: 1 + m.span()[0],
for node in function.nodes: "end" : node.source_mapping['start'] +
for ir in node.irs: len(in_file_str[node.source_mapping['start']:(node.source_mapping['start']+
if isinstance(ir, Member): node.source_mapping['length'])].\
if str(ir.variable_left) == name: decode('utf-8').split('=')[0]) + 1 + m.span()[0] + len(old_str_of_interest),
old_str_of_interest = in_file_str[node.source_mapping['start']: "old_string" : old_str_of_interest,
(node.source_mapping['start']+ "new_string" : new_str_of_interest
node.source_mapping['length'])].decode('utf-8')\ }
.split('=')[1] if not patch in patches[in_file_relative]:
m = re.search(r'(.*)'+name, old_str_of_interest) patches[in_file_relative].append(patch)
old_str_of_interest = old_str_of_interest[m.span()[0]:] else:
(new_str_of_interest, num_repl) = re.subn(r'(.*)'+name, r'\1'+name[0].upper()+name[1:], raise SlitherException("Could not find new object?!")
old_str_of_interest, 1) # To-do: Check any other place/way where enum type is used
if num_repl != 0:
patch = {
"file" : in_file,
"detector" : "naming-convention (enum use)",
"start" : node.source_mapping['start'] +
len(in_file_str[node.source_mapping['start']:
(node.source_mapping['start']+
node.source_mapping['length'])].decode('utf-8').split('=')[0]) +
1 + m.span()[0],
"end" : node.source_mapping['start'] +
len(in_file_str[node.source_mapping['start']:(node.source_mapping['start']+
node.source_mapping['length'])].\
decode('utf-8').split('=')[0]) + 1 + m.span()[0] + len(old_str_of_interest),
"old_string" : old_str_of_interest,
"new_string" : new_str_of_interest
}
if not patch in patches[in_file_relative]:
patches[in_file_relative].append(patch)
else:
raise SlitherException("Could not find new object?!")
# To-do: Check any other place/way where enum type is used
def _create_patch_struct_definition(format_info): def _create_patch_struct_definition(format_info):
@ -725,28 +743,34 @@ def _create_patch_struct_definition(format_info):
contract_name = format_info.contract_name contract_name = format_info.contract_name
modify_loc_start, modify_loc_end = format_info.loc_start, format_info.loc_end modify_loc_start, modify_loc_end = format_info.loc_start, format_info.loc_end
for contract in slither.contracts: target_contract = slither.get_contract_from_name(contract_name)
if (contract.name == contract_name): if not target_contract:
for struct in contract.structures: raise SlitherException(f"Contract not found {contract_name}")
if (struct.name == name):
in_file_str = slither.source_code[in_file].encode('utf-8') target_structure = slither.get_structure_from_name(name)
old_str_of_interest = in_file_str[modify_loc_start:modify_loc_end] if not target_structure:
(new_str_of_interest, num_repl) = re.subn(r'(.*)'+"struct"+r'(.*)'+name, r'\1'+"struct"+r'\2'+ raise SlitherException(f"Structure not found {name}")
name[0].capitalize()+name[1:],
old_str_of_interest.decode('utf-8'), 1) # TODO (JF) target_structure is not used, the above checks could be removed?
if num_repl != 0:
patch = { in_file_str = slither.source_code[in_file].encode('utf-8')
"file" : in_file, old_str_of_interest = in_file_str[modify_loc_start:modify_loc_end]
"detector" : "naming-convention (struct definition)", (new_str_of_interest, num_repl) = re.subn(r'(.*)'+"struct"+r'(.*)'+name, r'\1'+"struct"+r'\2'+
"start" : modify_loc_start, name[0].capitalize()+name[1:],
"end" : modify_loc_end, old_str_of_interest.decode('utf-8'), 1)
"old_string" : old_str_of_interest.decode('utf-8'), if num_repl != 0:
"new_string" : new_str_of_interest patch = {
} "file" : in_file,
if not patch in patches[in_file_relative]: "detector" : "naming-convention (struct definition)",
patches[in_file_relative].append(patch) "start" : modify_loc_start,
else: "end" : modify_loc_end,
raise SlitherException("Could not find struct?!") "old_string" : old_str_of_interest.decode('utf-8'),
"new_string" : new_str_of_interest
}
if not patch in patches[in_file_relative]:
patches[in_file_relative].append(patch)
else:
raise SlitherException("Could not find struct?!")
def _create_patch_struct_uses(format_info): def _create_patch_struct_uses(format_info):
@ -754,49 +778,49 @@ def _create_patch_struct_uses(format_info):
in_file, in_file_relative = format_info.in_file, format_info.in_file_relative in_file, in_file_relative = format_info.in_file, format_info.in_file_relative
contract_name = format_info.contract_name contract_name = format_info.contract_name
for contract in slither.contracts: target_contract = slither.get_contract_from_name(contract_name)
if (contract.name == contract_name): if not target_contract:
target_contract = contract raise SlitherException(f"Contract not found {contract_name}")
for contract in slither.contracts:
if (contract == target_contract or (contract in target_contract.derived_contracts)): for contract in [target_contract] + target_contract.derived_contracts:
in_file_str = slither.source_code[in_file].encode('utf-8') in_file_str = slither.source_code[in_file].encode('utf-8')
# Check state variables of struct type # Check state variables of struct type
# To-do: Deep-check aggregate types (struct and mapping) # To-do: Deep-check aggregate types (struct and mapping)
svs = contract.variables svs = contract.variables
for sv in svs: for sv in svs:
if (str(sv.type) == contract_name + "." + name): if (str(sv.type) == contract_name + "." + name):
old_str_of_interest = in_file_str[sv.source_mapping['start']:(sv.source_mapping['start']+ old_str_of_interest = in_file_str[sv.source_mapping['start']:(sv.source_mapping['start']+
sv.source_mapping['length'])] sv.source_mapping['length'])]
(new_str_of_interest, num_repl) = re.subn(name, name.capitalize(),
old_str_of_interest.decode('utf-8'), 1)
patch = {
"file" : in_file,
"detector" : "naming-convention (struct use)",
"start" : sv.source_mapping['start'],
"end" : sv.source_mapping['start'] + sv.source_mapping['length'],
"old_string" : old_str_of_interest.decode('utf-8'),
"new_string" : new_str_of_interest
}
if not patch in patches[in_file_relative]:
patches[in_file_relative].append(patch)
# Check function+modifier locals+parameters+returns
# To-do: Deep-check aggregate types (struct and mapping)
fms = contract.functions + contract.modifiers
for fm in fms:
for v in fm.variables:
if (str(v.type) == contract_name + "." + name):
old_str_of_interest = in_file_str[v.source_mapping['start']:(v.source_mapping['start']+
v.source_mapping['length'])]
(new_str_of_interest, num_repl) = re.subn(name, name.capitalize(), (new_str_of_interest, num_repl) = re.subn(name, name.capitalize(),
old_str_of_interest.decode('utf-8'), 1) old_str_of_interest.decode('utf-8'), 1)
patch = { patch = {
"file" : in_file, "file" : in_file,
"detector" : "naming-convention (struct use)", "detector" : "naming-convention (struct use)",
"start" : sv.source_mapping['start'], "start" : v.source_mapping['start'],
"end" : sv.source_mapping['start'] + sv.source_mapping['length'], "end" : v.source_mapping['start'] + v.source_mapping['length'],
"old_string" : old_str_of_interest.decode('utf-8'), "old_string" : old_str_of_interest.decode('utf-8'),
"new_string" : new_str_of_interest "new_string" : new_str_of_interest
} }
if not patch in patches[in_file_relative]: if not patch in patches[in_file_relative]:
patches[in_file_relative].append(patch) patches[in_file_relative].append(patch)
# Check function+modifier locals+parameters+returns # To-do: Check any other place/way where struct type is used (e.g. typecast)
# To-do: Deep-check aggregate types (struct and mapping)
fms = contract.functions + contract.modifiers
for fm in fms:
for v in fm.variables:
if (str(v.type) == contract_name + "." + name):
old_str_of_interest = in_file_str[v.source_mapping['start']:(v.source_mapping['start']+
v.source_mapping['length'])]
(new_str_of_interest, num_repl) = re.subn(name, name.capitalize(),
old_str_of_interest.decode('utf-8'), 1)
patch = {
"file" : in_file,
"detector" : "naming-convention (struct use)",
"start" : v.source_mapping['start'],
"end" : v.source_mapping['start'] + v.source_mapping['length'],
"old_string" : old_str_of_interest.decode('utf-8'),
"new_string" : new_str_of_interest
}
if not patch in patches[in_file_relative]:
patches[in_file_relative].append(patch)
# To-do: Check any other place/way where struct type is used (e.g. typecast)

Loading…
Cancel
Save