add Naming Convention Detector

pull/34/head
redshark1802 6 years ago
parent 265a7d6a17
commit 495de91217
  1. 10
      scripts/travis_test.sh
  2. 4
      slither/__main__.py
  3. 0
      slither/detectors/naming_convention/__init__.py
  4. 154
      slither/detectors/naming_convention/naming_convention.py
  5. 60
      tests/naming_convention.sol

@ -9,7 +9,7 @@ fi
# contains also the test for the suicidal detector
slither tests/backdoor.sol --disable-solc-warnings
if [ $? -ne 2 ]; then
if [ $? -ne 3 ]; then
exit 1
fi
@ -24,7 +24,7 @@ if [ $? -ne 1 ]; then
fi
slither tests/reentrancy.sol --disable-solc-warnings
if [ $? -ne 1 ]; then
if [ $? -ne 4 ]; then
exit 1
fi
@ -53,6 +53,10 @@ if [ $? -ne 2 ]; then
exit 1
fi
slither tests/naming_convention.sol --disable-solc-warnings
if [ $? -ne 10 ]; then
exit 1
fi
### Test scripts
@ -71,4 +75,4 @@ python examples/scripts/variable_in_condition.py examples/scripts/variable_in_co
if [ $? -ne 0 ]; then
exit 1
fi
exit 0
exit 0

@ -100,6 +100,7 @@ def main():
from slither.detectors.variables.uninitialized_storage_variables import UninitializedStorageVars
from slither.detectors.variables.unused_state_variables import UnusedStateVars
from slither.detectors.statements.tx_origin import TxOrigin
from slither.detectors.naming_convention.naming_convention import NamingConvention
detectors = [Backdoor,
UninitializedStateVarsDetection,
@ -111,7 +112,8 @@ def main():
ArbitrarySend,
Suicidal,
UnusedStateVars,
TxOrigin]
TxOrigin,
NamingConvention]
from slither.printers.summary.summary import PrinterSummary
from slither.printers.summary.quick_summary import PrinterQuickSummary

@ -0,0 +1,154 @@
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
import re
class NamingConvention(AbstractDetector):
"""
Check if naming conventions are followed
https://solidity.readthedocs.io/en/v0.4.25/style-guide.html?highlight=naming_convention%20convention#naming_convention-conventions
"""
ARGUMENT = 'naming-convention'
HELP = 'naming convention violations'
IMPACT = DetectorClassification.INFORMATIONAL
CONFIDENCE = DetectorClassification.INFORMATIONAL
@staticmethod
def is_cap_words(name):
return re.search('^[A-Z]([A-Za-z0-9]+)?_?$', name) is not None
@staticmethod
def is_mixed_case(name):
return re.search('^[a-z]([A-Za-z0-9]+)?_?$', name) is not None
@staticmethod
def is_upper_case_with_underscores(name):
return re.search('^[A-Z0-9_]+_?$', name) is not None
@staticmethod
def should_avoid_name(name):
return re.search('^[lOI]$', name) is not None
def detect(self):
results = []
for contract in self.contracts:
if self.is_cap_words(contract.name) is False:
info = " Contract '{}' is not in CapWords".format(contract.name)
self.log(info)
results.append({'vuln': 'NamingConvention',
'filename': self.filename,
'contract': contract.name,
'sourceMapping': contract.source_mapping})
for struct in contract.structures:
if self.is_cap_words(struct.name) is False:
info = " Struct '{}' is not in CapWords, Contract: '{}' ".format(struct.name, contract.name)
self.log(info)
results.append({'vuln': 'NamingConvention',
'filename': self.filename,
'contract': contract.name,
'struct': struct.name,
'sourceMapping': struct.source_mapping})
for event in contract.events:
if self.is_cap_words(event.name) is False:
info = " Event '{}' is not in CapWords, Contract: '{}' ".format(event.name, contract.name)
self.log(info)
results.append({'vuln': 'NamingConvention',
'filename': self.filename,
'contract': contract.name,
'event': event.name,
'sourceMapping': event.source_mapping})
for func in contract.functions:
if self.is_mixed_case(func.name) is False:
info = " Function '{}' is not in mixedCase, Contract: '{}' ".format(func.name, contract.name)
self.log(info)
results.append({'vuln': 'NamingConvention',
'filename': self.filename,
'contract': contract.name,
'function': func.name,
'sourceMapping': func.source_mapping})
for argument in func.parameters:
if self.is_mixed_case(argument.name) is False:
info = " Parameter '{}' is not in mixedCase, Contract: '{}', Function: '{}'' " \
.format(argument.name, argument.name, contract.name)
self.log(info)
results.append({'vuln': 'NamingConvention',
'filename': self.filename,
'contract': contract.name,
'function': func.name,
'argument': argument.name,
'sourceMapping': argument.source_mapping})
for var in contract.state_variables:
if self.should_avoid_name(var.name):
if self.is_upper_case_with_underscores(var.name) is False:
info = " Variable '{}' l, O, I should not be used, Contract: '{}' " \
.format(var.name, contract.name)
self.log(info)
results.append({'vuln': 'NamingConvention',
'filename': self.filename,
'contract': contract.name,
'constant': var.name,
'sourceMapping': var.source_mapping})
if var.is_constant is True:
if self.is_upper_case_with_underscores(var.name) is False:
info = " Constant '{}' is not in UPPER_CASE_WITH_UNDERSCORES, Contract: '{}' " \
.format(var.name, contract.name)
self.log(info)
results.append({'vuln': 'NamingConvention',
'filename': self.filename,
'contract': contract.name,
'constant': var.name,
'sourceMapping': var.source_mapping})
else:
if self.is_mixed_case(var.name) is False:
info = " Variable '{}' is not in mixedCase, Contract: '{}' ".format(var.name, contract.name)
self.log(info)
results.append({'vuln': 'NamingConvention',
'filename': self.filename,
'contract': contract.name,
'variable': var.name,
'sourceMapping': var.source_mapping})
for enum in contract.enums:
if self.is_cap_words(enum.name) is False:
info = " Enum '{}' is not in CapWords, Contract: '{}' ".format(enum.name, contract.name)
self.log(info)
results.append({'vuln': 'NamingConvention',
'filename': self.filename,
'contract': contract.name,
'enum': enum.name,
'sourceMapping': enum.source_mapping})
for modifier in contract.modifiers:
if self.is_mixed_case(modifier.name) is False:
info = " Modifier '{}' is not in mixedCase, Contract: '{}' ".format(modifier.name, contract.name)
self.log(info)
results.append({'vuln': 'NamingConvention',
'filename': self.filename,
'contract': contract.name,
'modifier': modifier.name,
'sourceMapping': modifier.source_mapping})
return results

@ -0,0 +1,60 @@
pragma solidity ^0.4.24;
contract naming {
enum Numbers {ONE, TWO}
enum numbers {ONE, TWO}
uint constant MY_CONSTANT = 1;
uint constant MY_other_CONSTANT = 2;
uint Var_One = 1;
uint varTwo = 2;
struct test {
}
struct Test {
}
event Event_(uint);
event event_(uint);
function getOne() constant returns (uint)
{
return 1;
}
function GetOne() constant returns (uint)
{
return 1;
}
function setInt(uint number1, uint Number2)
{
}
modifier CantDo() {
_;
}
modifier canDo() {
_;
}
}
contract Test {
}
contract T {
uint k = 1;
uint constant M = 1;
uint l = 1;
}
Loading…
Cancel
Save