Commit 83788eae authored by Iuri Matias's avatar Iuri Matias

update remix-analyzer syntax to use const, let and this

parent 89ad1dcd
var common = require('./staticAnalysisCommon') const common = require('./staticAnalysisCommon')
var AstWalker = require('remix-lib').AstWalker const AstWalker = require('remix-lib').AstWalker
function abstractAstView () { function abstractAstView () {
this.contracts = [] this.contracts = []
...@@ -56,8 +56,8 @@ abstractAstView.prototype.build_visit = function (relevantNodeFilter) { ...@@ -56,8 +56,8 @@ abstractAstView.prototype.build_visit = function (relevantNodeFilter) {
stateVariables: common.getStateVariableDeclarationsFormContractNode(node) stateVariables: common.getStateVariableDeclarationsFormContractNode(node)
}) })
} else if (common.isInheritanceSpecifier(node)) { } else if (common.isInheritanceSpecifier(node)) {
var currentContract = getCurrentContract(that) const currentContract = getCurrentContract(that)
var inheritsFromName = common.getInheritsFromName(node) const inheritsFromName = common.getInheritsFromName(node)
currentContract.inheritsFrom.push(inheritsFromName) currentContract.inheritsFrom.push(inheritsFromName)
} else if (common.isFunctionDefinition(node)) { } else if (common.isFunctionDefinition(node)) {
setCurrentFunction(that, { setCurrentFunction(that, {
...@@ -85,7 +85,7 @@ abstractAstView.prototype.build_visit = function (relevantNodeFilter) { ...@@ -85,7 +85,7 @@ abstractAstView.prototype.build_visit = function (relevantNodeFilter) {
if (!that.isFunctionNotModifier) throw new Error('abstractAstView.js: Found modifier invocation outside of function scope.') if (!that.isFunctionNotModifier) throw new Error('abstractAstView.js: Found modifier invocation outside of function scope.')
getCurrentFunction(that).modifierInvocations.push(node) getCurrentFunction(that).modifierInvocations.push(node)
} else if (relevantNodeFilter(node)) { } else if (relevantNodeFilter(node)) {
var scope = (that.isFunctionNotModifier) ? getCurrentFunction(that) : getCurrentModifier(that) let scope = (that.isFunctionNotModifier) ? getCurrentFunction(that) : getCurrentModifier(that)
if (scope) { if (scope) {
scope.relevantNodes.push(node) scope.relevantNodes.push(node)
} else { } else {
...@@ -111,10 +111,11 @@ function resolveStateVariablesInHierarchy (contracts) { ...@@ -111,10 +111,11 @@ function resolveStateVariablesInHierarchy (contracts) {
resolveStateVariablesInHierarchyForContract(c, contracts) resolveStateVariablesInHierarchyForContract(c, contracts)
}) })
} }
function resolveStateVariablesInHierarchyForContract (currentContract, contracts) { function resolveStateVariablesInHierarchyForContract (currentContract, contracts) {
currentContract.inheritsFrom.map((inheritsFromName) => { currentContract.inheritsFrom.map((inheritsFromName) => {
// add variables from inherited contracts // add variables from inherited contracts
var inheritsFrom = contracts.find((contract) => common.getContractName(contract.node) === inheritsFromName) const inheritsFrom = contracts.find((contract) => common.getContractName(contract.node) === inheritsFromName)
if (inheritsFrom) { if (inheritsFrom) {
currentContract.stateVariables = currentContract.stateVariables.concat(inheritsFrom.stateVariables) currentContract.stateVariables = currentContract.stateVariables.concat(inheritsFrom.stateVariables)
} else { } else {
...@@ -122,8 +123,9 @@ function resolveStateVariablesInHierarchyForContract (currentContract, contracts ...@@ -122,8 +123,9 @@ function resolveStateVariablesInHierarchyForContract (currentContract, contracts
} }
}) })
} }
function setCurrentContract (that, contract) { function setCurrentContract (that, contract) {
var name = common.getContractName(contract.node) const name = common.getContractName(contract.node)
if (that.contracts.map((c) => common.getContractName(c.node)).filter((n) => n === name).length > 0) { if (that.contracts.map((c) => common.getContractName(c.node)).filter((n) => n === name).length > 0) {
console.log('abstractAstView.js: two or more contracts with the same name dectected, import aliases not supported at the moment') console.log('abstractAstView.js: two or more contracts with the same name dectected, import aliases not supported at the moment')
that.multipleContractsWithSameName = true that.multipleContractsWithSameName = true
...@@ -167,7 +169,7 @@ function getReturnParameters (funcNode) { ...@@ -167,7 +169,7 @@ function getReturnParameters (funcNode) {
} }
function getLocalVariables (funcNode) { function getLocalVariables (funcNode) {
var locals = [] const locals = []
new AstWalker().walk(funcNode, {'*': function (node) { new AstWalker().walk(funcNode, {'*': function (node) {
if (common.isVariableDeclaration(node)) locals.push(node) if (common.isVariableDeclaration(node)) locals.push(node)
return true return true
......
var name = 'Result not used: ' const name = 'Result not used: '
var desc = 'The result of an operation was not used.' const desc = 'The result of an operation was not used.'
var categories = require('./categories') const categories = require('./categories')
var common = require('./staticAnalysisCommon') const common = require('./staticAnalysisCommon')
var algo = require('./algorithmCategories') const algo = require('./algorithmCategories')
function assignAndCompare () { function assignAndCompare () {
this.warningNodes = [] this.warningNodes = []
...@@ -13,7 +13,7 @@ assignAndCompare.prototype.visit = function (node) { ...@@ -13,7 +13,7 @@ assignAndCompare.prototype.visit = function (node) {
} }
assignAndCompare.prototype.report = function (compilationResults) { assignAndCompare.prototype.report = function (compilationResults) {
return this.warningNodes.map(function (item, i) { return this.warningNodes.map((item, i) => {
return { return {
warning: 'A binary operation yields a value that is not used in the following. This is often caused by confusing assignment (=) and comparison (==).', warning: 'A binary operation yields a value that is not used in the following. This is often caused by confusing assignment (=) and comparison (==).',
location: item.src location: item.src
......
var name = 'Block.blockhash usage: ' const name = 'Block.blockhash usage: '
var desc = 'Semantics maybe unclear' const desc = 'Semantics maybe unclear'
var categories = require('./categories') const categories = require('./categories')
var common = require('./staticAnalysisCommon') const common = require('./staticAnalysisCommon')
var algo = require('./algorithmCategories') const algo = require('./algorithmCategories')
function blockBlockhash () { function blockBlockhash () {
this.warningNodes = [] this.warningNodes = []
...@@ -13,7 +13,7 @@ blockBlockhash.prototype.visit = function (node) { ...@@ -13,7 +13,7 @@ blockBlockhash.prototype.visit = function (node) {
} }
blockBlockhash.prototype.report = function (compilationResults) { blockBlockhash.prototype.report = function (compilationResults) {
return this.warningNodes.map(function (item, i) { return this.warningNodes.map((item, i) => {
return { return {
warning: `use of "block.blockhash": "block.blockhash" is used to access the last 256 block hashes. warning: `use of "block.blockhash": "block.blockhash" is used to access the last 256 block hashes.
A miner computes the block hash by "summing up" the information in the current block mined. A miner computes the block hash by "summing up" the information in the current block mined.
......
var name = 'Block timestamp: ' const name = 'Block timestamp: '
var desc = 'Semantics maybe unclear' const desc = 'Semantics maybe unclear'
var categories = require('./categories') const categories = require('./categories')
var common = require('./staticAnalysisCommon') const common = require('./staticAnalysisCommon')
var algo = require('./algorithmCategories') const algo = require('./algorithmCategories')
function blockTimestamp () { function blockTimestamp () {
this.warningNowNodes = [] this.warningNowNodes = []
...@@ -15,14 +15,14 @@ blockTimestamp.prototype.visit = function (node) { ...@@ -15,14 +15,14 @@ blockTimestamp.prototype.visit = function (node) {
} }
blockTimestamp.prototype.report = function (compilationResults) { blockTimestamp.prototype.report = function (compilationResults) {
return this.warningNowNodes.map(function (item, i) { return this.warningNowNodes.map((item, i) => {
return { return {
warning: `use of "now": "now" does not mean current time. Now is an alias for block.timestamp. warning: `use of "now": "now" does not mean current time. Now is an alias for block.timestamp.
Block.timestamp can be influenced by miners to a certain degree, be careful.`, Block.timestamp can be influenced by miners to a certain degree, be careful.`,
location: item.src, location: item.src,
more: 'http://solidity.readthedocs.io/en/develop/frequently-asked-questions.html#are-timestamps-now-block-timestamp-reliable' more: 'http://solidity.readthedocs.io/en/develop/frequently-asked-questions.html#are-timestamps-now-block-timestamp-reliable'
} }
}).concat(this.warningblockTimestampNodes.map(function (item, i) { }).concat(this.warningblockTimestampNodes.map((item, i) => {
return { return {
warning: `use of "block.timestamp": "block.timestamp" can be influenced by miners to a certain degree. warning: `use of "block.timestamp": "block.timestamp" can be influenced by miners to a certain degree.
That means that a miner can "choose" the block.timestamp, to a certain degree, to change the outcome of a transaction in the mined block.`, That means that a miner can "choose" the block.timestamp, to a certain degree, to change the outcome of a transaction in the mined block.`,
......
var name = 'Check effects: ' const name = 'Check effects: '
var desc = 'Avoid potential reentrancy bugs' const desc = 'Avoid potential reentrancy bugs'
var categories = require('./categories') const categories = require('./categories')
var common = require('./staticAnalysisCommon') const common = require('./staticAnalysisCommon')
var fcallGraph = require('./functionCallGraph') const fcallGraph = require('./functionCallGraph')
var AbstractAst = require('./abstractAstView') const AbstractAst = require('./abstractAstView')
var algo = require('./algorithmCategories') const algo = require('./algorithmCategories')
function checksEffectsInteraction () { function checksEffectsInteraction () {
this.abstractAst = new AbstractAst() this.abstractAst = new AbstractAst()
...@@ -20,10 +20,10 @@ checksEffectsInteraction.prototype.visit = function () { throw new Error('checks ...@@ -20,10 +20,10 @@ checksEffectsInteraction.prototype.visit = function () { throw new Error('checks
checksEffectsInteraction.prototype.report = function () { throw new Error('checksEffectsInteraction.js no report function set upon construction') } checksEffectsInteraction.prototype.report = function () { throw new Error('checksEffectsInteraction.js no report function set upon construction') }
function report (contracts, multipleContractsWithSameName) { function report (contracts, multipleContractsWithSameName) {
var warnings = [] const warnings = []
var hasModifiers = contracts.some((item) => item.modifiers.length > 0) const hasModifiers = contracts.some((item) => item.modifiers.length > 0)
var callGraph = fcallGraph.buildGlobalFuncCallGraph(contracts) const callGraph = fcallGraph.buildGlobalFuncCallGraph(contracts)
contracts.forEach((contract) => { contracts.forEach((contract) => {
contract.functions.forEach((func) => { contract.functions.forEach((func) => {
...@@ -33,8 +33,8 @@ function report (contracts, multipleContractsWithSameName) { ...@@ -33,8 +33,8 @@ function report (contracts, multipleContractsWithSameName) {
contract.functions.forEach((func) => { contract.functions.forEach((func) => {
if (isPotentialVulnerableFunction(func, getContext(callGraph, contract, func))) { if (isPotentialVulnerableFunction(func, getContext(callGraph, contract, func))) {
var funcName = common.getFullQuallyfiedFuncDefinitionIdent(contract.node, func.node, func.parameters) const funcName = common.getFullQuallyfiedFuncDefinitionIdent(contract.node, func.node, func.parameters)
var comments = (hasModifiers) ? 'Note: Modifiers are currently not considered by this static analysis.' : '' let comments = (hasModifiers) ? 'Note: Modifiers are currently not considered by this static analysis.' : ''
comments += (multipleContractsWithSameName) ? 'Note: Import aliases are currently not supported by this static analysis.' : '' comments += (multipleContractsWithSameName) ? 'Note: Import aliases are currently not supported by this static analysis.' : ''
warnings.push({ warnings.push({
warning: `Potential Violation of Checks-Effects-Interaction pattern in ${funcName}: Could potentially lead to re-entrancy vulnerability. ${comments}`, warning: `Potential Violation of Checks-Effects-Interaction pattern in ${funcName}: Could potentially lead to re-entrancy vulnerability. ${comments}`,
...@@ -57,8 +57,8 @@ function getStateVariables (contract, func) { ...@@ -57,8 +57,8 @@ function getStateVariables (contract, func) {
} }
function isPotentialVulnerableFunction (func, context) { function isPotentialVulnerableFunction (func, context) {
var isPotentialVulnerable = false let isPotentialVulnerable = false
var interaction = false let interaction = false
func.relevantNodes.forEach((node) => { func.relevantNodes.forEach((node) => {
if (common.isInteraction(node)) { if (common.isInteraction(node)) {
interaction = true interaction = true
...@@ -71,7 +71,7 @@ function isPotentialVulnerableFunction (func, context) { ...@@ -71,7 +71,7 @@ function isPotentialVulnerableFunction (func, context) {
function isLocalCallWithStateChange (node, context) { function isLocalCallWithStateChange (node, context) {
if (common.isLocalCallGraphRelevantNode(node)) { if (common.isLocalCallGraphRelevantNode(node)) {
var func = fcallGraph.resolveCallGraphSymbol(context.callGraph, common.getFullQualifiedFunctionCallIdent(context.currentContract.node, node)) const func = fcallGraph.resolveCallGraphSymbol(context.callGraph, common.getFullQualifiedFunctionCallIdent(context.currentContract.node, node))
return !func || (func && func.node.changesState) return !func || (func && func.node.changesState)
} }
return false return false
......
var name = 'Constant functions: ' const name = 'Constant functions: '
var desc = 'Check for potentially constant functions' const desc = 'Check for potentially constant functions'
var categories = require('./categories') const categories = require('./categories')
var common = require('./staticAnalysisCommon') const common = require('./staticAnalysisCommon')
var fcallGraph = require('./functionCallGraph') const fcallGraph = require('./functionCallGraph')
var AbstractAst = require('./abstractAstView') const AbstractAst = require('./abstractAstView')
var algo = require('./algorithmCategories') const algo = require('./algorithmCategories')
function constantFunctions () { function constantFunctions () {
this.abstractAst = new AbstractAst() this.abstractAst = new AbstractAst()
...@@ -29,10 +29,10 @@ constantFunctions.prototype.visit = function () { throw new Error('constantFunct ...@@ -29,10 +29,10 @@ constantFunctions.prototype.visit = function () { throw new Error('constantFunct
constantFunctions.prototype.report = function () { throw new Error('constantFunctions.js no report function set upon construction') } constantFunctions.prototype.report = function () { throw new Error('constantFunctions.js no report function set upon construction') }
function report (contracts, multipleContractsWithSameName) { function report (contracts, multipleContractsWithSameName) {
var warnings = [] const warnings = []
var hasModifiers = contracts.some((item) => item.modifiers.length > 0) const hasModifiers = contracts.some((item) => item.modifiers.length > 0)
var callGraph = fcallGraph.buildGlobalFuncCallGraph(contracts) const callGraph = fcallGraph.buildGlobalFuncCallGraph(contracts)
contracts.forEach((contract) => { contracts.forEach((contract) => {
contract.functions.forEach((func) => { contract.functions.forEach((func) => {
...@@ -46,8 +46,8 @@ function report (contracts, multipleContractsWithSameName) { ...@@ -46,8 +46,8 @@ function report (contracts, multipleContractsWithSameName) {
contract.functions.filter((func) => common.hasFunctionBody(func.node)).forEach((func) => { contract.functions.filter((func) => common.hasFunctionBody(func.node)).forEach((func) => {
if (common.isConstantFunction(func.node) !== func.potentiallyshouldBeConst) { if (common.isConstantFunction(func.node) !== func.potentiallyshouldBeConst) {
var funcName = common.getFullQuallyfiedFuncDefinitionIdent(contract.node, func.node, func.parameters) const funcName = common.getFullQuallyfiedFuncDefinitionIdent(contract.node, func.node, func.parameters)
var comments = (hasModifiers) ? 'Note: Modifiers are currently not considered by this static analysis.' : '' let comments = (hasModifiers) ? 'Note: Modifiers are currently not considered by this static analysis.' : ''
comments += (multipleContractsWithSameName) ? 'Note: Import aliases are currently not supported by this static analysis.' : '' comments += (multipleContractsWithSameName) ? 'Note: Import aliases are currently not supported by this static analysis.' : ''
if (func.potentiallyshouldBeConst) { if (func.potentiallyshouldBeConst) {
warnings.push({ warnings.push({
...@@ -95,7 +95,7 @@ function isConstBreaker (node, context) { ...@@ -95,7 +95,7 @@ function isConstBreaker (node, context) {
function isCallOnNonConstExternalInterfaceFunction (node, context) { function isCallOnNonConstExternalInterfaceFunction (node, context) {
if (common.isExternalDirectCall(node)) { if (common.isExternalDirectCall(node)) {
var func = fcallGraph.resolveCallGraphSymbol(context.callGraph, common.getFullQualifiedFunctionCallIdent(context.currentContract, node)) const func = fcallGraph.resolveCallGraphSymbol(context.callGraph, common.getFullQualifiedFunctionCallIdent(context.currentContract, node))
return !func || (func && !common.isConstantFunction(func.node.node)) return !func || (func && !common.isConstantFunction(func.node.node))
} }
return false return false
......
var name = 'Delete on dynamic Array: ' const name = 'Delete on dynamic Array: '
var desc = 'Use require and appropriately' const desc = 'Use require and appropriately'
var categories = require('./categories') const categories = require('./categories')
var common = require('./staticAnalysisCommon') const common = require('./staticAnalysisCommon')
var algo = require('./algorithmCategories') const algo = require('./algorithmCategories')
function deleteDynamicArrays () { function deleteDynamicArrays () {
this.rel = [] this.rel = []
......
var name = 'Delete from dynamic Array: ' const name = 'Delete from dynamic Array: '
var desc = 'Using delete on an array leaves a gap' const desc = 'Using delete on an array leaves a gap'
var categories = require('./categories') const categories = require('./categories')
var common = require('./staticAnalysisCommon') const common = require('./staticAnalysisCommon')
function deleteFromDynamicArray () { function deleteFromDynamicArray () {
this.relevantNodes = [] this.relevantNodes = []
......
var name = 'ERC20: ' const name = 'ERC20: '
var desc = 'Decimal should be uint8' const desc = 'Decimal should be uint8'
var categories = require('./categories') const categories = require('./categories')
var common = require('./staticAnalysisCommon') const common = require('./staticAnalysisCommon')
var AbstractAst = require('./abstractAstView') const AbstractAst = require('./abstractAstView')
var algo = require('./algorithmCategories') const algo = require('./algorithmCategories')
function erc20Decimals () { function erc20Decimals () {
this.abstractAst = new AbstractAst() this.abstractAst = new AbstractAst()
...@@ -18,14 +18,14 @@ erc20Decimals.prototype.visit = function () { throw new Error('erc20Decimals.js ...@@ -18,14 +18,14 @@ erc20Decimals.prototype.visit = function () { throw new Error('erc20Decimals.js
erc20Decimals.prototype.report = function () { throw new Error('erc20Decimals.js no report function set upon construction') } erc20Decimals.prototype.report = function () { throw new Error('erc20Decimals.js no report function set upon construction') }
function report (contracts, multipleContractsWithSameName) { function report (contracts, multipleContractsWithSameName) {
var warnings = [] const warnings = []
contracts.forEach((contract) => { contracts.forEach((contract) => {
let contractAbiSignatures = contract.functions.map((f) => common.helpers.buildAbiSignature(common.getFunctionDefinitionName(f.node), f.parameters)) const contractAbiSignatures = contract.functions.map((f) => common.helpers.buildAbiSignature(common.getFunctionDefinitionName(f.node), f.parameters))
if (isERC20(contractAbiSignatures)) { if (isERC20(contractAbiSignatures)) {
let decimalsVar = contract.stateVariables.filter((stateVar) => common.getDeclaredVariableName(stateVar) === 'decimals' && (common.getDeclaredVariableType(stateVar) !== 'uint8' || stateVar.attributes.visibility !== 'public')) const decimalsVar = contract.stateVariables.filter((stateVar) => common.getDeclaredVariableName(stateVar) === 'decimals' && (common.getDeclaredVariableType(stateVar) !== 'uint8' || stateVar.attributes.visibility !== 'public'))
let decimalsFun = contract.functions.filter((f) => common.getFunctionDefinitionName(f.node) === 'decimals' && const decimalsFun = contract.functions.filter((f) => common.getFunctionDefinitionName(f.node) === 'decimals' &&
( (
(f.returns.length === 0 || f.returns.length > 1) || (f.returns.length === 0 || f.returns.length > 1) ||
(f.returns.length === 1 && (f.returns[0].type !== 'uint8' || f.node.attributes.visibility !== 'public')) (f.returns.length === 1 && (f.returns[0].type !== 'uint8' || f.node.attributes.visibility !== 'public'))
......
var name = 'Ether transfer in a loop: ' const name = 'Ether transfer in a loop: '
var desc = 'Avoid transferring Ether to multiple addresses in a loop' const desc = 'Avoid transferring Ether to multiple addresses in a loop'
var categories = require('./categories') const categories = require('./categories')
var common = require('./staticAnalysisCommon') const common = require('./staticAnalysisCommon')
function etherTransferInLoop () { function etherTransferInLoop () {
this.relevantNodes = [] this.relevantNodes = []
...@@ -9,8 +9,8 @@ function etherTransferInLoop () { ...@@ -9,8 +9,8 @@ function etherTransferInLoop () {
etherTransferInLoop.prototype.visit = function (node) { etherTransferInLoop.prototype.visit = function (node) {
if (common.isLoop(node)) { if (common.isLoop(node)) {
var transferNodes = [] let transferNodes = []
var loopBlockStartIndex = common.getLoopBlockStartIndex(node) const loopBlockStartIndex = common.getLoopBlockStartIndex(node)
if (common.isBlock(node.children[loopBlockStartIndex])) { if (common.isBlock(node.children[loopBlockStartIndex])) {
transferNodes = node.children[loopBlockStartIndex].children transferNodes = node.children[loopBlockStartIndex].children
.filter(child => (common.isExpressionStatement(child) && .filter(child => (common.isExpressionStatement(child) &&
......
var name = 'For loop iterates over dynamic array: ' const name = 'For loop iterates over dynamic array: '
var desc = 'The number of \'for\' loop iterations depends on dynamic array\'s size' const desc = 'The number of \'for\' loop iterations depends on dynamic array\'s size'
var categories = require('./categories') const categories = require('./categories')
var { isForLoop, isDynamicArrayLengthAccess, isBinaryOperation } = require('./staticAnalysisCommon') const { isForLoop, isDynamicArrayLengthAccess, isBinaryOperation } = require('./staticAnalysisCommon')
function forLoopIteratesOverDynamicArray () { function forLoopIteratesOverDynamicArray () {
this.relevantNodes = [] this.relevantNodes = []
...@@ -10,9 +10,9 @@ function forLoopIteratesOverDynamicArray () { ...@@ -10,9 +10,9 @@ function forLoopIteratesOverDynamicArray () {
forLoopIteratesOverDynamicArray.prototype.visit = function (node) { forLoopIteratesOverDynamicArray.prototype.visit = function (node) {
if (isForLoop(node)) { if (isForLoop(node)) {
// Access 'condition' node of 'for' loop statement // Access 'condition' node of 'for' loop statement
let forLoopConditionNode = node.children[1] const forLoopConditionNode = node.children[1]
// Access right side of condition as its children // Access right side of condition as its children
let conditionChildrenNode = forLoopConditionNode.children[1] const conditionChildrenNode = forLoopConditionNode.children[1]
// Check if it is a binary operation. if yes, check if its children node access length of dynamic array // Check if it is a binary operation. if yes, check if its children node access length of dynamic array
if (isBinaryOperation(conditionChildrenNode) && isDynamicArrayLengthAccess(conditionChildrenNode.children[0])) { if (isBinaryOperation(conditionChildrenNode) && isDynamicArrayLengthAccess(conditionChildrenNode.children[0])) {
this.relevantNodes.push(node) this.relevantNodes.push(node)
......
'use strict' 'use strict'
var common = require('./staticAnalysisCommon') const common = require('./staticAnalysisCommon')
function buildLocalFuncCallGraphInternal (functions, nodeFilter, extractNodeIdent, extractFuncDefIdent) { function buildLocalFuncCallGraphInternal (functions, nodeFilter, extractNodeIdent, extractFuncDefIdent) {
var callGraph = {} const callGraph = {}
functions.forEach((func) => { functions.forEach((func) => {
var calls = func.relevantNodes const calls = func.relevantNodes
.filter(nodeFilter) .filter(nodeFilter)
.map(extractNodeIdent) .map(extractNodeIdent)
.filter((name) => name !== extractFuncDefIdent(func)) // filter self recursive call .filter((name) => name !== extractFuncDefIdent(func)) // filter self recursive call
...@@ -41,11 +41,11 @@ function buildLocalFuncCallGraphInternal (functions, nodeFilter, extractNodeIden ...@@ -41,11 +41,11 @@ function buildLocalFuncCallGraphInternal (functions, nodeFilter, extractNodeIden
* @return {map (string -> Contract Call Graph)} returns map from contract name to contract call graph * @return {map (string -> Contract Call Graph)} returns map from contract name to contract call graph
*/ */
function buildGlobalFuncCallGraph (contracts) { function buildGlobalFuncCallGraph (contracts) {
var callGraph = {} const callGraph = {}
contracts.forEach((contract) => { contracts.forEach((contract) => {
var filterNodes = (node) => { return common.isLocalCallGraphRelevantNode(node) || common.isExternalDirectCall(node) } const filterNodes = (node) => { return common.isLocalCallGraphRelevantNode(node) || common.isExternalDirectCall(node) }
var getNodeIdent = (node) => { return common.getFullQualifiedFunctionCallIdent(contract.node, node) } const getNodeIdent = (node) => { return common.getFullQualifiedFunctionCallIdent(contract.node, node) }
var getFunDefIdent = (funcDef) => { return common.getFullQuallyfiedFuncDefinitionIdent(contract.node, funcDef.node, funcDef.parameters) } const getFunDefIdent = (funcDef) => { return common.getFullQuallyfiedFuncDefinitionIdent(contract.node, funcDef.node, funcDef.parameters) }
callGraph[common.getContractName(contract.node)] = { contract: contract, functions: buildLocalFuncCallGraphInternal(contract.functions, filterNodes, getNodeIdent, getFunDefIdent) } callGraph[common.getContractName(contract.node)] = { contract: contract, functions: buildLocalFuncCallGraphInternal(contract.functions, filterNodes, getNodeIdent, getFunDefIdent) }
}) })
...@@ -66,7 +66,7 @@ function analyseCallGraph (callGraph, funcName, context, nodeCheck) { ...@@ -66,7 +66,7 @@ function analyseCallGraph (callGraph, funcName, context, nodeCheck) {
} }
function analyseCallGraphInternal (callGraph, funcName, context, combinator, nodeCheck, visited) { function analyseCallGraphInternal (callGraph, funcName, context, combinator, nodeCheck, visited) {
var current = resolveCallGraphSymbol(callGraph, funcName) const current = resolveCallGraphSymbol(callGraph, funcName)
if (current === undefined || visited[funcName] === true) return true if (current === undefined || visited[funcName] === true) return true
visited[funcName] = true visited[funcName] = true
...@@ -80,20 +80,20 @@ function resolveCallGraphSymbol (callGraph, funcName) { ...@@ -80,20 +80,20 @@ function resolveCallGraphSymbol (callGraph, funcName) {
} }
function resolveCallGraphSymbolInternal (callGraph, funcName, silent) { function resolveCallGraphSymbolInternal (callGraph, funcName, silent) {
var current let current
if (funcName.includes('.')) { if (funcName.includes('.')) {
var parts = funcName.split('.') const parts = funcName.split('.')
var contractPart = parts[0] const contractPart = parts[0]
var functionPart = parts[1] const functionPart = parts[1]
var currentContract = callGraph[contractPart] const currentContract = callGraph[contractPart]
if (!(currentContract === undefined)) { if (!(currentContract === undefined)) {
current = currentContract.functions[funcName] current = currentContract.functions[funcName]
// resolve inheritance hierarchy // resolve inheritance hierarchy
if (current === undefined) { if (current === undefined) {
// resolve inheritance lookup in linearized fashion // resolve inheritance lookup in linearized fashion
var inheritsFromNames = currentContract.contract.inheritsFrom.reverse() const inheritsFromNames = currentContract.contract.inheritsFrom.reverse()
for (var i = 0; i < inheritsFromNames.length; i++) { for (let i = 0; i < inheritsFromNames.length; i++) {
var res = resolveCallGraphSymbolInternal(callGraph, inheritsFromNames[i] + '.' + functionPart, true) const res = resolveCallGraphSymbolInternal(callGraph, inheritsFromNames[i] + '.' + functionPart, true)
if (!(res === undefined)) return res if (!(res === undefined)) return res
} }
} }
......
var name = 'Gas costs: ' const name = 'Gas costs: '
var desc = 'Warn if the gas requirements of functions are too high.' const desc = 'Warn if the gas requirements of functions are too high.'
var categories = require('./categories') const categories = require('./categories')
var algo = require('./algorithmCategories') const algo = require('./algorithmCategories')
function gasCosts () { function gasCosts () {
} }
...@@ -13,15 +13,15 @@ function gasCosts () { ...@@ -13,15 +13,15 @@ function gasCosts () {
*/ */
// @TODO has been copied from remix-ide repo ! should fix that soon ! // @TODO has been copied from remix-ide repo ! should fix that soon !
function visitContracts (contracts, cb) { function visitContracts (contracts, cb) {
for (var file in contracts) { for (let file in contracts) {
for (var name in contracts[file]) { for (let name in contracts[file]) {
if (cb({ name: name, object: contracts[file][name], file: file })) return if (cb({ name: name, object: contracts[file][name], file: file })) return
} }
} }
} }
gasCosts.prototype.report = function (compilationResults) { gasCosts.prototype.report = function (compilationResults) {
var report = [] const report = []
visitContracts(compilationResults.contracts, (contract) => { visitContracts(compilationResults.contracts, (contract) => {
if ( if (
!contract.object.evm.gasEstimates || !contract.object.evm.gasEstimates ||
...@@ -29,7 +29,7 @@ gasCosts.prototype.report = function (compilationResults) { ...@@ -29,7 +29,7 @@ gasCosts.prototype.report = function (compilationResults) {
) { ) {
return return
} }
var fallback = contract.object.evm.gasEstimates.external[''] const fallback = contract.object.evm.gasEstimates.external['']
if (fallback !== undefined) { if (fallback !== undefined) {
if (fallback === null || fallback >= 2100 || fallback === 'infinite') { if (fallback === null || fallback >= 2100 || fallback === 'infinite') {
report.push({ report.push({
...@@ -43,8 +43,8 @@ gasCosts.prototype.report = function (compilationResults) { ...@@ -43,8 +43,8 @@ gasCosts.prototype.report = function (compilationResults) {
if (functionName === '') { if (functionName === '') {
continue continue
} }
var gas = contract.object.evm.gasEstimates.external[functionName] const gas = contract.object.evm.gasEstimates.external[functionName]
var gasString = gas === null ? 'unknown or not constant' : 'high: ' + gas const gasString = gas === null ? 'unknown or not constant' : 'high: ' + gas
if (gas === null || gas >= 3000000 || gas === 'infinite') { if (gas === null || gas >= 3000000 || gas === 'infinite') {
report.push({ report.push({
warning: `Gas requirement of function ${contract.name}.${functionName} ${gasString}. warning: `Gas requirement of function ${contract.name}.${functionName} ${gasString}.
......
var name = 'Guard Conditions: ' const name = 'Guard Conditions: '
var desc = 'Use require and appropriately' const desc = 'Use require and appropriately'
var categories = require('./categories') const categories = require('./categories')
var common = require('./staticAnalysisCommon') const common = require('./staticAnalysisCommon')
var algo = require('./algorithmCategories') const algo = require('./algorithmCategories')
function guardConditions () { function guardConditions () {
this.guards = [] this.guards = []
......
var name = 'Inline assembly: ' const name = 'Inline assembly: '
var desc = 'Use of Inline Assembly' const desc = 'Use of Inline Assembly'
var categories = require('./categories') const categories = require('./categories')
var common = require('./staticAnalysisCommon') const common = require('./staticAnalysisCommon')
var algo = require('./algorithmCategories') const algo = require('./algorithmCategories')
function inlineAssembly () { function inlineAssembly () {
this.inlineAssNodes = [] this.inlineAssNodes = []
......
var name = 'Data Trucated: ' const name = 'Data Trucated: '
var desc = 'Division on int/uint values truncates the result.' const desc = 'Division on int/uint values truncates the result.'
var categories = require('./categories') const categories = require('./categories')
var common = require('./staticAnalysisCommon') const common = require('./staticAnalysisCommon')
var algo = require('./algorithmCategories') const algo = require('./algorithmCategories')
function intDivitionTruncate () { function intDivitionTruncate () {
this.warningNodes = [] this.warningNodes = []
...@@ -13,7 +13,7 @@ intDivitionTruncate.prototype.visit = function (node) { ...@@ -13,7 +13,7 @@ intDivitionTruncate.prototype.visit = function (node) {
} }
intDivitionTruncate.prototype.report = function (compilationResults) { intDivitionTruncate.prototype.report = function (compilationResults) {
return this.warningNodes.map(function (item, i) { return this.warningNodes.map((item, i) => {
return { return {
warning: 'Division of integer values yields an integer value again. That means e.g. 10 / 100 = 0 instead of 0.1 since the result is an integer again. This does not hold for division of (only) literal values since those yield rational constants.', warning: 'Division of integer values yields an integer value again. That means e.g. 10 / 100 = 0 instead of 0.1 since the result is an integer again. This does not hold for division of (only) literal values since those yield rational constants.',
location: item.src location: item.src
......
var name = 'Low level calls: ' const name = 'Low level calls: '
var desc = 'Semantics maybe unclear' const desc = 'Semantics maybe unclear'
var categories = require('./categories') const categories = require('./categories')
var common = require('./staticAnalysisCommon') const common = require('./staticAnalysisCommon')
var algo = require('./algorithmCategories') const algo = require('./algorithmCategories')
function lowLevelCalls () { function lowLevelCalls () {
this.llcNodes = [] this.llcNodes = []
...@@ -27,9 +27,9 @@ lowLevelCalls.prototype.visit = function (node) { ...@@ -27,9 +27,9 @@ lowLevelCalls.prototype.visit = function (node) {
} }
lowLevelCalls.prototype.report = function (compilationResults) { lowLevelCalls.prototype.report = function (compilationResults) {
return this.llcNodes.map(function (item, i) { return this.llcNodes.map((item, i) => {
var text = '' let text = ''
var morehref = null let morehref = null
switch (item.type) { switch (item.type) {
case common.lowLevelCallTypes.CALL: case common.lowLevelCallTypes.CALL:
text = `use of "call": the use of low level "call" should be avoided whenever possible. text = `use of "call": the use of low level "call" should be avoided whenever possible.
......
var name = 'no return: ' const name = 'no return: '
var desc = 'Function with return type is not returning' const desc = 'Function with return type is not returning'
var categories = require('./categories') const categories = require('./categories')
var common = require('./staticAnalysisCommon') const common = require('./staticAnalysisCommon')
var AbstractAst = require('./abstractAstView') const AbstractAst = require('./abstractAstView')
var algo = require('./algorithmCategories') const algo = require('./algorithmCategories')
function noReturn () { function noReturn () {
this.abstractAst = new AbstractAst() this.abstractAst = new AbstractAst()
...@@ -20,11 +20,11 @@ noReturn.prototype.visit = function () { throw new Error('noReturn.js no visit f ...@@ -20,11 +20,11 @@ noReturn.prototype.visit = function () { throw new Error('noReturn.js no visit f
noReturn.prototype.report = function () { throw new Error('noReturn.js no report function set upon construction') } noReturn.prototype.report = function () { throw new Error('noReturn.js no report function set upon construction') }
function report (contracts, multipleContractsWithSameName) { function report (contracts, multipleContractsWithSameName) {
var warnings = [] const warnings = []
contracts.forEach((contract) => { contracts.forEach((contract) => {
contract.functions.filter((func) => common.hasFunctionBody(func.node)).forEach((func) => { contract.functions.filter((func) => common.hasFunctionBody(func.node)).forEach((func) => {
var funcName = common.getFullQuallyfiedFuncDefinitionIdent(contract.node, func.node, func.parameters) const funcName = common.getFullQuallyfiedFuncDefinitionIdent(contract.node, func.node, func.parameters)
if (hasNamedAndUnnamedReturns(func)) { if (hasNamedAndUnnamedReturns(func)) {
warnings.push({ warnings.push({
warning: `${funcName}: Mixing of named and unnamed return parameters is not advised.`, warning: `${funcName}: Mixing of named and unnamed return parameters is not advised.`,
...@@ -51,9 +51,9 @@ function hasReturnStatement (func) { ...@@ -51,9 +51,9 @@ function hasReturnStatement (func) {
} }
function hasAssignToAllNamedReturns (func) { function hasAssignToAllNamedReturns (func) {
var namedReturns = func.returns.filter((n) => n.name.length > 0).map((n) => n.name) const namedReturns = func.returns.filter((n) => n.name.length > 0).map((n) => n.name)
var assignedVars = func.relevantNodes.filter(common.isAssignment).map(common.getEffectedVariableName) const assignedVars = func.relevantNodes.filter(common.isAssignment).map(common.getEffectedVariableName)
var diff = namedReturns.filter(e => !assignedVars.includes(e)) const diff = namedReturns.filter(e => !assignedVars.includes(e))
return diff.length === 0 return diff.length === 0
} }
......
var name = 'Selfdestruct: ' const name = 'Selfdestruct: '
var desc = 'Be aware of caller contracts.' const desc = 'Be aware of caller contracts.'
var categories = require('./categories') const categories = require('./categories')
var common = require('./staticAnalysisCommon') const common = require('./staticAnalysisCommon')
var AbstractAst = require('./abstractAstView') const AbstractAst = require('./abstractAstView')
var algo = require('./algorithmCategories') const algo = require('./algorithmCategories')
function selfdestruct () { function selfdestruct () {
this.abstractAst = new AbstractAst() this.abstractAst = new AbstractAst()
...@@ -21,7 +21,7 @@ selfdestruct.prototype.visit = function () { throw new Error('selfdestruct.js no ...@@ -21,7 +21,7 @@ selfdestruct.prototype.visit = function () { throw new Error('selfdestruct.js no
selfdestruct.prototype.report = function () { throw new Error('selfdestruct.js no report function set upon construction') } selfdestruct.prototype.report = function () { throw new Error('selfdestruct.js no report function set upon construction') }
function report (contracts, multipleContractsWithSameName) { function report (contracts, multipleContractsWithSameName) {
var warnings = [] const warnings = []
contracts.forEach((contract) => { contracts.forEach((contract) => {
contract.functions.forEach((func) => { contract.functions.forEach((func) => {
......
var name = 'Similar variable names: ' const name = 'Similar variable names: '
var desc = 'Check if variable names are too similar' const desc = 'Check if variable names are too similar'
var categories = require('./categories') const categories = require('./categories')
var common = require('./staticAnalysisCommon') const common = require('./staticAnalysisCommon')
var AbstractAst = require('./abstractAstView') const AbstractAst = require('./abstractAstView')
var levenshtein = require('fast-levenshtein') const levenshtein = require('fast-levenshtein')
var remixLib = require('remix-lib') const remixLib = require('remix-lib')
var util = remixLib.util const util = remixLib.util
var algo = require('./algorithmCategories') const algo = require('./algorithmCategories')
function similarVariableNames () { function similarVariableNames () {
this.abstractAst = new AbstractAst() this.abstractAst = new AbstractAst()
...@@ -23,22 +23,22 @@ similarVariableNames.prototype.visit = function () { throw new Error('similarVar ...@@ -23,22 +23,22 @@ similarVariableNames.prototype.visit = function () { throw new Error('similarVar
similarVariableNames.prototype.report = function () { throw new Error('similarVariableNames.js no report function set upon construction') } similarVariableNames.prototype.report = function () { throw new Error('similarVariableNames.js no report function set upon construction') }
function report (contracts, multipleContractsWithSameName) { function report (contracts, multipleContractsWithSameName) {
var warnings = [] const warnings = []
var hasModifiers = contracts.some((item) => item.modifiers.length > 0) const hasModifiers = contracts.some((item) => item.modifiers.length > 0)
contracts.forEach((contract) => { contracts.forEach((contract) => {
contract.functions.forEach((func) => { contract.functions.forEach((func) => {
var funcName = common.getFullQuallyfiedFuncDefinitionIdent(contract.node, func.node, func.parameters) const funcName = common.getFullQuallyfiedFuncDefinitionIdent(contract.node, func.node, func.parameters)
var hasModifiersComments = '' let hasModifiersComments = ''
if (hasModifiers) { if (hasModifiers) {
hasModifiersComments = 'Note: Modifiers are currently not considered by this static analysis.' hasModifiersComments = 'Note: Modifiers are currently not considered by this static analysis.'
} }
var multipleContractsWithSameNameComments = '' let multipleContractsWithSameNameComments = ''
if (multipleContractsWithSameName) { if (multipleContractsWithSameName) {
multipleContractsWithSameNameComments = 'Note: Import aliases are currently not supported by this static analysis.' multipleContractsWithSameNameComments = 'Note: Import aliases are currently not supported by this static analysis.'
} }
var vars = getFunctionVariables(contract, func).map(common.getDeclaredVariableName) const vars = getFunctionVariables(contract, func).map(common.getDeclaredVariableName)
findSimilarVarNames(vars).map((sim) => { findSimilarVarNames(vars).map((sim) => {
warnings.push({ warnings.push({
...@@ -53,12 +53,12 @@ function report (contracts, multipleContractsWithSameName) { ...@@ -53,12 +53,12 @@ function report (contracts, multipleContractsWithSameName) {
} }
function findSimilarVarNames (vars) { function findSimilarVarNames (vars) {
var similar = [] const similar = []
var comb = {} const comb = {}
vars.map((varName1) => vars.map((varName2) => { vars.map((varName1) => vars.map((varName2) => {
if (varName1.length > 1 && varName2.length > 1 && varName2 !== varName1 && !isCommonPrefixedVersion(varName1, varName2) && !isCommonNrSuffixVersion(varName1, varName2) && !(comb[varName1 + ';' + varName2] || comb[varName2 + ';' + varName1])) { if (varName1.length > 1 && varName2.length > 1 && varName2 !== varName1 && !isCommonPrefixedVersion(varName1, varName2) && !isCommonNrSuffixVersion(varName1, varName2) && !(comb[varName1 + ';' + varName2] || comb[varName2 + ';' + varName1])) {
comb[varName1 + ';' + varName2] = true comb[varName1 + ';' + varName2] = true
var distance = levenshtein.get(varName1, varName2) const distance = levenshtein.get(varName1, varName2)
if (distance <= 2) similar.push({ var1: varName1, var2: varName2, distance: distance }) if (distance <= 2) similar.push({ var1: varName1, var2: varName2, distance: distance })
} }
})) }))
...@@ -70,8 +70,7 @@ function isCommonPrefixedVersion (varName1, varName2) { ...@@ -70,8 +70,7 @@ function isCommonPrefixedVersion (varName1, varName2) {
} }
function isCommonNrSuffixVersion (varName1, varName2) { function isCommonNrSuffixVersion (varName1, varName2) {
var ref = '^' + util.escapeRegExp(varName1.slice(0, -1)) + '[0-9]*$' const ref = '^' + util.escapeRegExp(varName1.slice(0, -1)) + '[0-9]*$'
return varName2.match(ref) != null return varName2.match(ref) != null
} }
......
'use strict' 'use strict'
var remixLib = require('remix-lib') const remixLib = require('remix-lib')
var util = remixLib.util const util = remixLib.util
var nodeTypes = { const nodeTypes = {
IDENTIFIER: 'Identifier', IDENTIFIER: 'Identifier',
MEMBERACCESS: 'MemberAccess', MEMBERACCESS: 'MemberAccess',
FUNCTIONCALL: 'FunctionCall', FUNCTIONCALL: 'FunctionCall',
...@@ -29,7 +29,7 @@ var nodeTypes = { ...@@ -29,7 +29,7 @@ var nodeTypes = {
ELEMENTARYTYPENAMEEXPRESSION: 'ElementaryTypeNameExpression' ELEMENTARYTYPENAMEEXPRESSION: 'ElementaryTypeNameExpression'
} }
var basicTypes = { const basicTypes = {
UINT: 'uint256', UINT: 'uint256',
BOOL: 'bool', BOOL: 'bool',
ADDRESS: 'address', ADDRESS: 'address',
...@@ -40,7 +40,7 @@ var basicTypes = { ...@@ -40,7 +40,7 @@ var basicTypes = {
BYTES4: 'bytes4' BYTES4: 'bytes4'
} }
var basicRegex = { const basicRegex = {
CONTRACTTYPE: '^contract ', CONTRACTTYPE: '^contract ',
FUNCTIONTYPE: '^function \\(', FUNCTIONTYPE: '^function \\(',
EXTERNALFUNCTIONTYPE: '^function \\(.*\\).* external', EXTERNALFUNCTIONTYPE: '^function \\(.*\\).* external',
...@@ -50,7 +50,7 @@ var basicRegex = { ...@@ -50,7 +50,7 @@ var basicRegex = {
LIBRARYTYPE: '^type\\(library (.*)\\)' LIBRARYTYPE: '^type\\(library (.*)\\)'
} }
var basicFunctionTypes = { const basicFunctionTypes = {
SEND: buildFunctionSignature([basicTypes.UINT], [basicTypes.BOOL], false), SEND: buildFunctionSignature([basicTypes.UINT], [basicTypes.BOOL], false),
CALL: buildFunctionSignature([], [basicTypes.BOOL], true), CALL: buildFunctionSignature([], [basicTypes.BOOL], true),
'CALL-v0.5': buildFunctionSignature([basicTypes.BYTES_MEM], [basicTypes.BOOL, basicTypes.BYTES_MEM], true), 'CALL-v0.5': buildFunctionSignature([basicTypes.BYTES_MEM], [basicTypes.BOOL, basicTypes.BYTES_MEM], true),
...@@ -59,7 +59,7 @@ var basicFunctionTypes = { ...@@ -59,7 +59,7 @@ var basicFunctionTypes = {
TRANSFER: buildFunctionSignature([basicTypes.UINT], [], false) TRANSFER: buildFunctionSignature([basicTypes.UINT], [], false)
} }
var builtinFunctions = { const builtinFunctions = {
'keccak256()': true, 'keccak256()': true,
'sha3()': true, 'sha3()': true,
'sha256()': true, 'sha256()': true,
...@@ -79,7 +79,7 @@ var builtinFunctions = { ...@@ -79,7 +79,7 @@ var builtinFunctions = {
'address(address)': true 'address(address)': true
} }
var lowLevelCallTypes = { const lowLevelCallTypes = {
CALL: { ident: 'call', type: basicFunctionTypes.CALL }, CALL: { ident: 'call', type: basicFunctionTypes.CALL },
'CALL-v0.5': { ident: 'call', type: basicFunctionTypes['CALL-v0.5'] }, 'CALL-v0.5': { ident: 'call', type: basicFunctionTypes['CALL-v0.5'] },
CALLCODE: { ident: 'callcode', type: basicFunctionTypes.CALL }, CALLCODE: { ident: 'callcode', type: basicFunctionTypes.CALL },
...@@ -89,7 +89,7 @@ var lowLevelCallTypes = { ...@@ -89,7 +89,7 @@ var lowLevelCallTypes = {
TRANSFER: { ident: 'transfer', type: basicFunctionTypes.TRANSFER } TRANSFER: { ident: 'transfer', type: basicFunctionTypes.TRANSFER }
} }
var specialVariables = { const specialVariables = {
BLOCKTIMESTAMP: { obj: 'block', member: 'timestamp', type: basicTypes.UINT }, BLOCKTIMESTAMP: { obj: 'block', member: 'timestamp', type: basicTypes.UINT },
BLOCKHASH: { BLOCKHASH: {
obj: 'block', obj: 'block',
...@@ -98,7 +98,7 @@ var specialVariables = { ...@@ -98,7 +98,7 @@ var specialVariables = {
} }
} }
var abiNamespace = { const abiNamespace = {
ENCODE: { ENCODE: {
obj: 'abi', obj: 'abi',
member: 'encode', member: 'encode',
...@@ -333,12 +333,12 @@ function getFunctionOrModifierDefinitionReturnParameterPart (funcNode) { ...@@ -333,12 +333,12 @@ function getFunctionOrModifierDefinitionReturnParameterPart (funcNode) {
* @return {string} parameter signature * @return {string} parameter signature
*/ */
function getFunctionCallTypeParameterType (func) { function getFunctionCallTypeParameterType (func) {
var type = getFunctionCallType(func) const type = getFunctionCallType(func)
if (type.startsWith('function (')) { if (type.startsWith('function (')) {
var paramTypes = '' let paramTypes = ''
var openPar = 1 let openPar = 1
for (var x = 10; x < type.length; x++) { for (let x = 10; x < type.length; x++) {
var c = type.charAt(x) const c = type.charAt(x)
if (c === '(') openPar++ if (c === '(') openPar++
else if (c === ')') openPar-- else if (c === ')') openPar--
...@@ -1031,7 +1031,7 @@ function nodeType (node, typeRegex) { ...@@ -1031,7 +1031,7 @@ function nodeType (node, typeRegex) {
} }
function name (node, nameRegex) { function name (node, nameRegex) {
var regex = new RegExp(nameRegex) const regex = new RegExp(nameRegex)
return (node && !nameRegex) || (node && node.attributes && (regex.test(node.attributes.value) || regex.test(node.attributes.member_name))) return (node && !nameRegex) || (node && node.attributes && (regex.test(node.attributes.value) || regex.test(node.attributes.member_name)))
} }
...@@ -1046,8 +1046,8 @@ function exactMatch (regexStr) { ...@@ -1046,8 +1046,8 @@ function exactMatch (regexStr) {
} }
function matches () { function matches () {
var args = [] const args = []
for (var k = 0; k < arguments.length; k++) { for (let k = 0; k < arguments.length; k++) {
args.push(arguments[k]) args.push(arguments[k])
} }
return '(' + args.join('|') + ')' return '(' + args.join('|') + ')'
...@@ -1078,10 +1078,10 @@ function buildAbiSignature (funName, paramTypes) { ...@@ -1078,10 +1078,10 @@ function buildAbiSignature (funName, paramTypes) {
function findFirstSubNodeLTR (node, type) { function findFirstSubNodeLTR (node, type) {
if (!node || !node.children) return null if (!node || !node.children) return null
for (let i = 0; i < node.children.length; ++i) { for (let i = 0; i < node.children.length; ++i) {
var item = node.children[i] const item = node.children[i]
if (nodeType(item, type)) return item if (nodeType(item, type)) return item
else { else {
var res = findFirstSubNodeLTR(item, type) const res = findFirstSubNodeLTR(item, type)
if (res) return res if (res) return res
} }
} }
......
var name = 'String Length: ' const name = 'String Length: '
var desc = 'Bytes length != String length' const desc = 'Bytes length != String length'
var categories = require('./categories') const categories = require('./categories')
var common = require('./staticAnalysisCommon') const common = require('./staticAnalysisCommon')
function stringBytesLength () { function stringBytesLength () {
this.stringToBytesConversions = [] this.stringToBytesConversions = []
...@@ -31,4 +31,3 @@ module.exports = { ...@@ -31,4 +31,3 @@ module.exports = {
category: categories.MISC, category: categories.MISC,
Module: stringBytesLength Module: stringBytesLength
} }
var name = 'This on local calls: ' const name = 'This on local calls: '
var desc = 'Invocation of local functions via this' const desc = 'Invocation of local functions via this'
var categories = require('./categories') const categories = require('./categories')
var common = require('./staticAnalysisCommon') const common = require('./staticAnalysisCommon')
var algo = require('./algorithmCategories') const algo = require('./algorithmCategories')
function thisLocal () { function thisLocal () {
this.warningNodes = [] this.warningNodes = []
......
var name = 'Transaction origin: ' const name = 'Transaction origin: '
var desc = 'Warn if tx.origin is used' const desc = 'Warn if tx.origin is used'
var categories = require('./categories') const categories = require('./categories')
var algo = require('./algorithmCategories') const algo = require('./algorithmCategories')
function txOrigin () { function txOrigin () {
this.txOriginNodes = [] this.txOriginNodes = []
...@@ -19,7 +19,7 @@ txOrigin.prototype.visit = function (node) { ...@@ -19,7 +19,7 @@ txOrigin.prototype.visit = function (node) {
} }
txOrigin.prototype.report = function () { txOrigin.prototype.report = function () {
return this.txOriginNodes.map(function (item, i) { return this.txOriginNodes.map((item, i) => {
return { return {
warning: `Use of tx.origin: "tx.origin" is useful only in very exceptional cases. warning: `Use of tx.origin: "tx.origin" is useful only in very exceptional cases.
If you use it for authentication, you usually want to replace it by "msg.sender", because otherwise any contract you call can act on your behalf.`, If you use it for authentication, you usually want to replace it by "msg.sender", because otherwise any contract you call can act on your behalf.`,
......
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