mirror of https://github.com/crytic/slither
Detect functions using inline assembly. Refs: https://github.com/trailofbits/slither/issues/26pull/34/head
parent
265a7d6a17
commit
1d6cebd991
@ -0,0 +1,59 @@ |
||||
""" |
||||
Module detecting usage of inline assembly |
||||
""" |
||||
|
||||
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification |
||||
from slither.core.cfg.node import NodeType |
||||
|
||||
|
||||
class Assembly(AbstractDetector): |
||||
""" |
||||
Detect usage of inline assembly |
||||
""" |
||||
|
||||
ARGUMENT = 'assembly' |
||||
HELP = 'assembly usage' |
||||
IMPACT = DetectorClassification.INFORMATIONAL |
||||
CONFIDENCE = DetectorClassification.HIGH |
||||
|
||||
@staticmethod |
||||
def _contains_inline_assembly_use(node): |
||||
""" |
||||
Check if the node contains ASSEMBLY type |
||||
Returns: |
||||
(bool) |
||||
""" |
||||
return node.type == NodeType.ASSEMBLY |
||||
|
||||
def detect_assembly(self, contract): |
||||
ret = [] |
||||
for f in contract.functions: |
||||
nodes = f.nodes |
||||
assembly_nodes = [n for n in nodes if |
||||
self._contains_inline_assembly_use(n)] |
||||
if assembly_nodes: |
||||
ret.append((f, assembly_nodes)) |
||||
return ret |
||||
|
||||
def detect(self): |
||||
""" Detect the functions that use inline assembly |
||||
""" |
||||
results = [] |
||||
for c in self.contracts: |
||||
values = self.detect_assembly(c) |
||||
for func, nodes in values: |
||||
func_name = func.name |
||||
info = "Assembly in %s, Contract: %s, Function: %s" % (self.filename, |
||||
c.name, |
||||
func_name) |
||||
self.log(info) |
||||
|
||||
sourceMapping = [n.source_mapping for n in nodes] |
||||
|
||||
results.append({'vuln': 'Assembly', |
||||
'sourceMapping': sourceMapping, |
||||
'filename': self.filename, |
||||
'contract': c.name, |
||||
'function_name': func_name}) |
||||
|
||||
return results |
@ -0,0 +1,22 @@ |
||||
pragma solidity ^0.4.0; |
||||
|
||||
// taken from https://solidity.readthedocs.io/en/v0.4.25/assembly.html |
||||
|
||||
library GetCode { |
||||
function at(address _addr) public view returns (bytes o_code) { |
||||
assembly { |
||||
// retrieve the size of the code, this needs assembly |
||||
let size := extcodesize(_addr) |
||||
// allocate output byte array - this could also be done without assembly |
||||
// by using o_code = new bytes(size) |
||||
o_code := mload(0x40) |
||||
// new "memory end" including padding |
||||
mstore(0x40, add(o_code, and(add(add(size, 0x20), 0x1f), not(0x1f)))) |
||||
// store length in memory |
||||
mstore(o_code, size) |
||||
// actually retrieve the code, this needs assembly |
||||
extcodecopy(_addr, add(o_code, 0x20), 0, size) |
||||
} |
||||
} |
||||
} |
||||
|
@ -0,0 +1,49 @@ |
||||
pragma solidity ^0.4.16; |
||||
|
||||
// taken from https://solidity.readthedocs.io/en/v0.4.25/assembly.html |
||||
|
||||
library VectorSum { |
||||
// This function is less efficient because the optimizer currently fails to |
||||
// remove the bounds checks in array access. |
||||
function sumSolidity(uint[] _data) public view returns (uint o_sum) { |
||||
for (uint i = 0; i < _data.length; ++i) |
||||
o_sum += _data[i]; |
||||
} |
||||
|
||||
// We know that we only access the array in bounds, so we can avoid the check. |
||||
// 0x20 needs to be added to an array because the first slot contains the |
||||
// array length. |
||||
function sumAsm(uint[] _data) public view returns (uint o_sum) { |
||||
for (uint i = 0; i < _data.length; ++i) { |
||||
assembly { |
||||
o_sum := add(o_sum, mload(add(add(_data, 0x20), mul(i, 0x20)))) |
||||
} |
||||
} |
||||
} |
||||
|
||||
// Same as above, but accomplish the entire code within inline assembly. |
||||
function sumPureAsm(uint[] _data) public view returns (uint o_sum) { |
||||
assembly { |
||||
// Load the length (first 32 bytes) |
||||
let len := mload(_data) |
||||
|
||||
// Skip over the length field. |
||||
// |
||||
// Keep temporary variable so it can be incremented in place. |
||||
// |
||||
// NOTE: incrementing _data would result in an unusable |
||||
// _data variable after this assembly block |
||||
let data := add(_data, 0x20) |
||||
|
||||
// Iterate until the bound is not met. |
||||
for |
||||
{ let end := add(data, len) } |
||||
lt(data, end) |
||||
{ data := add(data, 0x20) } |
||||
{ |
||||
o_sum := add(o_sum, mload(data)) |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
Loading…
Reference in new issue