Commit b6b07a0c authored by aniket-engg's avatar aniket-engg Committed by Aniket

commons updated according to latest AST

parent dd3edce0
import { default as category } from './categories' import { default as category } from './categories'
import { isSubScopeWithTopLevelUnAssignedBinOp, getUnAssignedTopLevelBinOps } from './staticAnalysisCommon' import { isSubScopeWithTopLevelUnAssignedBinOp, getUnAssignedTopLevelBinOps } from './staticAnalysisCommon'
import { default as algorithm } from './algorithmCategories' import { default as algorithm } from './algorithmCategories'
import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, AstNodeLegacy, CompilationResult} from './../../types' import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, BlockAstNode, IfStatementAstNode, WhileStatementAstNode, ForStatementAstNode, CompilationResult, ExpressionStatementAstNode} from './../../types'
export default class assignAndCompare implements AnalyzerModule { export default class assignAndCompare implements AnalyzerModule {
warningNodes: AstNodeLegacy[] = [] warningNodes: ExpressionStatementAstNode[] = []
name: string = 'Result not used: ' name: string = 'Result not used: '
description: string = 'The result of an operation was not used.' description: string = 'The result of an operation was not used.'
category: ModuleCategory = category.MISC category: ModuleCategory = category.MISC
algorithm: ModuleAlgorithm = algorithm.EXACT algorithm: ModuleAlgorithm = algorithm.EXACT
visit (node: AstNodeLegacy): void { visit (node: BlockAstNode | IfStatementAstNode | WhileStatementAstNode | ForStatementAstNode): void {
if (isSubScopeWithTopLevelUnAssignedBinOp(node)) getUnAssignedTopLevelBinOps(node).forEach((n) => this.warningNodes.push(n)) if (isSubScopeWithTopLevelUnAssignedBinOp(node)) getUnAssignedTopLevelBinOps(node).forEach((n) => this.warningNodes.push(n))
} }
......
import { default as category } from './categories' import { default as category } from './categories'
import { isBlockBlockHashAccess } from './staticAnalysisCommon' import { isBlockBlockHashAccess } from './staticAnalysisCommon'
import { default as algorithm } from './algorithmCategories' import { default as algorithm } from './algorithmCategories'
import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, AstNodeLegacy, CompilationResult} from './../../types' import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, CompilationResult, FunctionCallAstNode} from './../../types'
export default class blockBlockhash implements AnalyzerModule { export default class blockBlockhash implements AnalyzerModule {
warningNodes: AstNodeLegacy[] = [] warningNodes: FunctionCallAstNode[] = []
name: string = 'Block.blockhash usage: ' name: string = 'Block.blockhash usage: '
description: string = 'Semantics maybe unclear' description: string = 'Semantics maybe unclear'
category: ModuleCategory = category.SECURITY category: ModuleCategory = category.SECURITY
algorithm: ModuleAlgorithm = algorithm.EXACT algorithm: ModuleAlgorithm = algorithm.EXACT
visit (node: AstNodeLegacy): void { visit (node: FunctionCallAstNode): void {
if (isBlockBlockHashAccess(node)) this.warningNodes.push(node) if (isBlockBlockHashAccess(node)) this.warningNodes.push(node)
} }
......
import { default as category } from './categories' import { default as category } from './categories'
import { isNowAccess, isBlockTimestampAccess } from './staticAnalysisCommon' import { isNowAccess, isBlockTimestampAccess } from './staticAnalysisCommon'
import { default as algorithm } from './algorithmCategories' import { default as algorithm } from './algorithmCategories'
import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, AstNodeLegacy, CompilationResult, IdentifierAstNode, MemberAccessAstNode} from './../../types' import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, CompilationResult, IdentifierAstNode, MemberAccessAstNode} from './../../types'
export default class blockTimestamp implements AnalyzerModule { export default class blockTimestamp implements AnalyzerModule {
warningNowNodes: IdentifierAstNode[] = [] warningNowNodes: IdentifierAstNode[] = []
......
import { default as category } from './categories' import { default as category } from './categories'
import { default as algorithm } from './algorithmCategories' import { default as algorithm } from './algorithmCategories'
import { isTransfer } from './staticAnalysisCommon' import { isTransfer } from './staticAnalysisCommon'
import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, AstNodeLegacy, CompilationResult, ForStatementAstNode, WhileStatementAstNode, CommonAstNode, ExpressionStatementAstNode} from './../../types' import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, CompilationResult, ForStatementAstNode, WhileStatementAstNode, CommonAstNode, ExpressionStatementAstNode} from './../../types'
export default class etherTransferInLoop implements AnalyzerModule { export default class etherTransferInLoop implements AnalyzerModule {
relevantNodes: CommonAstNode[] = [] relevantNodes: CommonAstNode[] = []
...@@ -11,13 +11,13 @@ export default class etherTransferInLoop implements AnalyzerModule { ...@@ -11,13 +11,13 @@ export default class etherTransferInLoop implements AnalyzerModule {
algorithm: ModuleAlgorithm = algorithm.EXACT algorithm: ModuleAlgorithm = algorithm.EXACT
visit (node: ForStatementAstNode | WhileStatementAstNode): void { visit (node: ForStatementAstNode | WhileStatementAstNode): void {
let transferNodes: CommonAstNode[] = [] let transferNodes: ExpressionStatementAstNode[] = []
transferNodes = node.body.statements.filter(child => ( if(node.body.nodeType === 'Block')
child.nodeType === 'ExpressionStatement' && transferNodes = node.body.statements.filter(child => ( child.nodeType === 'ExpressionStatement' &&
child.expression.nodeType === 'FunctionCall' && child.expression.nodeType === 'FunctionCall' && isTransfer(child.expression.expression)))
isTransfer(child.expression.expression) // When loop body is described without braces
) else if(node.body.nodeType === 'ExpressionStatement' && node.body.expression.nodeType === 'FunctionCall' && isTransfer(node.body.expression.expression))
) transferNodes.push(node.body)
if (transferNodes.length > 0) { if (transferNodes.length > 0) {
this.relevantNodes.push(...transferNodes) this.relevantNodes.push(...transferNodes)
} }
......
import { default as category } from './categories' import { default as category } from './categories'
import { default as algorithm } from './algorithmCategories' import { default as algorithm } from './algorithmCategories'
import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, AstNodeLegacy, CompilationResult, InlineAssemblyAstNode} from './../../types' import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, CompilationResult, InlineAssemblyAstNode} from './../../types'
export default class inlineAssembly implements AnalyzerModule { export default class inlineAssembly implements AnalyzerModule {
inlineAssNodes: InlineAssemblyAstNode[] = [] inlineAssNodes: InlineAssemblyAstNode[] = []
......
import { default as category } from './categories' import { default as category } from './categories'
import { default as algorithm } from './algorithmCategories' import { default as algorithm } from './algorithmCategories'
import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, AstNodeLegacy, CompilationResult} from './../../types' import { isTxOriginAccess } from './staticAnalysisCommon'
import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, CompilationResult, MemberAccessAstNode} from './../../types'
export default class txOrigin implements AnalyzerModule { export default class txOrigin implements AnalyzerModule {
txOriginNodes: AstNodeLegacy[] = [] txOriginNodes: MemberAccessAstNode[] = []
name: string = 'Transaction origin: ' name: string = 'Transaction origin: '
description: string = 'Warn if tx.origin is used' description: string = 'Warn if tx.origin is used'
category: ModuleCategory = category.SECURITY category: ModuleCategory = category.SECURITY
algorithm: ModuleAlgorithm = algorithm.EXACT algorithm: ModuleAlgorithm = algorithm.EXACT
visit (node: AstNodeLegacy): void { visit (node: MemberAccessAstNode): void {
if (node.name === 'MemberAccess' && node.attributes && if (isTxOriginAccess(node)) {
node.attributes.member_name === 'origin' &&
(node.attributes.type === 'address' || node.attributes.type === 'address payable') &&
node.children && node.children.length && node.children[0].attributes &&
node.children[0].attributes.type === 'tx' &&
node.children[0].attributes.value === 'tx') {
this.txOriginNodes.push(node) this.txOriginNodes.push(node)
} }
} }
......
...@@ -312,8 +312,8 @@ export interface IfStatementAstNode { ...@@ -312,8 +312,8 @@ export interface IfStatementAstNode {
nodeType: 'IfStatement' nodeType: 'IfStatement'
src: string src: string
condition: object condition: object
trueBody: object trueBody: BlockAstNode | ExpressionStatementAstNode
falseBody: object falseBody: BlockAstNode | ExpressionStatementAstNode
} }
export interface TryCatchClauseAstNode { export interface TryCatchClauseAstNode {
...@@ -338,7 +338,7 @@ export interface WhileStatementAstNode { ...@@ -338,7 +338,7 @@ export interface WhileStatementAstNode {
nodeType: 'WhileStatement' | 'DoWhileStatement' nodeType: 'WhileStatement' | 'DoWhileStatement'
src: string src: string
condition: any condition: any
body: BlockAstNode body: BlockAstNode | ExpressionStatementAstNode
} }
export interface ForStatementAstNode { export interface ForStatementAstNode {
...@@ -348,7 +348,7 @@ export interface ForStatementAstNode { ...@@ -348,7 +348,7 @@ export interface ForStatementAstNode {
initializationExpression: VariableDeclarationStatementAstNode initializationExpression: VariableDeclarationStatementAstNode
condition: any condition: any
loopExpression: ExpressionStatementAstNode loopExpression: ExpressionStatementAstNode
body: BlockAstNode body: BlockAstNode | ExpressionStatementAstNode
} }
export interface ContinueAstNode { export interface ContinueAstNode {
...@@ -423,7 +423,7 @@ export interface AssignmentAstNode extends ExpressionAttributes { ...@@ -423,7 +423,7 @@ export interface AssignmentAstNode extends ExpressionAttributes {
nodeType: 'Assignment' nodeType: 'Assignment'
src: string src: string
operator: string operator: string
leftHandSide: object leftHandSide: any
rightHandSide: object rightHandSide: object
} }
......
pragma solidity >=0.4.9 <0.7.0; pragma solidity >=0.4.9 <0.7.0;
library Set { contract Set {
// We define a new struct datatype that will be used to // We define a new struct datatype that will be used to
// hold its data in the calling contract. // hold its data in the calling contract.
struct Data { mapping(uint => bool) flags; } // struct Data { uint flags; }
// Note that the first parameter is of type "storage // Note that the first parameter is of type "storage
// reference" and thus only its storage address and not // reference" and thus only its storage address and not
...@@ -11,35 +11,35 @@ library Set { ...@@ -11,35 +11,35 @@ library Set {
// special feature of library functions. It is idiomatic // special feature of library functions. It is idiomatic
// to call the first parameter 'self', if the function can // to call the first parameter 'self', if the function can
// be seen as a method of that object. // be seen as a method of that object.
function insert(Data storage self, uint value) public //function insert(Data memory self, uint value) public
returns (bool) // returns (bool)
{ //{
if (self.flags[value]) // if (self.flags[value])
return false; // already there // return false; // already there
self.flags[value] = true; // self.flags[value] = true;
return true; // return true;
} // }
function remove(Data storage self, uint value) public // function remove(Data memory self, uint value) public
returns (bool) // returns (bool)
{ // {
if (!self.flags[value]) // if (!self.flags[value])
return false; // not there // return false; // not there
self.flags[value] = false; // self.flags[value] = false;
return true; // return true;
} // }
function contains(Data storage self, uint value) public function contains(uint value) public pure
returns (bool) returns (uint)
{ {
return self.flags[value]; return value;
} }
} }
contract C { contract C {
Set.Data knownValues; Set x;
function register(uint value) public { function register(uint value) public {
// The library functions can be called without a // The library functions can be called without a
...@@ -47,12 +47,18 @@ contract C { ...@@ -47,12 +47,18 @@ contract C {
// "instance" will be the current contract. // "instance" will be the current contract.
address payable a; address payable a;
a.send(10 wei); a.send(10 wei);
if (!Set.insert(knownValues, value)) //if (!Set.insert(knownValues, value))
revert(); // revert();
} }
function tests2() public { function tests2() public {
this.register(10); x = Set(0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c);
uint y = x.contains(103);
if(y == 103){
y++;
} else {
y--;
}
} }
// In this contract, we can also directly access knownValues.flags, if we want. // In this contract, we can also directly access knownValues.flags, if we want.
} }
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment