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

node identification methods removed

parent d5548b62
import { isContractDefinition, getStateVariableDeclarationsFormContractNode, isInheritanceSpecifier,
getInheritsFromName, isModifierDefinition, isModifierInvocation, getContractName,
getFunctionOrModifierDefinitionParameterPart, getType, getDeclaredVariableName, isVariableDeclaration,
import { getStateVariableDeclarationsFormContractNode,
getInheritsFromName, getContractName,
getFunctionOrModifierDefinitionParameterPart, getType, getDeclaredVariableName,
getFunctionDefinitionReturnParameterPart } from './staticAnalysisCommon'
import { AstWalker } from 'remix-astwalker'
import { CommonAstNode } from 'types'
import { CommonAstNode, FunctionDefinitionAstNode, ParameterListAstNode } from 'types'
export default class abstractAstView {
contracts = []
......@@ -49,7 +49,7 @@ export default class abstractAstView {
*/
build_visit (relevantNodeFilter) {
var that = this
return function (node: CommonAstNode) {
return function (node: any) {
if (node.nodeType === "ContractDefinition") {
that.setCurrentContract(that, {
node: node,
......@@ -59,7 +59,7 @@ export default class abstractAstView {
inheritsFrom: [],
stateVariables: getStateVariableDeclarationsFormContractNode(node)
})
} else if (isInheritanceSpecifier(node)) {
} else if (node.nodeType === "InheritanceSpecifier") {
const currentContract = that.getCurrentContract(that)
const inheritsFromName = getInheritsFromName(node)
currentContract.inheritsFrom.push(inheritsFromName)
......@@ -78,14 +78,14 @@ export default class abstractAstView {
that.getCurrentFunction(that).relevantNodes.push(item.node)
}
})
} else if (isModifierDefinition(node)) {
} else if (node.nodeType === "ModifierDefinition") {
that.setCurrentModifier(that, {
node: node,
relevantNodes: [],
localVariables: that.getLocalVariables(node),
parameters: that.getLocalParameters(node)
})
} else if (isModifierInvocation(node)) {
} else if (node.nodeType === "ModifierInvocation") {
if (!that.isFunctionNotModifier) throw new Error('abstractAstView.js: Found modifier invocation outside of function scope.')
that.getCurrentFunction(that).modifierInvocations.push(node)
} else if (relevantNodeFilter(node)) {
......@@ -160,7 +160,7 @@ export default class abstractAstView {
}
private getLocalParameters (funcNode) {
return this.getLocalVariables(getFunctionOrModifierDefinitionParameterPart(funcNode)).map(getType)
return getFunctionOrModifierDefinitionParameterPart(funcNode).parameters.map(getType)
}
private getReturnParameters (funcNode) {
......@@ -172,10 +172,10 @@ export default class abstractAstView {
})
}
private getLocalVariables (funcNode) {
private getLocalVariables (funcNode: ParameterListAstNode) {
const locals: any[] = []
new AstWalker().walk(funcNode, {'*': function (node) {
if (isVariableDeclaration(node)) locals.push(node)
if (node.nodeType === "VariableDeclaration") locals.push(node)
return true
}})
return locals
......
import { default as category } from './categories'
import { isLowLevelCall, isTransfer, isExternalDirectCall, isEffect, isLocalCallGraphRelevantNode,
isInlineAssembly, isNewExpression, isSelfdestructCall, isDeleteUnaryOperation, isPayableFunction,
isSelfdestructCall, isDeleteUnaryOperation, isPayableFunction,
isConstructor, getFullQuallyfiedFuncDefinitionIdent, hasFunctionBody, isConstantFunction, isWriteOnStateVariable,
isStorageVariableDeclaration, isCallToNonConstLocalFunction, getFullQualifiedFunctionCallIdent} from './staticAnalysisCommon'
import { default as algorithm } from './algorithmCategories'
import { buildGlobalFuncCallGraph, resolveCallGraphSymbol, analyseCallGraph } from './functionCallGraph'
import AbstractAst from './abstractAstView'
import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, AstNodeLegacy, CompilationResult} from './../../types'
import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, AstNodeLegacy, CompilationResult, CommonAstNode} from './../../types'
export default class constantFunctions implements AnalyzerModule {
name: string = 'Constant functions: '
......@@ -17,13 +17,13 @@ export default class constantFunctions implements AnalyzerModule {
abstractAst: AbstractAst = new AbstractAst()
visit = this.abstractAst.build_visit(
(node: AstNodeLegacy) => isLowLevelCall(node) ||
(node: CommonAstNode) => isLowLevelCall(node) ||
isTransfer(node) ||
isExternalDirectCall(node) ||
isEffect(node) ||
isLocalCallGraphRelevantNode(node) ||
isInlineAssembly(node) ||
isNewExpression(node) ||
node.nodeType === "InlineAssembly" ||
node.nodeType === "NewExpression" ||
isSelfdestructCall(node) ||
isDeleteUnaryOperation(node)
)
......@@ -98,8 +98,8 @@ export default class constantFunctions implements AnalyzerModule {
isTransfer(node) ||
this.isCallOnNonConstExternalInterfaceFunction(node, context) ||
isCallToNonConstLocalFunction(node) ||
isInlineAssembly(node) ||
isNewExpression(node) ||
node.nodeType === "InlineAssembly" ||
node.nodeType === "NewExpression" ||
isSelfdestructCall(node) ||
isDeleteUnaryOperation(node)
}
......
import { default as category } from './categories'
import { default as algorithm } from './algorithmCategories'
import { isLoop, isBlock, getLoopBlockStartIndex, isExpressionStatement, isTransfer } from './staticAnalysisCommon'
import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, AstNodeLegacy, CompilationResult} from './../../types'
import { getLoopBlockStartIndex, isTransfer } from './staticAnalysisCommon'
import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, AstNodeLegacy, CompilationResult, ForStatementAstNode, WhileStatementAstNode, CommonAstNode, ExpressionStatementAstNode} from './../../types'
export default class etherTransferInLoop implements AnalyzerModule {
relevantNodes: AstNodeLegacy[] = []
relevantNodes: CommonAstNode[] = []
name: string = 'Ether transfer in a loop: '
description: string = 'Avoid transferring Ether to multiple addresses in a loop'
category: ModuleCategory = category.GAS
algorithm: ModuleAlgorithm = algorithm.EXACT
visit (node: AstNodeLegacy): void {
if (isLoop(node)) {
let transferNodes: AstNodeLegacy[] = []
const loopBlockStartIndex: number | undefined = getLoopBlockStartIndex(node)
if (loopBlockStartIndex && node.children && isBlock(node.children[loopBlockStartIndex])) {
const childrenNodes: AstNodeLegacy[] | undefined = node.children[loopBlockStartIndex].children
if(childrenNodes)
transferNodes = childrenNodes.filter(child => (
isExpressionStatement(child) &&
child.children &&
child.children[0].name === 'FunctionCall' &&
child.children[0].children &&
isTransfer(child.children[0].children[0])
visit (node: ForStatementAstNode | WhileStatementAstNode): void {
let transferNodes: CommonAstNode[] = []
transferNodes = node.body.statements.filter(child => (
child.nodeType === 'ExpressionStatement' &&
child.expression.nodeType === 'FunctionCall' &&
isTransfer(child.expression.expression)
)
)
if (transferNodes.length > 0) {
this.relevantNodes.push(...transferNodes)
}
}
}
}
report (compilationResults: CompilationResult): ReportObj[] {
return this.relevantNodes.map((node) => {
......
import { default as category } from './categories'
import { default as algorithm } from './algorithmCategories'
import { isForLoop, isDynamicArrayLengthAccess, isBinaryOperation } from './staticAnalysisCommon'
import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, AstNodeLegacy, CompilationResult} from './../../types'
import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, AstNodeLegacy, CompilationResult, CommonAstNode} from './../../types'
export default class forLoopIteratesOverDynamicArray implements AnalyzerModule {
relevantNodes: AstNodeLegacy[] = []
relevantNodes: CommonAstNode[] = []
name: string = 'For loop iterates over dynamic array: '
description: string = 'The number of \'for\' loop iterations depends on dynamic array\'s size'
category: ModuleCategory = category.GAS
algorithm: ModuleAlgorithm = algorithm.EXACT
visit (node: AstNodeLegacy): void {
if (isForLoop(node) && node.children) {
visit (node: CommonAstNode): void {
if (node.nodeType === "Forstatement" && node.children) {
let conditionChildrenNode: AstNodeLegacy | null = null
// Access 'condition' node of 'for' loop statement
const forLoopConditionNode: AstNodeLegacy = node.children[1]
......
import { default as category } from './categories'
import { isInlineAssembly } from './staticAnalysisCommon'
import { default as algorithm } from './algorithmCategories'
import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, AstNodeLegacy, CompilationResult} from './../../types'
import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, AstNodeLegacy, CompilationResult, InlineAssemblyAstNode} from './../../types'
export default class inlineAssembly implements AnalyzerModule {
inlineAssNodes: AstNodeLegacy[] = []
inlineAssNodes: InlineAssemblyAstNode[] = []
name: string = 'Inline assembly: '
description: string = 'Use of Inline Assembly'
category: ModuleCategory = category.SECURITY
algorithm: ModuleAlgorithm = algorithm.EXACT
visit (node: AstNodeLegacy): void {
if (isInlineAssembly(node)) this.inlineAssNodes.push(node)
visit (node: InlineAssemblyAstNode): void {
this.inlineAssNodes.push(node)
}
report (compilationResults: CompilationResult): ReportObj[] {
......
import { default as category } from './categories'
import { isReturn, isAssignment, hasFunctionBody, getFullQuallyfiedFuncDefinitionIdent, getEffectedVariableName } from './staticAnalysisCommon'
import { hasFunctionBody, getFullQuallyfiedFuncDefinitionIdent, getEffectedVariableName } from './staticAnalysisCommon'
import { default as algorithm } from './algorithmCategories'
import AbstractAst from './abstractAstView'
import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, AstNodeLegacy, CompilationResult} from './../../types'
import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, AstNodeLegacy, CompilationResult, CommonAstNode, FunctionDefinitionAstNode} from './../../types'
export default class noReturn implements AnalyzerModule {
name: string = 'no return: '
......@@ -13,7 +13,7 @@ export default class noReturn implements AnalyzerModule {
abstractAst: AbstractAst = new AbstractAst()
visit = this.abstractAst.build_visit(
(node: AstNodeLegacy) => isReturn(node) || isAssignment(node)
(node: CommonAstNode) => node.nodeType === "Return" || node.nodeType === "Assignment"
)
report = this.abstractAst.build_report(this._report.bind(this))
......@@ -44,13 +44,13 @@ export default class noReturn implements AnalyzerModule {
return func.returns.length > 0
}
private hasReturnStatement (func): boolean {
return func.relevantNodes.filter(isReturn).length > 0
private hasReturnStatement (func: CommonAstNode): boolean {
return func.relevantNodes.filter(n => n.nodeType === "Return").length > 0
}
private hasAssignToAllNamedReturns (func): boolean {
const namedReturns = func.returns.filter((n) => n.name.length > 0).map((n) => n.name)
const assignedVars = func.relevantNodes.filter(isAssignment).map(getEffectedVariableName)
const assignedVars = func.relevantNodes.filter(n => n.nodeType === "Assignment").map(getEffectedVariableName)
const diff = namedReturns.filter(e => !assignedVars.includes(e))
return diff.length === 0
}
......
......@@ -95,7 +95,7 @@ export interface ContractDefinitionAstNode {
linearizedBaseContracts: Array<number>
baseContracts: Array<InheritanceSpecifierAstNode>
contractDependencies: Array<number>
nodes: Array<any>
nodes: Array<CommonAstNode>
scope: number
}
......@@ -298,7 +298,7 @@ export interface BlockAstNode {
id: number
nodeType: 'Block'
src: string
statements: Array<object>
statements: Array<CommonAstNode>
}
export interface PlaceholderStatementAstNode {
......
......@@ -317,89 +317,89 @@ test('staticAnalysisCommon.getLoopBlockStartIndex', function (t) {
// t.notOk(common.isFunctionDefinition(node3), 'substring should not work')
// })
test('staticAnalysisCommon.isModifierDefinition', function (t) {
t.plan(3)
const node1 = { name: 'ModifierDefinition' }
const node2 = { name: 'MemberAccess' }
const node3 = { name: 'ModifierDefinitionBLABLA' }
// test('staticAnalysisCommon.isModifierDefinition', function (t) {
// t.plan(3)
// const node1 = { name: 'ModifierDefinition' }
// const node2 = { name: 'MemberAccess' }
// const node3 = { name: 'ModifierDefinitionBLABLA' }
t.ok(common.isModifierDefinition(node1), 'is exact match should work')
t.notOk(common.isModifierDefinition(node2), 'different node should not work')
t.notOk(common.isModifierDefinition(node3), 'substring should not work')
})
// t.ok(common.isModifierDefinition(node1), 'is exact match should work')
// t.notOk(common.isModifierDefinition(node2), 'different node should not work')
// t.notOk(common.isModifierDefinition(node3), 'substring should not work')
// })
test('staticAnalysisCommon.isModifierInvocation', function (t) {
t.plan(3)
const node1 = { name: 'ModifierInvocation' }
const node2 = { name: 'MemberAccess' }
const node3 = { name: 'ModifierInvocationBLABLA' }
// test('staticAnalysisCommon.isModifierInvocation', function (t) {
// t.plan(3)
// const node1 = { name: 'ModifierInvocation' }
// const node2 = { name: 'MemberAccess' }
// const node3 = { name: 'ModifierInvocationBLABLA' }
t.ok(common.isModifierInvocation(node1), 'is exact match should work')
t.notOk(common.isModifierInvocation(node2), 'different node should not work')
t.notOk(common.isModifierInvocation(node3), 'substring should not work')
})
// t.ok(common.isModifierInvocation(node1), 'is exact match should work')
// t.notOk(common.isModifierInvocation(node2), 'different node should not work')
// t.notOk(common.isModifierInvocation(node3), 'substring should not work')
// })
test('staticAnalysisCommon.isVariableDeclaration', function (t) {
t.plan(3)
const node1 = { name: 'VariableDeclaration' }
const node2 = { name: 'MemberAccess' }
const node3 = { name: 'VariableDeclarationBLABLA' }
// test('staticAnalysisCommon.isVariableDeclaration', function (t) {
// t.plan(3)
// const node1 = { name: 'VariableDeclaration' }
// const node2 = { name: 'MemberAccess' }
// const node3 = { name: 'VariableDeclarationBLABLA' }
t.ok(common.isVariableDeclaration(node1), 'is exact match should work')
t.notOk(common.isVariableDeclaration(node2), 'different node should not work')
t.notOk(common.isVariableDeclaration(node3), 'substring should not work')
})
// t.ok(common.isVariableDeclaration(node1), 'is exact match should work')
// t.notOk(common.isVariableDeclaration(node2), 'different node should not work')
// t.notOk(common.isVariableDeclaration(node3), 'substring should not work')
// })
test('staticAnalysisCommon.isInheritanceSpecifier', function (t) {
t.plan(3)
const node1 = { name: 'InheritanceSpecifier' }
const node2 = { name: 'MemberAccess' }
const node3 = { name: 'InheritanceSpecifierBLABLA' }
// test('staticAnalysisCommon.isInheritanceSpecifier', function (t) {
// t.plan(3)
// const node1 = { name: 'InheritanceSpecifier' }
// const node2 = { name: 'MemberAccess' }
// const node3 = { name: 'InheritanceSpecifierBLABLA' }
t.ok(common.isInheritanceSpecifier(node1), 'is exact match should work')
t.notOk(common.isInheritanceSpecifier(node2), 'different node should not work')
t.notOk(common.isInheritanceSpecifier(node3), 'substring should not work')
})
// t.ok(common.isInheritanceSpecifier(node1), 'is exact match should work')
// t.notOk(common.isInheritanceSpecifier(node2), 'different node should not work')
// t.notOk(common.isInheritanceSpecifier(node3), 'substring should not work')
// })
test('staticAnalysisCommon.isAssignment', function (t) {
t.plan(3)
const node1 = { name: 'Assignment' }
const node2 = { name: 'MemberAccess' }
const node3 = { name: 'AssignmentBLABLA' }
// test('staticAnalysisCommon.isAssignment', function (t) {
// t.plan(3)
// const node1 = { name: 'Assignment' }
// const node2 = { name: 'MemberAccess' }
// const node3 = { name: 'AssignmentBLABLA' }
t.ok(common.isAssignment(node1), 'is exact match should work')
t.notOk(common.isAssignment(node2), 'different node should not work')
t.notOk(common.isAssignment(node3), 'substring should not work')
})
// t.ok(common.isAssignment(node1), 'is exact match should work')
// t.notOk(common.isAssignment(node2), 'different node should not work')
// t.notOk(common.isAssignment(node3), 'substring should not work')
// })
test('staticAnalysisCommon.isContractDefinition', function (t) {
t.plan(3)
const node1 = { name: 'ContractDefinition' }
const node2 = { name: 'MemberAccess' }
const node3 = { name: 'ContractDefinitionBLABLA' }
// test('staticAnalysisCommon.isContractDefinition', function (t) {
// t.plan(3)
// const node1 = { name: 'ContractDefinition' }
// const node2 = { name: 'MemberAccess' }
// const node3 = { name: 'ContractDefinitionBLABLA' }
t.ok(common.isContractDefinition(node1), 'is exact match should work')
t.notOk(common.isContractDefinition(node2), 'different node should not work')
t.notOk(common.isContractDefinition(node3), 'substring should not work')
})
// t.ok(common.isContractDefinition(node1), 'is exact match should work')
// t.notOk(common.isContractDefinition(node2), 'different node should not work')
// t.notOk(common.isContractDefinition(node3), 'substring should not work')
// })
test('staticAnalysisCommon.isInlineAssembly', function (t) {
t.plan(3)
const node1 = { name: 'InlineAssembly' }
const node2 = { name: 'MemberAccess' }
const node3 = { name: 'InlineAssemblyBLABLA' }
// test('staticAnalysisCommon.isInlineAssembly', function (t) {
// t.plan(3)
// const node1 = { name: 'InlineAssembly' }
// const node2 = { name: 'MemberAccess' }
// const node3 = { name: 'InlineAssemblyBLABLA' }
t.ok(common.isInlineAssembly(node1), 'is exact match should work')
t.notOk(common.isInlineAssembly(node2), 'different node should not work')
t.notOk(common.isInlineAssembly(node3), 'substring should not work')
})
// t.ok(common.isInlineAssembly(node1), 'is exact match should work')
// t.notOk(common.isInlineAssembly(node2), 'different node should not work')
// t.notOk(common.isInlineAssembly(node3), 'substring should not work')
// })
test('staticAnalysisCommon.isLoop', function (t) {
t.plan(3)
t.equal(common.isLoop(forLoopNode), true)
t.equal(common.isLoop(doWhileLoopNode), true)
t.equal(common.isLoop(whileLoopNode), true)
})
// test('staticAnalysisCommon.isLoop', function (t) {
// t.plan(3)
// t.equal(common.isLoop(forLoopNode), true)
// t.equal(common.isLoop(doWhileLoopNode), true)
// t.equal(common.isLoop(whileLoopNode), true)
// })
// #################### Complex Node Identification
......
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