method updates

pull/5370/head
aniket-engg 5 years ago committed by Aniket
parent 28a9149d6c
commit ffa8dd8bcc
  1. 6
      remix-analyzer/src/solidity-analyzer/modules/abstractAstView.ts
  2. 2
      remix-analyzer/src/solidity-analyzer/modules/constantFunctions.ts
  3. 6
      remix-analyzer/src/solidity-analyzer/modules/deleteDynamicArrays.ts
  4. 26
      remix-analyzer/src/solidity-analyzer/modules/forLoopIteratesOverDynamicArray.ts
  5. 6
      remix-analyzer/src/solidity-analyzer/modules/intDivisionTruncate.ts
  6. 6
      remix-analyzer/src/solidity-analyzer/modules/lowLevelCalls.ts
  7. 153
      remix-analyzer/src/solidity-analyzer/modules/staticAnalysisCommon.ts
  8. 6
      remix-analyzer/src/solidity-analyzer/modules/thisLocal.ts
  9. 14
      remix-analyzer/src/types.ts

@ -3,7 +3,7 @@ import { getStateVariableDeclarationsFormContractNode,
getFunctionOrModifierDefinitionParameterPart, getType, getDeclaredVariableName,
getFunctionDefinitionReturnParameterPart } from './staticAnalysisCommon'
import { AstWalker } from 'remix-astwalker'
import { CommonAstNode, FunctionDefinitionAstNode, ParameterListAstNode } from 'types'
import { CommonAstNode, FunctionDefinitionAstNode, ParameterListAstNode, ModifierDefinitionAstNode } from 'types'
export default class abstractAstView {
contracts = []
@ -159,11 +159,11 @@ export default class abstractAstView {
return that.getCurrentContract(that).modifiers[that.currentModifierIndex]
}
private getLocalParameters (funcNode) {
private getLocalParameters (funcNode: FunctionDefinitionAstNode | ModifierDefinitionAstNode) {
return getFunctionOrModifierDefinitionParameterPart(funcNode).parameters.map(getType)
}
private getReturnParameters (funcNode) {
private getReturnParameters (funcNode: FunctionDefinitionAstNode) {
return this.getLocalVariables(getFunctionDefinitionReturnParameterPart(funcNode)).map((n) => {
return {
type: getType(n),

@ -17,7 +17,7 @@ export default class constantFunctions implements AnalyzerModule {
abstractAst: AbstractAst = new AbstractAst()
visit = this.abstractAst.build_visit(
(node: CommonAstNode) => isLowLevelCall(node) ||
(node: any) => isLowLevelCall(node) ||
isTransfer(node) ||
isExternalDirectCall(node) ||
isEffect(node) ||

@ -1,16 +1,16 @@
import { default as category } from './categories'
import { isDeleteOfDynamicArray } from './staticAnalysisCommon'
import { default as algorithm } from './algorithmCategories'
import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, AstNodeLegacy, CompilationResult} from './../../types'
import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, CompilationResult, UnaryOperationAstNode} from './../../types'
export default class deleteDynamicArrays implements AnalyzerModule {
rel: AstNodeLegacy[] = []
rel: UnaryOperationAstNode[] = []
name: string = 'Delete on dynamic Array: '
description: string = 'Use require and appropriately'
category: ModuleCategory = category.GAS
algorithm: ModuleAlgorithm = algorithm.EXACT
visit (node: AstNodeLegacy): void {
visit (node: UnaryOperationAstNode): void {
if (isDeleteOfDynamicArray(node)) this.rel.push(node)
}

@ -1,31 +1,23 @@
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, CommonAstNode} from './../../types'
import { isDynamicArrayLengthAccess } from './staticAnalysisCommon'
import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, CompilationResult, ForStatementAstNode} from './../../types'
export default class forLoopIteratesOverDynamicArray implements AnalyzerModule {
relevantNodes: CommonAstNode[] = []
relevantNodes: ForStatementAstNode[] = []
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: 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]
// Access right side of condition as its children
if(forLoopConditionNode && forLoopConditionNode.children){
conditionChildrenNode = forLoopConditionNode.children[1]
}
// Check if it is a binary operation. if yes, check if its children node access length of dynamic array
if (conditionChildrenNode && conditionChildrenNode.children && isBinaryOperation(conditionChildrenNode) && isDynamicArrayLengthAccess(conditionChildrenNode.children[0])) {
this.relevantNodes.push(node)
} else if (isDynamicArrayLengthAccess(conditionChildrenNode)) { // else check if condition node itself access length of dynamic array
visit (node: ForStatementAstNode): void {
const { condition } = node
// Check if condition is `i < array.length - 1`
if ((condition.nodeType === "BinaryOperation" && condition.rightExpression.nodeType === "BinaryOperation" && isDynamicArrayLengthAccess(condition.rightExpression.leftExpression)) ||
// or condition is `i < array.length`
(condition.nodeType === "BinaryOperation" && isDynamicArrayLengthAccess(condition.rightExpression))) {
this.relevantNodes.push(node)
}
}
}
report (compilationResults: CompilationResult): ReportObj[] {

@ -1,16 +1,16 @@
import { default as category } from './categories'
import { isIntDivision } from './staticAnalysisCommon'
import { default as algorithm } from './algorithmCategories'
import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, AstNodeLegacy, CompilationResult} from './../../types'
import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, CompilationResult, BinaryOperationAstNode} from './../../types'
export default class intDivisionTruncate implements AnalyzerModule {
warningNodes: AstNodeLegacy[] = []
warningNodes: BinaryOperationAstNode[] = []
name: string = 'Data Truncated: '
description: string = 'Division on int/uint values truncates the result.'
category: ModuleCategory = category.MISC
algorithm: ModuleAlgorithm = algorithm.EXACT
visit (node: AstNodeLegacy): void {
visit (node: BinaryOperationAstNode): void {
if (isIntDivision(node)) this.warningNodes.push(node)
}

@ -2,10 +2,10 @@ import { default as category } from './categories'
import { isLowLevelCallInst, isLowLevelCallInst050, isLowLevelCallcodeInst, isLowLevelDelegatecallInst,
isLowLevelSendInst, isLowLevelSendInst050, isLLDelegatecallInst050, lowLevelCallTypes } from './staticAnalysisCommon'
import { default as algorithm } from './algorithmCategories'
import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, AstNodeLegacy, CompilationResult} from './../../types'
import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, CompilationResult, MemberAccessAstNode} from './../../types'
interface llcNode {
node: AstNodeLegacy
node: MemberAccessAstNode
type: {
ident: string,
type: string
@ -19,7 +19,7 @@ export default class lowLevelCalls implements AnalyzerModule {
category: ModuleCategory = category.SECURITY
algorithm: ModuleAlgorithm = algorithm.EXACT
visit (node : AstNodeLegacy): void {
visit (node : MemberAccessAstNode): void {
if (isLowLevelCallInst(node)) {
this.llcNodes.push({node: node, type: lowLevelCallTypes.CALL})
} else if (isLowLevelCallInst050(node)) {

@ -1,6 +1,6 @@
'use strict'
import { FunctionDefinitionAstNode, ModifierDefinitionAstNode, ParameterListAstNode, CommonAstNode, ForStatementAstNode, WhileStatementAstNode, VariableDeclarationAstNode, ContractDefinitionAstNode, InheritanceSpecifierAstNode, MemberAccessAstNode } from "types"
import { FunctionDefinitionAstNode, ModifierDefinitionAstNode, ParameterListAstNode, CommonAstNode, ForStatementAstNode, WhileStatementAstNode, VariableDeclarationAstNode, ContractDefinitionAstNode, InheritanceSpecifierAstNode, MemberAccessAstNode, BinaryOperationAstNode, FunctionCallAstNode, ExpressionStatementAstNode, UnaryOperationAstNode, IdentifierAstNode, MappingAstNode, IndexAccessAstNode } from "types"
const remixLib = require('remix-lib')
const util = remixLib.util
@ -433,8 +433,8 @@ function isBinaryOperation (node) {
* @funcNode {ASTNode} function defintion node
* @return {bool}
*/
function hasFunctionBody (funcNode) {
return findFirstSubNodeLTR(funcNode, exactMatch(nodeTypes.BLOCK)) != null
function hasFunctionBody (funcNode: FunctionDefinitionAstNode) {
return funcNode.body != null
}
/**
@ -442,8 +442,8 @@ function hasFunctionBody (funcNode) {
* @node {ASTNode} node to check for
* @return {bool}
*/
function isDeleteOfDynamicArray (node) {
return isDeleteUnaryOperation(node) && isDynamicArrayAccess(node.children[0])
function isDeleteOfDynamicArray (node: UnaryOperationAstNode) {
return isDeleteUnaryOperation(node) && isDynamicArrayAccess(node.subExpression)
}
/**
@ -451,8 +451,8 @@ function isDeleteOfDynamicArray (node) {
* @node {ASTNode} node to check for
* @return {bool}
*/
function isDynamicArrayAccess (node) {
return node && nodeType(node, exactMatch(nodeTypes.IDENTIFIER)) && (node.attributes.type.endsWith('[] storage ref') || node.attributes.type === 'bytes storage ref' || node.attributes.type === 'string storage ref')
function isDynamicArrayAccess (node: IdentifierAstNode) {
return typeDescription(node, '[] storage ref') || typeDescription(node, 'bytes storage ref') || typeDescription(node, 'string storage ref')
}
/**
@ -460,11 +460,9 @@ function isDynamicArrayAccess (node) {
* @node {ASTNode} node to check for
* @return {bool}
*/
function isDynamicArrayLengthAccess (node) {
return node && // if node exists
nodeType(node, exactMatch(nodeTypes.MEMBERACCESS)) && // is memberAccess Node
(node.attributes.member_name === 'length') && // accessing 'length' member
node.children[0].attributes.type.indexOf('[]') !== -1 // member is accessed from dynamic array, notice [] without any number
function isDynamicArrayLengthAccess (node: MemberAccessAstNode) {
return (node.memberName === 'length') && // accessing 'length' member
node.expression['typeDescriptions']['typeString'].indexOf('[]') !== -1 // member is accessed from dynamic array, notice [] without any number
}
/**
@ -627,8 +625,8 @@ function isConstructor (node: FunctionDefinitionAstNode): boolean {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function isIntDivision (node) {
return isBinaryOperation(node) && operator(node, exactMatch(util.escapeRegExp('/'))) && expressionType(node, util.escapeRegExp('int'))
function isIntDivision (node: BinaryOperationAstNode) {
return operator(node, exactMatch(util.escapeRegExp('/'))) && typeDescription(node.rightExpression, util.escapeRegExp('int'))
}
/**
@ -646,7 +644,7 @@ function isSubScopeStatement (node) {
nodeType(node, exactMatch(nodeTypes.FORSTATEMENT)) ||
nodeType(node, exactMatch(nodeTypes.WHILESTATEMENT)) ||
nodeType(node, exactMatch(nodeTypes.DOWHILESTATEMENT))) &&
minNrOfChildren(node, 2) && !nodeType(node.children[1], exactMatch(nodeTypes.BLOCK))
!nodeType(node.children[1], exactMatch(nodeTypes.BLOCK))
}
/**
@ -654,8 +652,8 @@ function isSubScopeStatement (node) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function isBinaryOpInExpression (node) {
return node.nodeType === "ExpressionStatement" && nrOfChildren(node, 1) && isBinaryOperation(node.children[0])
function isBinaryOpInExpression (node: ExpressionStatementAstNode) {
return node.nodeType === "ExpressionStatement" && node.expression.nodeType === "BinaryOperation"
}
/**
@ -663,8 +661,8 @@ function isBinaryOpInExpression (node) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function isPlusPlusUnaryOperation (node) {
return nodeType(node, exactMatch(nodeTypes.UNARYOPERATION)) && operator(node, exactMatch(util.escapeRegExp('++')))
function isPlusPlusUnaryOperation (node: UnaryOperationAstNode) {
return node.operator === '++'
}
/**
@ -672,8 +670,8 @@ function isPlusPlusUnaryOperation (node) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function isDeleteUnaryOperation (node) {
return nodeType(node, exactMatch(nodeTypes.UNARYOPERATION)) && operator(node, exactMatch(util.escapeRegExp('delete')))
function isDeleteUnaryOperation (node: UnaryOperationAstNode) {
return node.operator === 'delete'
}
/**
@ -681,8 +679,8 @@ function isDeleteUnaryOperation (node) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function isMinusMinusUnaryOperation (node) {
return nodeType(node, exactMatch(nodeTypes.UNARYOPERATION)) && operator(node, exactMatch(util.escapeRegExp('--')))
function isMinusMinusUnaryOperation (node: UnaryOperationAstNode) {
return node.operator === '--'
}
/**
@ -690,8 +688,8 @@ function isMinusMinusUnaryOperation (node) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function isFullyImplementedContract (node) {
return nodeType(node, exactMatch(nodeTypes.CONTRACTDEFINITION)) && node.attributes.fullyImplemented === true
function isFullyImplementedContract (node: ContractDefinitionAstNode) {
return node.fullyImplemented === true
}
/**
@ -699,8 +697,8 @@ function isFullyImplementedContract (node) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function isLibrary (node) {
return nodeType(node, exactMatch(nodeTypes.CONTRACTDEFINITION)) && node.attributes.isLibrary === true
function isLibrary (node: ContractDefinitionAstNode) {
return node.contractKind === 'library'
}
/**
@ -708,8 +706,8 @@ function isLibrary (node) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function isCallToNonConstLocalFunction (node) {
return isLocalCall(node) && !expressionType(node.children[0], basicRegex.CONSTANTFUNCTIONTYPE)
function isCallToNonConstLocalFunction (node: FunctionCallAstNode) {
return isLocalCall(node) && !expressionType(node, basicRegex.CONSTANTFUNCTIONTYPE)
}
/**
@ -717,7 +715,7 @@ function isCallToNonConstLocalFunction (node) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function isLibraryCall (node) {
function isLibraryCall (node: MemberAccessAstNode) {
return isMemberAccess(node, basicRegex.FUNCTIONTYPE, undefined, basicRegex.LIBRARYTYPE, undefined)
}
@ -726,7 +724,7 @@ function isLibraryCall (node) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function isExternalDirectCall (node) {
function isExternalDirectCall (node: MemberAccessAstNode) {
return isMemberAccess(node, basicRegex.EXTERNALFUNCTIONTYPE, undefined, basicRegex.CONTRACTTYPE, undefined) && !isThisLocalCall(node) && !isSuperLocalCall(node)
}
@ -735,10 +733,8 @@ function isExternalDirectCall (node) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function isNowAccess (node) {
return nodeType(node, exactMatch(nodeTypes.IDENTIFIER)) &&
expressionType(node, exactMatch(basicTypes.UINT)) &&
memName(node, exactMatch('now'))
function isNowAccess (node: IdentifierAstNode) {
return node.name === "now" && typeDescription(node, exactMatch(basicTypes.UINT))
}
/**
@ -746,7 +742,7 @@ function isNowAccess (node) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function isBlockTimestampAccess (node) {
function isBlockTimestampAccess (node: MemberAccessAstNode) {
return isSpecialVariableAccess(node, specialVariables.BLOCKTIMESTAMP)
}
@ -755,7 +751,7 @@ function isBlockTimestampAccess (node) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function isBlockBlockHashAccess (node) {
function isBlockBlockHashAccess (node: MemberAccessAstNode) {
return isSpecialVariableAccess(node, specialVariables.BLOCKHASH) || isBuiltinFunctionCall(node) && getLocalCallName(node) === 'blockhash'
}
@ -764,7 +760,7 @@ function isBlockBlockHashAccess (node) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function isThisLocalCall (node) {
function isThisLocalCall (node: MemberAccessAstNode) {
return isMemberAccess(node, basicRegex.FUNCTIONTYPE, exactMatch('this'), basicRegex.CONTRACTTYPE, undefined)
}
@ -773,7 +769,7 @@ function isThisLocalCall (node) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function isSuperLocalCall (node) {
function isSuperLocalCall (node: MemberAccessAstNode) {
return isMemberAccess(node, basicRegex.FUNCTIONTYPE, exactMatch('super'), basicRegex.CONTRACTTYPE, undefined)
}
@ -782,13 +778,11 @@ function isSuperLocalCall (node) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function isLocalCall (node) {
return nodeType(node, exactMatch(nodeTypes.FUNCTIONCALL)) &&
minNrOfChildren(node, 1) &&
nodeType(node.children[0], exactMatch(nodeTypes.IDENTIFIER)) &&
expressionType(node.children[0], basicRegex.FUNCTIONTYPE) &&
!expressionType(node.children[0], basicRegex.EXTERNALFUNCTIONTYPE) &&
nrOfChildren(node.children[0], 0)
function isLocalCall (node: FunctionCallAstNode) {
return node.kind === 'functionCall' &&
node.expression.nodeType === 'Identifier' &&
expressionTypeDescription(node, basicRegex.FUNCTIONTYPE) &&
!expressionTypeDescription(node, basicRegex.FUNCTIONTYPE)
}
/**
@ -811,7 +805,7 @@ function isLowLevelCall (node) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function isLLSend050 (node) {
function isLLSend050 (node: MemberAccessAstNode) {
return isMemberAccess(node,
exactMatch(util.escapeRegExp(lowLevelCallTypes.SEND.type)),
undefined, exactMatch(basicTypes.PAYABLE_ADDRESS), exactMatch(lowLevelCallTypes.SEND.ident))
@ -822,7 +816,7 @@ function isLLSend050 (node) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function isLLSend (node) {
function isLLSend (node: MemberAccessAstNode) {
return isMemberAccess(node,
exactMatch(util.escapeRegExp(lowLevelCallTypes.SEND.type)),
undefined, exactMatch(basicTypes.ADDRESS), exactMatch(lowLevelCallTypes.SEND.ident))
@ -833,7 +827,7 @@ function isLLSend (node) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function isLLCall (node) {
function isLLCall (node: MemberAccessAstNode) {
return isMemberAccess(node,
exactMatch(util.escapeRegExp(lowLevelCallTypes.CALL.type)),
undefined, exactMatch(basicTypes.ADDRESS), exactMatch(lowLevelCallTypes.CALL.ident))
@ -844,7 +838,7 @@ function isLLCall (node) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function isLLCall050 (node) {
function isLLCall050 (node: MemberAccessAstNode) {
return isMemberAccess(node,
exactMatch(util.escapeRegExp(lowLevelCallTypes['CALL-v0.5'].type)),
undefined, exactMatch(basicTypes.PAYABLE_ADDRESS), exactMatch(lowLevelCallTypes['CALL-v0.5'].ident))
@ -855,7 +849,7 @@ function isLLCall050 (node) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function isLLCallcode (node) {
function isLLCallcode (node: MemberAccessAstNode) {
return isMemberAccess(node,
exactMatch(util.escapeRegExp(lowLevelCallTypes.CALLCODE.type)),
undefined, exactMatch(basicTypes.ADDRESS), exactMatch(lowLevelCallTypes.CALLCODE.ident))
@ -866,7 +860,7 @@ function isLLCallcode (node) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function isLLDelegatecall (node) {
function isLLDelegatecall (node: MemberAccessAstNode) {
return isMemberAccess(node,
exactMatch(util.escapeRegExp(lowLevelCallTypes.DELEGATECALL.type)),
undefined, exactMatch(basicTypes.ADDRESS), exactMatch(lowLevelCallTypes.DELEGATECALL.ident))
@ -877,7 +871,7 @@ function isLLDelegatecall (node) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function isLLDelegatecall050 (node) {
function isLLDelegatecall050 (node: MemberAccessAstNode) {
return isMemberAccess(node,
exactMatch(util.escapeRegExp(lowLevelCallTypes['DELEGATECALL-v0.5'].type)),
undefined, matches(basicTypes.PAYABLE_ADDRESS, basicTypes.ADDRESS), exactMatch(lowLevelCallTypes['DELEGATECALL-v0.5'].ident))
@ -888,7 +882,7 @@ function isLLDelegatecall050 (node) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function isTransfer (node) {
function isTransfer (node: MemberAccessAstNode) {
return isMemberAccess(node,
exactMatch(util.escapeRegExp(lowLevelCallTypes.TRANSFER.type)),
undefined, matches(basicTypes.ADDRESS, basicTypes.PAYABLE_ADDRESS), exactMatch(lowLevelCallTypes.TRANSFER.ident))
@ -898,13 +892,13 @@ function isStringToBytesConversion (node) {
return isExplicitCast(node, util.escapeRegExp('string *'), util.escapeRegExp('bytes'))
}
function isExplicitCast (node, castFromType, castToType) {
return nodeType(node, exactMatch(nodeTypes.FUNCTIONCALL)) && nrOfChildren(node, 2) &&
nodeType(node.children[0], exactMatch(nodeTypes.ELEMENTARYTYPENAMEEXPRESSION)) && memName(node.children[0], castToType) &&
nodeType(node.children[1], exactMatch(nodeTypes.IDENTIFIER)) && expressionType(node.children[1], castFromType)
function isExplicitCast (node: FunctionCallAstNode, castFromType: string, castToType: string) {
return node.kind === "typeConversion" &&
nodeType(node.expression, exactMatch(nodeTypes.ELEMENTARYTYPENAMEEXPRESSION)) && node.expression.typeName.name === castToType &&
nodeType(node.arguments[0], exactMatch(nodeTypes.IDENTIFIER)) && typeDescription(node.arguments[0], castFromType)
}
function isBytesLengthCheck (node) {
function isBytesLengthCheck (node: MemberAccessAstNode) {
return isMemberAccess(node, exactMatch(util.escapeRegExp(basicTypes.UINT)), undefined, util.escapeRegExp('bytes *'), 'length')
}
@ -925,41 +919,48 @@ function isBytesLengthCheck (node) {
* @return {bool}
* TODO: This should be removed once for loop iterates Over dynamic array fixed
*/
function isForLoop (node) {
return nodeType(node, exactMatch(nodeTypes.FORSTATEMENT))
}
// function isForLoop (node) {
// return nodeType(node, exactMatch(nodeTypes.FORSTATEMENT))
// }
// #################### Complex Node Identification - Private
function isMemberAccess (node: MemberAccessAstNode, retType, accessor, accessorType, memberName) {
function isMemberAccess (node: MemberAccessAstNode, retType: string, accessor: string| undefined, accessorType, memberName: string | undefined) {
return nodeType(node, exactMatch(nodeTypes.MEMBERACCESS)) &&
expressionType(node, retType) &&
memName(node, memberName) &&
nrOfChildren(node, 1) &&
memName(node.expression, accessor) &&
expressionType(node.expression, accessorType)
}
function isSpecialVariableAccess (node, varType) {
function isSpecialVariableAccess (node: MemberAccessAstNode, varType) {
return isMemberAccess(node, exactMatch(util.escapeRegExp(varType.type)), varType.obj, varType.obj, varType.member)
}
// #################### Node Identification Primitives
function nrOfChildren (node, nr) {
return (node && (nr === undefined || nr === null)) || (node && nr === 0 && !node.children) || (node && node.children && node.children.length === nr)
// function nrOfChildren (node, nr) {
// return (node && (nr === undefined || nr === null)) || (node && nr === 0 && !node.children) || (node && node.children && node.children.length === nr)
// }
// function minNrOfChildren (node, nr) {
// return (node && (nr === undefined || nr === null)) || (node && nr === 0 && !node.children) || (node && node.children && node.children.length >= nr)
// }
function expressionType (node, typeRegex) {
return new RegExp(typeRegex).test(node.expression.typeDescriptions.typeString)
}
function minNrOfChildren (node, nr) {
return (node && (nr === undefined || nr === null)) || (node && nr === 0 && !node.children) || (node && node.children && node.children.length >= nr)
function expressionTypeDescription (node, typeRegex) {
return new RegExp(typeRegex).test(node.expression.typeDescriptions.typeString)
}
function expressionType (node, typeRegex) {
return (node && !typeRegex) || (node && node.attributes && new RegExp(typeRegex).test(node.attributes.type))
function typeDescription (node, typeRegex) {
return new RegExp(typeRegex).test(node.typeDescriptions.typeString)
}
function nodeType (node, typeRegex) {
return (node && !typeRegex) || (node && new RegExp(typeRegex).test(node.name))
return new RegExp(typeRegex).test(node.nodeType)
}
function memName (node, memNameRegex) {
@ -968,7 +969,7 @@ function memName (node, memNameRegex) {
}
function operator (node, opRegex) {
return (node && !opRegex) || (node && new RegExp(opRegex).test(node.attributes.operator))
return new RegExp(opRegex).test(node.operator)
}
// #################### Helpers
@ -1021,8 +1022,8 @@ function findFirstSubNodeLTR (node, type) {
}
const helpers = {
nrOfChildren,
minNrOfChildren,
// nrOfChildren,
// minNrOfChildren,
expressionType,
nodeType,
memName,
@ -1104,7 +1105,7 @@ export {
isIntDivision,
isStringToBytesConversion,
isBytesLengthCheck,
isForLoop,
// isForLoop,
// #################### Trivial Node Identification
isDeleteUnaryOperation,

@ -1,16 +1,16 @@
import { default as category } from './categories'
import { isThisLocalCall } from './staticAnalysisCommon'
import { default as algorithm } from './algorithmCategories'
import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, AstNodeLegacy, CompilationResult} from './../../types'
import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, AstNodeLegacy, CompilationResult, MemberAccessAstNode} from './../../types'
export default class thisLocal implements AnalyzerModule {
warningNodes: AstNodeLegacy[] = []
warningNodes: MemberAccessAstNode[] = []
name: string = 'This on local calls: '
description: string = 'Invocation of local functions via this'
category: ModuleCategory = category.GAS
algorithm: ModuleAlgorithm = algorithm.EXACT
visit (node: AstNodeLegacy): void {
visit (node: MemberAccessAstNode): void {
if (isThisLocalCall(node)) this.warningNodes.push(node)
}

@ -337,7 +337,7 @@ export interface WhileStatementAstNode {
id: number
nodeType: 'WhileStatement' | 'DoWhileStatement'
src: string
condition: object
condition: any
body: BlockAstNode
}
@ -346,7 +346,7 @@ export interface ForStatementAstNode {
nodeType: 'ForStatement'
src: string
initializationExpression: VariableDeclarationStatementAstNode
condition: object
condition: any
loopExpression: ExpressionStatementAstNode
body: BlockAstNode
}
@ -397,7 +397,7 @@ export interface ExpressionStatementAstNode {
id: number
nodeType: 'ExpressionStatement'
src: string
expression: object
expression: any
}
interface ExpressionAttributes {
@ -441,7 +441,7 @@ export interface UnaryOperationAstNode extends ExpressionAttributes {
src: string
prefix: boolean
operator: string
subExpression: object
subExpression: any
}
export interface BinaryOperationAstNode extends ExpressionAttributes {
@ -458,7 +458,7 @@ export interface FunctionCallAstNode extends ExpressionAttributes {
id: number
nodeType: 'FunctionCall'
src: string
expression: object
expression: any
names: Array<any>
arguments: object
tryCall: boolean
@ -481,10 +481,8 @@ export interface NewExpressionAstNode extends ExpressionAttributes {
typeName: UserDefinedTypeNameAstNode | ElementaryTypeNameAstNode
}
export interface MemberAccessAstNode extends ExpressionAttributes {
id: number
export interface MemberAccessAstNode extends CommonAstNode, ExpressionAttributes {
nodeType: 'MemberAccess'
src: string
memberName: string
expression: object
referencedDeclaration: number | null

Loading…
Cancel
Save