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

ballot.sol integration tests

parent 8ccef1c5
......@@ -174,10 +174,10 @@ export default class abstractAstView {
private getLocalVariables (funcNode: ParameterListAstNode): VariableDeclarationAstNode[] {
const locals: VariableDeclarationAstNode[] = []
new AstWalker().walk(funcNode, {'*': function (node) {
new AstWalker().walkFull(funcNode, (node) => {
if (node.nodeType === "VariableDeclaration") locals.push(node)
return true
}})
})
return locals
}
}
......@@ -55,7 +55,6 @@ export default class constantFunctions implements AnalyzerModule {
)
}
})
contract.functions.filter((func) => hasFunctionBody(func.node)).forEach((func) => {
if (isConstantFunction(func.node) !== func['potentiallyshouldBeConst']) {
const funcName: string = getFullQuallyfiedFuncDefinitionIdent(contract.node, func.node, func.parameters)
......
'use strict'
import { FunctionHLAst, ContractHLAst, FunctionCallGraph, ContractCallGraph } from "types"
import { FunctionHLAst, ContractHLAst, FunctionCallGraph, ContractCallGraph, Context } from "types"
import { isLocalCallGraphRelevantNode, isExternalDirectCall, getFullQualifiedFunctionCallIdent, getFullQuallyfiedFuncDefinitionIdent, getContractName } from './staticAnalysisCommon'
function buildLocalFuncCallGraphInternal (functions: FunctionHLAst[], nodeFilter: any , extractNodeIdent: any, extractFuncDefIdent: Function): Record<string, FunctionCallGraph> {
......@@ -61,11 +61,11 @@ export function buildGlobalFuncCallGraph (contracts: ContractHLAst[]): Record<st
* @nodeCheck {(ASTNode, context) -> bool} applied on every relevant node in the call graph
* @return {bool} returns map from contract name to contract call graph
*/
export function analyseCallGraph (callGraph: Record<string, ContractCallGraph>, funcName: string, context: object, nodeCheck): boolean {
export function analyseCallGraph (callGraph: Record<string, ContractCallGraph>, funcName: string, context: Context, nodeCheck: ((node: any, context: Context) => boolean)): boolean {
return analyseCallGraphInternal(callGraph, funcName, context, (a, b) => a || b, nodeCheck, {})
}
function analyseCallGraphInternal (callGraph: Record<string, ContractCallGraph>, funcName: string, context: object, combinator: Function, nodeCheck, visited : object): boolean {
function analyseCallGraphInternal (callGraph: Record<string, ContractCallGraph>, funcName: string, context: Context, combinator: Function, nodeCheck, visited : object): boolean {
const current: FunctionCallGraph | undefined = resolveCallGraphSymbol(callGraph, funcName)
if (current === undefined || visited[funcName] === true) return true
......
......@@ -52,7 +52,10 @@ export default class similarVariableNames implements AnalyzerModule {
const similar: Record<string, any>[] = []
const comb: Record<string, boolean> = {}
vars.map((varName1) => vars.map((varName2) => {
if (varName1.length > 1 && varName2.length > 1 && varName2 !== varName1 && !this.isCommonPrefixedVersion(varName1, varName2) && !this.isCommonNrSuffixVersion(varName1, varName2) && !(comb[varName1 + ';' + varName2] || comb[varName2 + ';' + varName1])) {
if (varName1.length > 1 && varName2.length > 1 &&
varName2 !== varName1 && !this.isCommonPrefixedVersion(varName1, varName2) &&
!this.isCommonNrSuffixVersion(varName1, varName2) &&
!(comb[varName1 + ';' + varName2] || comb[varName2 + ';' + varName1])) {
comb[varName1 + ';' + varName2] = true
const distance: number = get(varName1, varName2)
if (distance <= 2) similar.push({ var1: varName1, var2: varName2, distance: distance })
......
......@@ -168,10 +168,31 @@ function getFunctionCallType (func: FunctionCallAstNode): string {
* @effectNode {ASTNode} Assignmnet node
* @return {string} variable name written to
*/
function getEffectedVariableName (effectNode: AssignmentAstNode | UnaryOperationAstNode): string {
function getEffectedVariableName (effectNode: AssignmentAstNode | UnaryOperationAstNode) {
if (!isEffect(effectNode)) throw new Error('staticAnalysisCommon.js: not an effect Node')
if(effectNode.nodeType === 'Assignment') return effectNode.leftHandSide.name
else /* if(effectNode.nodeType === 'UnaryOperation') */ return effectNode.subExpression.name
if(effectNode.nodeType === 'Assignment' || effectNode.nodeType === 'UnaryOperation') {
const IdentNode = findFirstSubNodeLTR(effectNode, exactMatch(nodeTypes.IDENTIFIER))
return IdentNode.name
}
}
// developed keeping identifier node search in mind
function findFirstSubNodeLTR (node, type) {
if(node.nodeType && nodeType(node, type))
return node
else if(node.nodeType && nodeType(node, exactMatch('Assignment')))
return findFirstSubNodeLTR(node.leftHandSide, type)
else if(node.nodeType && nodeType(node, exactMatch('MemberAccess')))
return findFirstSubNodeLTR(node.expression, type)
else if(node.nodeType && nodeType(node, exactMatch('IndexAccess')))
return findFirstSubNodeLTR(node.baseExpression, type)
else if(node.nodeType && nodeType(node, exactMatch('UnaryOperation')))
return findFirstSubNodeLTR(node.subExpression, type)
}
/**
......@@ -417,7 +438,7 @@ function getFullQualifiedFunctionCallIdent (contract: ContractDefinitionAstNode,
else if (isSuperLocalCall(func.expression)) return getContractName(contract) + '.' + getSuperLocalCallName(func) + '(' + getFunctionCallTypeParameterType(func) + ')'
else if (isExternalDirectCall(func.expression)) return getExternalDirectCallContractName(func) + '.' + getExternalDirectCallMemberName(func) + '(' + getFunctionCallTypeParameterType(func) + ')'
else if (isLibraryCall(func.expression)) return getLibraryCallContractName(func.expression) + '.' + getLibraryCallMemberName(func) + '(' + getFunctionCallTypeParameterType(func) + ')'
else throw new Error('staticAnalysisCommon.js: Can not get function name form non function call node')
else throw new Error('staticAnalysisCommon.js: Can not get function name from non function call node')
}
function getFullQuallyfiedFuncDefinitionIdent (contract: ContractDefinitionAstNode, func: FunctionDefinitionAstNode, paramTypes: any[]): string {
......@@ -622,7 +643,7 @@ function isEffect (node: AssignmentAstNode | UnaryOperationAstNode | InlineAssem
* @node {list Variable declaration} state variable declaration currently in scope
* @return {bool}
*/
function isWriteOnStateVariable (effectNode: AssignmentAstNode | InlineAssemblyAstNode | UnaryOperationAstNode, stateVariables: any[]) {
function isWriteOnStateVariable (effectNode: AssignmentAstNode | InlineAssemblyAstNode | UnaryOperationAstNode, stateVariables: VariableDeclarationAstNode[]) {
return effectNode.nodeType === "InlineAssembly" || (isEffect(effectNode) && isStateVariable(getEffectedVariableName(effectNode), stateVariables))
}
......@@ -632,8 +653,8 @@ function isWriteOnStateVariable (effectNode: AssignmentAstNode | InlineAssemblyA
* @node {list Variable declaration} state variable declaration currently in scope
* @return {bool}
*/
function isStateVariable (name: string, stateVariables: any[]): boolean {
return stateVariables.some((item) => name === getDeclaredVariableName(item))
function isStateVariable (name: string, stateVariables: VariableDeclarationAstNode[]): boolean {
return stateVariables.some((item: VariableDeclarationAstNode) => item.stateVariable && name === getDeclaredVariableName(item))
}
/**
......
......@@ -129,7 +129,7 @@ export interface ContractDefinitionAstNode {
nodeType: 'ContractDefinition'
src: string
name: string
documentation: object | null
documentation: string | null
contractKind: 'interface' | 'contract' | 'library'
abstract: boolean
fullyImplemented: boolean
......@@ -202,7 +202,7 @@ export interface FunctionDefinitionAstNode {
nodeType: 'FunctionDefinition'
src: string
name: string
documentation: object | null
documentation: string | null
kind: string
stateMutability: 'pure' | 'view' | 'nonpayable' | 'payable'
visibility: string
......
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