Unverified Commit b93b3577 authored by Aniket's avatar Aniket Committed by GitHub

Merge pull request #1242 from Aniket-Engg/fix/#854

[Static analysis] Interaction with different addresses inside the loop handled
parents 7ea3f1df 376baccd
var name = 'Ether transfer in a loop: '
var desc = 'Avoid transferring Ether to multiple addresses in a loop'
var categories = require('./categories')
var common = require('./staticAnalysisCommon')
function etherTransferInLoop () {
this.relevantNodes = []
}
etherTransferInLoop.prototype.visit = function (node) {
if (common.isLoop(node)) {
var transferNodes = []
var loopBlockStartIndex = common.getLoopBlockStartIndex(node)
if (common.isBlock(node.children[loopBlockStartIndex])) {
transferNodes = node.children[loopBlockStartIndex].children
.filter(child => (common.isExpressionStatement(child) &&
child.children[0].name === 'FunctionCall' &&
common.isTransfer(child.children[0].children[0])))
if (transferNodes.length > 0) {
this.relevantNodes.push(...transferNodes)
}
}
}
}
etherTransferInLoop.prototype.report = function (compilationResults) {
return this.relevantNodes.map((node) => {
return {
warning: 'Ether payout should not be done in a loop: Due to the block gas limit, transactions can only consume a certain amount of gas. The number of iterations in a loop can grow beyond the block gas limit which can cause the complete contract to be stalled at a certain point. If required then make sure that number of iterations are low and you trust each address involved.',
location: node.src,
more: 'https://solidity.readthedocs.io/en/latest/security-considerations.html#gas-limit-and-loops'
}
})
}
module.exports = {
name: name,
description: desc,
category: categories.GAS,
Module: etherTransferInLoop
}
...@@ -410,6 +410,16 @@ function getUnAssignedTopLevelBinOps (subScope) { ...@@ -410,6 +410,16 @@ function getUnAssignedTopLevelBinOps (subScope) {
return subScope.children.filter(isBinaryOpInExpression) return subScope.children.filter(isBinaryOpInExpression)
} }
function getLoopBlockStartIndex (node) {
if (isLoop(node)) {
if (nodeType(node, exactMatch(nodeTypes.FORSTATEMENT))) {
return 3 // For 'for' loop
} else {
return 1 // For 'while' and 'do-while' loop
}
}
}
// #################### Trivial Node Identification // #################### Trivial Node Identification
function isFunctionDefinition (node) { function isFunctionDefinition (node) {
...@@ -948,6 +958,17 @@ function isBytesLengthCheck (node) { ...@@ -948,6 +958,17 @@ function isBytesLengthCheck (node) {
} }
/** /**
* True if it is a loop
* @node {ASTNode} some AstNode
* @return {bool}
*/
function isLoop (node) {
return nodeType(node, exactMatch(nodeTypes.FORSTATEMENT)) ||
nodeType(node, exactMatch(nodeTypes.WHILESTATEMENT)) ||
nodeType(node, exactMatch(nodeTypes.DOWHILESTATEMENT))
}
/**
* True if it is a 'for' loop * True if it is a 'for' loop
* @node {ASTNode} some AstNode * @node {ASTNode} some AstNode
* @return {bool} * @return {bool}
...@@ -1073,6 +1094,7 @@ module.exports = { ...@@ -1073,6 +1094,7 @@ module.exports = {
getFunctionOrModifierDefinitionParameterPart: getFunctionOrModifierDefinitionParameterPart, getFunctionOrModifierDefinitionParameterPart: getFunctionOrModifierDefinitionParameterPart,
getFunctionOrModifierDefinitionReturnParameterPart: getFunctionOrModifierDefinitionReturnParameterPart, getFunctionOrModifierDefinitionReturnParameterPart: getFunctionOrModifierDefinitionReturnParameterPart,
getUnAssignedTopLevelBinOps: getUnAssignedTopLevelBinOps, getUnAssignedTopLevelBinOps: getUnAssignedTopLevelBinOps,
getLoopBlockStartIndex: getLoopBlockStartIndex,
// #################### Complex Node Identification // #################### Complex Node Identification
isDeleteOfDynamicArray: isDeleteOfDynamicArray, isDeleteOfDynamicArray: isDeleteOfDynamicArray,
...@@ -1117,6 +1139,7 @@ module.exports = { ...@@ -1117,6 +1139,7 @@ module.exports = {
isIntDivision: isIntDivision, isIntDivision: isIntDivision,
isStringToBytesConversion: isStringToBytesConversion, isStringToBytesConversion: isStringToBytesConversion,
isBytesLengthCheck: isBytesLengthCheck, isBytesLengthCheck: isBytesLengthCheck,
isLoop: isLoop,
isForLoop: isForLoop, isForLoop: isForLoop,
// #################### Trivial Node Identification // #################### Trivial Node Identification
...@@ -1136,6 +1159,7 @@ module.exports = { ...@@ -1136,6 +1159,7 @@ module.exports = {
isNewExpression: isNewExpression, isNewExpression: isNewExpression,
isReturn: isReturn, isReturn: isReturn,
isStatement: isStatement, isStatement: isStatement,
isExpressionStatement: isExpressionStatement,
isBlock: isBlock, isBlock: isBlock,
// #################### Constants // #################### Constants
......
...@@ -1119,6 +1119,686 @@ test('staticAnalysisCommon.getFullQuallyfiedFuncDefinitionIdent', function (t) { ...@@ -1119,6 +1119,686 @@ test('staticAnalysisCommon.getFullQuallyfiedFuncDefinitionIdent', function (t) {
t.throws(() => common.getFullQuallyfiedFuncDefinitionIdent({ name: 'FunctionCall' }, funDef, ['uint256', 'bool']), undefined, 'throws on wrong nodes') t.throws(() => common.getFullQuallyfiedFuncDefinitionIdent({ name: 'FunctionCall' }, funDef, ['uint256', 'bool']), undefined, 'throws on wrong nodes')
}) })
test('staticAnalysisCommon.getLoopBlockStartIndex', function (t) {
t.plan(3)
var node1 = {
'children':
[
{
'attributes':
{
'assignments':
[
21
]
},
'children':
[
{
'attributes':
{
'constant': false,
'name': 'i',
'scope': 39,
'stateVariable': false,
'storageLocation': 'default',
'type': 'uint256',
'value': null,
'visibility': 'internal'
},
'children':
[
{
'attributes':
{
'name': 'uint',
'type': 'uint256'
},
'id': 20,
'name': 'ElementaryTypeName',
'src': '207:4:0'
}
],
'id': 21,
'name': 'VariableDeclaration',
'src': '207:6:0'
},
{
'attributes':
{
'argumentTypes': null,
'overloadedDeclarations':
[
null
],
'referencedDeclaration': 17,
'type': 'uint256',
'value': 'index'
},
'id': 22,
'name': 'Identifier',
'src': '216:5:0'
}
],
'id': 23,
'name': 'VariableDeclarationStatement',
'src': '207:14:0'
},
{
'attributes':
{
'argumentTypes': null,
'commonType':
{
'typeIdentifier': 't_uint256',
'typeString': 'uint256'
},
'isConstant': false,
'isLValue': false,
'isPure': false,
'lValueRequested': false,
'operator': '<',
'type': 'bool'
},
'children':
[
{
'attributes':
{
'argumentTypes': null,
'overloadedDeclarations':
[
null
],
'referencedDeclaration': 21,
'type': 'uint256',
'value': 'i'
},
'id': 24,
'name': 'Identifier',
'src': '223:1:0'
},
{
'attributes':
{
'argumentTypes': null,
'hexvalue': '3130',
'isConstant': false,
'isLValue': false,
'isPure': true,
'lValueRequested': false,
'subdenomination': null,
'token': 'number',
'type': 'int_const 10',
'value': '10'
},
'id': 25,
'name': 'Literal',
'src': '227:2:0'
}
],
'id': 26,
'name': 'BinaryOperation',
'src': '223:6:0'
},
{
'children':
[
{
'attributes':
{
'argumentTypes': null,
'isConstant': false,
'isLValue': false,
'isPure': false,
'lValueRequested': false,
'operator': '++',
'prefix': false,
'type': 'uint256'
},
'children':
[
{
'attributes':
{
'argumentTypes': null,
'overloadedDeclarations':
[
null
],
'referencedDeclaration': 21,
'type': 'uint256',
'value': 'i'
},
'id': 27,
'name': 'Identifier',
'src': '231:1:0'
}
],
'id': 28,
'name': 'UnaryOperation',
'src': '231:3:0'
}
],
'id': 29,
'name': 'ExpressionStatement',
'src': '231:3:0'
},
{
'children':
[
{
'children':
[
{
'attributes':
{
'argumentTypes': null,
'isConstant': false,
'isLValue': false,
'isPure': false,
'isStructConstructorCall': false,
'lValueRequested': false,
'names':
[
null
],
'type': 'uint256',
'type_conversion': false
},
'children':
[
{
'attributes':
{
'argumentTypes':
[
{
'typeIdentifier': 't_uint256',
'typeString': 'uint256'
}
],
'isConstant': false,
'isLValue': false,
'isPure': false,
'lValueRequested': false,
'member_name': 'push',
'referencedDeclaration': null,
'type': 'function (uint256) returns (uint256)'
},
'children':
[
{
'attributes':
{
'argumentTypes': null,
'overloadedDeclarations':
[
null
],
'referencedDeclaration': 4,
'type': 'uint256[] storage ref',
'value': 'array'
},
'id': 30,
'name': 'Identifier',
'src': '250:5:0'
}
],
'id': 32,
'name': 'MemberAccess',
'src': '250:10:0'
},
{
'attributes':
{
'argumentTypes': null,
'overloadedDeclarations':
[
null
],
'referencedDeclaration': 21,
'type': 'uint256',
'value': 'i'
},
'id': 33,
'name': 'Identifier',
'src': '261:1:0'
}
],
'id': 34,
'name': 'FunctionCall',
'src': '250:13:0'
}
],
'id': 35,
'name': 'ExpressionStatement',
'src': '250:13:0'
}
],
'id': 36,
'name': 'Block',
'src': '236:38:0'
}
],
'id': 37,
'name': 'ForStatement',
'src': '202:72:0'
}
var node2 = {
'children':
[
{
'attributes':
{
'argumentTypes': null,
'commonType':
{
'typeIdentifier': 't_uint256',
'typeString': 'uint256'
},
'isConstant': false,
'isLValue': false,
'isPure': false,
'lValueRequested': false,
'operator': '<',
'type': 'bool'
},
'children':
[
{
'attributes':
{
'argumentTypes': null,
'overloadedDeclarations':
[
null
],
'referencedDeclaration': 69,
'type': 'uint256',
'value': 'i'
},
'id': 82,
'name': 'Identifier',
'src': '592:1:0'
},
{
'attributes':
{
'argumentTypes': null,
'hexvalue': '3130',
'isConstant': false,
'isLValue': false,
'isPure': true,
'lValueRequested': false,
'subdenomination': null,
'token': 'number',
'type': 'int_const 10',
'value': '10'
},
'id': 83,
'name': 'Literal',
'src': '596:2:0'
}
],
'id': 84,
'name': 'BinaryOperation',
'src': '592:6:0'
},
{
'children':
[
{
'children':
[
{
'attributes':
{
'argumentTypes': null,
'isConstant': false,
'isLValue': false,
'isPure': false,
'isStructConstructorCall': false,
'lValueRequested': false,
'names':
[
null
],
'type': 'uint256',
'type_conversion': false
},
'children':
[
{
'attributes':
{
'argumentTypes':
[
{
'typeIdentifier': 't_uint256',
'typeString': 'uint256'
}
],
'isConstant': false,
'isLValue': false,
'isPure': false,
'lValueRequested': false,
'member_name': 'push',
'referencedDeclaration': null,
'type': 'function (uint256) returns (uint256)'
},
'children':
[
{
'attributes':
{
'argumentTypes': null,
'overloadedDeclarations':
[
null
],
'referencedDeclaration': 4,
'type': 'uint256[] storage ref',
'value': 'array'
},
'id': 72,
'name': 'Identifier',
'src': '544:5:0'
}
],
'id': 74,
'name': 'MemberAccess',
'src': '544:10:0'
},
{
'attributes':
{
'argumentTypes': null,
'overloadedDeclarations':
[
null
],
'referencedDeclaration': 69,
'type': 'uint256',
'value': 'i'
},
'id': 75,
'name': 'Identifier',
'src': '555:1:0'
}
],
'id': 76,
'name': 'FunctionCall',
'src': '544:13:0'
}
],
'id': 77,
'name': 'ExpressionStatement',
'src': '544:13:0'
},
{
'children':
[
{
'attributes':
{
'argumentTypes': null,
'isConstant': false,
'isLValue': false,
'isPure': false,
'lValueRequested': false,
'operator': '++',
'prefix': false,
'type': 'uint256'
},
'children':
[
{
'attributes':
{
'argumentTypes': null,
'overloadedDeclarations':
[
null
],
'referencedDeclaration': 69,
'type': 'uint256',
'value': 'i'
},
'id': 78,
'name': 'Identifier',
'src': '571:1:0'
}
],
'id': 79,
'name': 'UnaryOperation',
'src': '571:3:0'
}
],
'id': 80,
'name': 'ExpressionStatement',
'src': '571:3:0'
}
],
'id': 81,
'name': 'Block',
'src': '530:55:0'
}
],
'id': 85,
'name': 'DoWhileStatement',
'src': '528:72:0'
}
var node3 = {
'children':
[
{
'attributes':
{
'argumentTypes': null,
'commonType':
{
'typeIdentifier': 't_uint256',
'typeString': 'uint256'
},
'isConstant': false,
'isLValue': false,
'isPure': false,
'lValueRequested': false,
'operator': '<',
'type': 'bool'
},
'children':
[
{
'attributes':
{
'argumentTypes': null,
'overloadedDeclarations':
[
null
],
'referencedDeclaration': 45,
'type': 'uint256',
'value': 'i'
},
'id': 48,
'name': 'Identifier',
'src': '372:1:0'
},
{
'attributes':
{
'argumentTypes': null,
'hexvalue': '3130',
'isConstant': false,
'isLValue': false,
'isPure': true,
'lValueRequested': false,
'subdenomination': null,
'token': 'number',
'type': 'int_const 10',
'value': '10'
},
'id': 49,
'name': 'Literal',
'src': '376:2:0'
}
],
'id': 50,
'name': 'BinaryOperation',
'src': '372:6:0'
},
{
'children':
[
{
'children':
[
{
'attributes':
{
'argumentTypes': null,
'isConstant': false,
'isLValue': false,
'isPure': false,
'isStructConstructorCall': false,
'lValueRequested': false,
'names':
[
null
],
'type': 'uint256',
'type_conversion': false
},
'children':
[
{
'attributes':
{
'argumentTypes':
[
{
'typeIdentifier': 't_uint256',
'typeString': 'uint256'
}
],
'isConstant': false,
'isLValue': false,
'isPure': false,
'lValueRequested': false,
'member_name': 'push',
'referencedDeclaration': null,
'type': 'function (uint256) returns (uint256)'
},
'children':
[
{
'attributes':
{
'argumentTypes': null,
'overloadedDeclarations':
[
null
],
'referencedDeclaration': 4,
'type': 'uint256[] storage ref',
'value': 'array'
},
'id': 51,
'name': 'Identifier',
'src': '394:5:0'
}
],
'id': 53,
'name': 'MemberAccess',
'src': '394:10:0'
},
{
'attributes':
{
'argumentTypes': null,
'overloadedDeclarations':
[
null
],
'referencedDeclaration': 45,
'type': 'uint256',
'value': 'i'
},
'id': 54,
'name': 'Identifier',
'src': '405:1:0'
}
],
'id': 55,
'name': 'FunctionCall',
'src': '394:13:0'
}
],
'id': 56,
'name': 'ExpressionStatement',
'src': '394:13:0'
},
{
'children':
[
{
'attributes':
{
'argumentTypes': null,
'isConstant': false,
'isLValue': false,
'isPure': false,
'lValueRequested': false,
'operator': '++',
'prefix': false,
'type': 'uint256'
},
'children':
[
{
'attributes':
{
'argumentTypes': null,
'overloadedDeclarations':
[
null
],
'referencedDeclaration': 45,
'type': 'uint256',
'value': 'i'
},
'id': 57,
'name': 'Identifier',
'src': '421:1:0'
}
],
'id': 58,
'name': 'UnaryOperation',
'src': '421:3:0'
}
],
'id': 59,
'name': 'ExpressionStatement',
'src': '421:3:0'
}
],
'id': 60,
'name': 'Block',
'src': '380:55:0'
}
],
'id': 61,
'name': 'WhileStatement',
'src': '365:70:0'
}
t.equal(common.getLoopBlockStartIndex(node1), 3) // 'for' loop
t.equal(common.getLoopBlockStartIndex(node2), 1) // 'do-while' loop
t.equal(common.getLoopBlockStartIndex(node3), 1) // 'while' loop
})
// #################### Trivial Node Identification // #################### Trivial Node Identification
test('staticAnalysisCommon.isFunctionDefinition', function (t) { test('staticAnalysisCommon.isFunctionDefinition', function (t) {
...@@ -1209,6 +1889,686 @@ test('staticAnalysisCommon.isInlineAssembly', function (t) { ...@@ -1209,6 +1889,686 @@ test('staticAnalysisCommon.isInlineAssembly', function (t) {
t.notOk(common.isInlineAssembly(node3), 'substring should not work') t.notOk(common.isInlineAssembly(node3), 'substring should not work')
}) })
test('staticAnalysisCommon.isLoop', function (t) {
t.plan(3)
var node1 = {
'children':
[
{
'attributes':
{
'assignments':
[
21
]
},
'children':
[
{
'attributes':
{
'constant': false,
'name': 'i',
'scope': 39,
'stateVariable': false,
'storageLocation': 'default',
'type': 'uint256',
'value': null,
'visibility': 'internal'
},
'children':
[
{
'attributes':
{
'name': 'uint',
'type': 'uint256'
},
'id': 20,
'name': 'ElementaryTypeName',
'src': '207:4:0'
}
],
'id': 21,
'name': 'VariableDeclaration',
'src': '207:6:0'
},
{
'attributes':
{
'argumentTypes': null,
'overloadedDeclarations':
[
null
],
'referencedDeclaration': 17,
'type': 'uint256',
'value': 'index'
},
'id': 22,
'name': 'Identifier',
'src': '216:5:0'
}
],
'id': 23,
'name': 'VariableDeclarationStatement',
'src': '207:14:0'
},
{
'attributes':
{
'argumentTypes': null,
'commonType':
{
'typeIdentifier': 't_uint256',
'typeString': 'uint256'
},
'isConstant': false,
'isLValue': false,
'isPure': false,
'lValueRequested': false,
'operator': '<',
'type': 'bool'
},
'children':
[
{
'attributes':
{
'argumentTypes': null,
'overloadedDeclarations':
[
null
],
'referencedDeclaration': 21,
'type': 'uint256',
'value': 'i'
},
'id': 24,
'name': 'Identifier',
'src': '223:1:0'
},
{
'attributes':
{
'argumentTypes': null,
'hexvalue': '3130',
'isConstant': false,
'isLValue': false,
'isPure': true,
'lValueRequested': false,
'subdenomination': null,
'token': 'number',
'type': 'int_const 10',
'value': '10'
},
'id': 25,
'name': 'Literal',
'src': '227:2:0'
}
],
'id': 26,
'name': 'BinaryOperation',
'src': '223:6:0'
},
{
'children':
[
{
'attributes':
{
'argumentTypes': null,
'isConstant': false,
'isLValue': false,
'isPure': false,
'lValueRequested': false,
'operator': '++',
'prefix': false,
'type': 'uint256'
},
'children':
[
{
'attributes':
{
'argumentTypes': null,
'overloadedDeclarations':
[
null
],
'referencedDeclaration': 21,
'type': 'uint256',
'value': 'i'
},
'id': 27,
'name': 'Identifier',
'src': '231:1:0'
}
],
'id': 28,
'name': 'UnaryOperation',
'src': '231:3:0'
}
],
'id': 29,
'name': 'ExpressionStatement',
'src': '231:3:0'
},
{
'children':
[
{
'children':
[
{
'attributes':
{
'argumentTypes': null,
'isConstant': false,
'isLValue': false,
'isPure': false,
'isStructConstructorCall': false,
'lValueRequested': false,
'names':
[
null
],
'type': 'uint256',
'type_conversion': false
},
'children':
[
{
'attributes':
{
'argumentTypes':
[
{
'typeIdentifier': 't_uint256',
'typeString': 'uint256'
}
],
'isConstant': false,
'isLValue': false,
'isPure': false,
'lValueRequested': false,
'member_name': 'push',
'referencedDeclaration': null,
'type': 'function (uint256) returns (uint256)'
},
'children':
[
{
'attributes':
{
'argumentTypes': null,
'overloadedDeclarations':
[
null
],
'referencedDeclaration': 4,
'type': 'uint256[] storage ref',
'value': 'array'
},
'id': 30,
'name': 'Identifier',
'src': '250:5:0'
}
],
'id': 32,
'name': 'MemberAccess',
'src': '250:10:0'
},
{
'attributes':
{
'argumentTypes': null,
'overloadedDeclarations':
[
null
],
'referencedDeclaration': 21,
'type': 'uint256',
'value': 'i'
},
'id': 33,
'name': 'Identifier',
'src': '261:1:0'
}
],
'id': 34,
'name': 'FunctionCall',
'src': '250:13:0'
}
],
'id': 35,
'name': 'ExpressionStatement',
'src': '250:13:0'
}
],
'id': 36,
'name': 'Block',
'src': '236:38:0'
}
],
'id': 37,
'name': 'ForStatement',
'src': '202:72:0'
}
var node2 = {
'children':
[
{
'attributes':
{
'argumentTypes': null,
'commonType':
{
'typeIdentifier': 't_uint256',
'typeString': 'uint256'
},
'isConstant': false,
'isLValue': false,
'isPure': false,
'lValueRequested': false,
'operator': '<',
'type': 'bool'
},
'children':
[
{
'attributes':
{
'argumentTypes': null,
'overloadedDeclarations':
[
null
],
'referencedDeclaration': 69,
'type': 'uint256',
'value': 'i'
},
'id': 82,
'name': 'Identifier',
'src': '592:1:0'
},
{
'attributes':
{
'argumentTypes': null,
'hexvalue': '3130',
'isConstant': false,
'isLValue': false,
'isPure': true,
'lValueRequested': false,
'subdenomination': null,
'token': 'number',
'type': 'int_const 10',
'value': '10'
},
'id': 83,
'name': 'Literal',
'src': '596:2:0'
}
],
'id': 84,
'name': 'BinaryOperation',
'src': '592:6:0'
},
{
'children':
[
{
'children':
[
{
'attributes':
{
'argumentTypes': null,
'isConstant': false,
'isLValue': false,
'isPure': false,
'isStructConstructorCall': false,
'lValueRequested': false,
'names':
[
null
],
'type': 'uint256',
'type_conversion': false
},
'children':
[
{
'attributes':
{
'argumentTypes':
[
{
'typeIdentifier': 't_uint256',
'typeString': 'uint256'
}
],
'isConstant': false,
'isLValue': false,
'isPure': false,
'lValueRequested': false,
'member_name': 'push',
'referencedDeclaration': null,
'type': 'function (uint256) returns (uint256)'
},
'children':
[
{
'attributes':
{
'argumentTypes': null,
'overloadedDeclarations':
[
null
],
'referencedDeclaration': 4,
'type': 'uint256[] storage ref',
'value': 'array'
},
'id': 72,
'name': 'Identifier',
'src': '544:5:0'
}
],
'id': 74,
'name': 'MemberAccess',
'src': '544:10:0'
},
{
'attributes':
{
'argumentTypes': null,
'overloadedDeclarations':
[
null
],
'referencedDeclaration': 69,
'type': 'uint256',
'value': 'i'
},
'id': 75,
'name': 'Identifier',
'src': '555:1:0'
}
],
'id': 76,
'name': 'FunctionCall',
'src': '544:13:0'
}
],
'id': 77,
'name': 'ExpressionStatement',
'src': '544:13:0'
},
{
'children':
[
{
'attributes':
{
'argumentTypes': null,
'isConstant': false,
'isLValue': false,
'isPure': false,
'lValueRequested': false,
'operator': '++',
'prefix': false,
'type': 'uint256'
},
'children':
[
{
'attributes':
{
'argumentTypes': null,
'overloadedDeclarations':
[
null
],
'referencedDeclaration': 69,
'type': 'uint256',
'value': 'i'
},
'id': 78,
'name': 'Identifier',
'src': '571:1:0'
}
],
'id': 79,
'name': 'UnaryOperation',
'src': '571:3:0'
}
],
'id': 80,
'name': 'ExpressionStatement',
'src': '571:3:0'
}
],
'id': 81,
'name': 'Block',
'src': '530:55:0'
}
],
'id': 85,
'name': 'DoWhileStatement',
'src': '528:72:0'
}
var node3 = {
'children':
[
{
'attributes':
{
'argumentTypes': null,
'commonType':
{
'typeIdentifier': 't_uint256',
'typeString': 'uint256'
},
'isConstant': false,
'isLValue': false,
'isPure': false,
'lValueRequested': false,
'operator': '<',
'type': 'bool'
},
'children':
[
{
'attributes':
{
'argumentTypes': null,
'overloadedDeclarations':
[
null
],
'referencedDeclaration': 45,
'type': 'uint256',
'value': 'i'
},
'id': 48,
'name': 'Identifier',
'src': '372:1:0'
},
{
'attributes':
{
'argumentTypes': null,
'hexvalue': '3130',
'isConstant': false,
'isLValue': false,
'isPure': true,
'lValueRequested': false,
'subdenomination': null,
'token': 'number',
'type': 'int_const 10',
'value': '10'
},
'id': 49,
'name': 'Literal',
'src': '376:2:0'
}
],
'id': 50,
'name': 'BinaryOperation',
'src': '372:6:0'
},
{
'children':
[
{
'children':
[
{
'attributes':
{
'argumentTypes': null,
'isConstant': false,
'isLValue': false,
'isPure': false,
'isStructConstructorCall': false,
'lValueRequested': false,
'names':
[
null
],
'type': 'uint256',
'type_conversion': false
},
'children':
[
{
'attributes':
{
'argumentTypes':
[
{
'typeIdentifier': 't_uint256',
'typeString': 'uint256'
}
],
'isConstant': false,
'isLValue': false,
'isPure': false,
'lValueRequested': false,
'member_name': 'push',
'referencedDeclaration': null,
'type': 'function (uint256) returns (uint256)'
},
'children':
[
{
'attributes':
{
'argumentTypes': null,
'overloadedDeclarations':
[
null
],
'referencedDeclaration': 4,
'type': 'uint256[] storage ref',
'value': 'array'
},
'id': 51,
'name': 'Identifier',
'src': '394:5:0'
}
],
'id': 53,
'name': 'MemberAccess',
'src': '394:10:0'
},
{
'attributes':
{
'argumentTypes': null,
'overloadedDeclarations':
[
null
],
'referencedDeclaration': 45,
'type': 'uint256',
'value': 'i'
},
'id': 54,
'name': 'Identifier',
'src': '405:1:0'
}
],
'id': 55,
'name': 'FunctionCall',
'src': '394:13:0'
}
],
'id': 56,
'name': 'ExpressionStatement',
'src': '394:13:0'
},
{
'children':
[
{
'attributes':
{
'argumentTypes': null,
'isConstant': false,
'isLValue': false,
'isPure': false,
'lValueRequested': false,
'operator': '++',
'prefix': false,
'type': 'uint256'
},
'children':
[
{
'attributes':
{
'argumentTypes': null,
'overloadedDeclarations':
[
null
],
'referencedDeclaration': 45,
'type': 'uint256',
'value': 'i'
},
'id': 57,
'name': 'Identifier',
'src': '421:1:0'
}
],
'id': 58,
'name': 'UnaryOperation',
'src': '421:3:0'
}
],
'id': 59,
'name': 'ExpressionStatement',
'src': '421:3:0'
}
],
'id': 60,
'name': 'Block',
'src': '380:55:0'
}
],
'id': 61,
'name': 'WhileStatement',
'src': '365:70:0'
}
t.equal(common.isLoop(node1), true)
t.equal(common.isLoop(node2), true)
t.equal(common.isLoop(node3), true)
})
// #################### Complex Node Identification // #################### Complex Node Identification
test('staticAnalysisCommon.isBuiltinFunctionCall', function (t) { test('staticAnalysisCommon.isBuiltinFunctionCall', function (t) {
......
...@@ -37,6 +37,7 @@ var testFiles = [ ...@@ -37,6 +37,7 @@ var testFiles = [
'intDivisionTruncate.sol', 'intDivisionTruncate.sol',
'ERC20.sol', 'ERC20.sol',
'stringBytesLength.sol', 'stringBytesLength.sol',
'etherTransferInLoop.sol',
'forLoopIteratesOverDynamicArray.sol' 'forLoopIteratesOverDynamicArray.sol'
] ]
...@@ -77,6 +78,7 @@ test('Integration test thisLocal.js', function (t) { ...@@ -77,6 +78,7 @@ test('Integration test thisLocal.js', function (t) {
'intDivisionTruncate.sol': 0, 'intDivisionTruncate.sol': 0,
'ERC20.sol': 0, 'ERC20.sol': 0,
'stringBytesLength.sol': 0, 'stringBytesLength.sol': 0,
'etherTransferInLoop.sol': 0,
'forLoopIteratesOverDynamicArray.sol': 0 'forLoopIteratesOverDynamicArray.sol': 0
} }
...@@ -115,6 +117,7 @@ test('Integration test checksEffectsInteraction.js', function (t) { ...@@ -115,6 +117,7 @@ test('Integration test checksEffectsInteraction.js', function (t) {
'intDivisionTruncate.sol': 0, 'intDivisionTruncate.sol': 0,
'ERC20.sol': 0, 'ERC20.sol': 0,
'stringBytesLength.sol': 0, 'stringBytesLength.sol': 0,
'etherTransferInLoop.sol': 0,
'forLoopIteratesOverDynamicArray.sol': 0 'forLoopIteratesOverDynamicArray.sol': 0
} }
...@@ -153,6 +156,7 @@ test('Integration test constantFunctions.js', function (t) { ...@@ -153,6 +156,7 @@ test('Integration test constantFunctions.js', function (t) {
'intDivisionTruncate.sol': 0, 'intDivisionTruncate.sol': 0,
'ERC20.sol': 0, 'ERC20.sol': 0,
'stringBytesLength.sol': 0, 'stringBytesLength.sol': 0,
'etherTransferInLoop.sol': 0,
'forLoopIteratesOverDynamicArray.sol': 0 'forLoopIteratesOverDynamicArray.sol': 0
} }
...@@ -191,6 +195,7 @@ test('Integration test inlineAssembly.js', function (t) { ...@@ -191,6 +195,7 @@ test('Integration test inlineAssembly.js', function (t) {
'intDivisionTruncate.sol': 0, 'intDivisionTruncate.sol': 0,
'ERC20.sol': 0, 'ERC20.sol': 0,
'stringBytesLength.sol': 0, 'stringBytesLength.sol': 0,
'etherTransferInLoop.sol': 0,
'forLoopIteratesOverDynamicArray.sol': 0 'forLoopIteratesOverDynamicArray.sol': 0
} }
...@@ -229,6 +234,7 @@ test('Integration test txOrigin.js', function (t) { ...@@ -229,6 +234,7 @@ test('Integration test txOrigin.js', function (t) {
'intDivisionTruncate.sol': 0, 'intDivisionTruncate.sol': 0,
'ERC20.sol': 0, 'ERC20.sol': 0,
'stringBytesLength.sol': 0, 'stringBytesLength.sol': 0,
'etherTransferInLoop.sol': 0,
'forLoopIteratesOverDynamicArray.sol': 0 'forLoopIteratesOverDynamicArray.sol': 0
} }
...@@ -267,6 +273,7 @@ test('Integration test gasCosts.js', function (t) { ...@@ -267,6 +273,7 @@ test('Integration test gasCosts.js', function (t) {
'intDivisionTruncate.sol': 1, 'intDivisionTruncate.sol': 1,
'ERC20.sol': 2, 'ERC20.sol': 2,
'stringBytesLength.sol': 1, 'stringBytesLength.sol': 1,
'etherTransferInLoop.sol': 3,
'forLoopIteratesOverDynamicArray.sol': 1 'forLoopIteratesOverDynamicArray.sol': 1
} }
...@@ -305,6 +312,7 @@ test('Integration test similarVariableNames.js', function (t) { ...@@ -305,6 +312,7 @@ test('Integration test similarVariableNames.js', function (t) {
'intDivisionTruncate.sol': 0, 'intDivisionTruncate.sol': 0,
'ERC20.sol': 0, 'ERC20.sol': 0,
'stringBytesLength.sol': 0, 'stringBytesLength.sol': 0,
'etherTransferInLoop.sol': 0,
'forLoopIteratesOverDynamicArray.sol': 0 'forLoopIteratesOverDynamicArray.sol': 0
} }
...@@ -343,6 +351,7 @@ test('Integration test inlineAssembly.js', function (t) { ...@@ -343,6 +351,7 @@ test('Integration test inlineAssembly.js', function (t) {
'intDivisionTruncate.sol': 0, 'intDivisionTruncate.sol': 0,
'ERC20.sol': 0, 'ERC20.sol': 0,
'stringBytesLength.sol': 0, 'stringBytesLength.sol': 0,
'etherTransferInLoop.sol': 0,
'forLoopIteratesOverDynamicArray.sol': 0 'forLoopIteratesOverDynamicArray.sol': 0
} }
...@@ -381,6 +390,7 @@ test('Integration test blockTimestamp.js', function (t) { ...@@ -381,6 +390,7 @@ test('Integration test blockTimestamp.js', function (t) {
'intDivisionTruncate.sol': 0, 'intDivisionTruncate.sol': 0,
'ERC20.sol': 0, 'ERC20.sol': 0,
'stringBytesLength.sol': 0, 'stringBytesLength.sol': 0,
'etherTransferInLoop.sol': 0,
'forLoopIteratesOverDynamicArray.sol': 0 'forLoopIteratesOverDynamicArray.sol': 0
} }
...@@ -419,6 +429,7 @@ test('Integration test lowLevelCalls.js', function (t) { ...@@ -419,6 +429,7 @@ test('Integration test lowLevelCalls.js', function (t) {
'intDivisionTruncate.sol': 0, 'intDivisionTruncate.sol': 0,
'ERC20.sol': 0, 'ERC20.sol': 0,
'stringBytesLength.sol': 0, 'stringBytesLength.sol': 0,
'etherTransferInLoop.sol': 0,
'forLoopIteratesOverDynamicArray.sol': 0 'forLoopIteratesOverDynamicArray.sol': 0
} }
...@@ -457,6 +468,7 @@ test('Integration test blockBlockhash.js', function (t) { ...@@ -457,6 +468,7 @@ test('Integration test blockBlockhash.js', function (t) {
'intDivisionTruncate.sol': 0, 'intDivisionTruncate.sol': 0,
'ERC20.sol': 0, 'ERC20.sol': 0,
'stringBytesLength.sol': 0, 'stringBytesLength.sol': 0,
'etherTransferInLoop.sol': 0,
'forLoopIteratesOverDynamicArray.sol': 0 'forLoopIteratesOverDynamicArray.sol': 0
} }
...@@ -495,6 +507,7 @@ test('Integration test noReturn.js', function (t) { ...@@ -495,6 +507,7 @@ test('Integration test noReturn.js', function (t) {
'intDivisionTruncate.sol': 0, 'intDivisionTruncate.sol': 0,
'ERC20.sol': 0, 'ERC20.sol': 0,
'stringBytesLength.sol': 0, 'stringBytesLength.sol': 0,
'etherTransferInLoop.sol': 0,
'forLoopIteratesOverDynamicArray.sol': 0 'forLoopIteratesOverDynamicArray.sol': 0
} }
...@@ -533,6 +546,7 @@ test('Integration test selfdestruct.js', function (t) { ...@@ -533,6 +546,7 @@ test('Integration test selfdestruct.js', function (t) {
'ERC20.sol': 0, 'ERC20.sol': 0,
'intDivisionTruncate.sol': 5, 'intDivisionTruncate.sol': 5,
'stringBytesLength.sol': 0, 'stringBytesLength.sol': 0,
'etherTransferInLoop.sol': 0,
'forLoopIteratesOverDynamicArray.sol': 0 'forLoopIteratesOverDynamicArray.sol': 0
} }
...@@ -571,6 +585,7 @@ test('Integration test guardConditions.js', function (t) { ...@@ -571,6 +585,7 @@ test('Integration test guardConditions.js', function (t) {
'intDivisionTruncate.sol': 1, 'intDivisionTruncate.sol': 1,
'ERC20.sol': 0, 'ERC20.sol': 0,
'stringBytesLength.sol': 0, 'stringBytesLength.sol': 0,
'etherTransferInLoop.sol': 0,
'forLoopIteratesOverDynamicArray.sol': 0 'forLoopIteratesOverDynamicArray.sol': 0
} }
...@@ -609,6 +624,7 @@ test('Integration test deleteDynamicArrays.js', function (t) { ...@@ -609,6 +624,7 @@ test('Integration test deleteDynamicArrays.js', function (t) {
'intDivisionTruncate.sol': 0, 'intDivisionTruncate.sol': 0,
'ERC20.sol': 0, 'ERC20.sol': 0,
'stringBytesLength.sol': 0, 'stringBytesLength.sol': 0,
'etherTransferInLoop.sol': 0,
'forLoopIteratesOverDynamicArray.sol': 0 'forLoopIteratesOverDynamicArray.sol': 0
} }
...@@ -647,6 +663,7 @@ test('Integration test deleteFromDynamicArray.js', function (t) { ...@@ -647,6 +663,7 @@ test('Integration test deleteFromDynamicArray.js', function (t) {
'intDivisionTruncate.sol': 0, 'intDivisionTruncate.sol': 0,
'ERC20.sol': 0, 'ERC20.sol': 0,
'stringBytesLength.sol': 0, 'stringBytesLength.sol': 0,
'etherTransferInLoop.sol': 0,
'forLoopIteratesOverDynamicArray.sol': 0 'forLoopIteratesOverDynamicArray.sol': 0
} }
...@@ -685,6 +702,7 @@ test('Integration test assignAndCompare.js', function (t) { ...@@ -685,6 +702,7 @@ test('Integration test assignAndCompare.js', function (t) {
'intDivisionTruncate.sol': 0, 'intDivisionTruncate.sol': 0,
'ERC20.sol': 0, 'ERC20.sol': 0,
'stringBytesLength.sol': 0, 'stringBytesLength.sol': 0,
'etherTransferInLoop.sol': 0,
'forLoopIteratesOverDynamicArray.sol': 0 'forLoopIteratesOverDynamicArray.sol': 0
} }
...@@ -723,6 +741,7 @@ test('Integration test intDivisionTruncate.js', function (t) { ...@@ -723,6 +741,7 @@ test('Integration test intDivisionTruncate.js', function (t) {
'intDivisionTruncate.sol': 2, 'intDivisionTruncate.sol': 2,
'ERC20.sol': 0, 'ERC20.sol': 0,
'stringBytesLength.sol': 0, 'stringBytesLength.sol': 0,
'etherTransferInLoop.sol': 0,
'forLoopIteratesOverDynamicArray.sol': 0 'forLoopIteratesOverDynamicArray.sol': 0
} }
...@@ -761,6 +780,7 @@ test('Integration test erc20Decimal.js', function (t) { ...@@ -761,6 +780,7 @@ test('Integration test erc20Decimal.js', function (t) {
'intDivisionTruncate.sol': 0, 'intDivisionTruncate.sol': 0,
'ERC20.sol': 1, 'ERC20.sol': 1,
'stringBytesLength.sol': 0, 'stringBytesLength.sol': 0,
'etherTransferInLoop.sol': 0,
'forLoopIteratesOverDynamicArray.sol': 0 'forLoopIteratesOverDynamicArray.sol': 0
} }
...@@ -799,6 +819,7 @@ test('Integration test stringBytesLength.js', function (t) { ...@@ -799,6 +819,7 @@ test('Integration test stringBytesLength.js', function (t) {
'intDivisionTruncate.sol': 0, 'intDivisionTruncate.sol': 0,
'ERC20.sol': 0, 'ERC20.sol': 0,
'stringBytesLength.sol': 1, 'stringBytesLength.sol': 1,
'etherTransferInLoop.sol': 0,
'forLoopIteratesOverDynamicArray.sol': 0 'forLoopIteratesOverDynamicArray.sol': 0
} }
...@@ -807,6 +828,45 @@ test('Integration test stringBytesLength.js', function (t) { ...@@ -807,6 +828,45 @@ test('Integration test stringBytesLength.js', function (t) {
}) })
}) })
test('Integration test etherTransferInLoop.js', function (t) {
t.plan(testFiles.length)
var module = require('../../src/solidity-analyzer/modules/etherTransferInLoop')
var lengthCheck = {
'KingOfTheEtherThrone.sol': 0,
'assembly.sol': 0,
'ballot.sol': 0,
'ballot_reentrant.sol': 0,
'ballot_withoutWarnings.sol': 0,
'cross_contract.sol': 0,
'inheritance.sol': 0,
'modifier1.sol': 0,
'modifier2.sol': 0,
'notReentrant.sol': 0,
'structReentrant.sol': 0,
'thisLocal.sol': 0,
'globals.sol': 0,
'library.sol': 0,
'transfer.sol': 0,
'ctor.sol': 0,
'forgottenReturn.sol': 0,
'selfdestruct.sol': 0,
'deleteDynamicArray.sol': 0,
'deleteFromDynamicArray.sol': 0,
'blockLevelCompare.sol': 0,
'intDivisionTruncate.sol': 0,
'ERC20.sol': 0,
'stringBytesLength.sol': 0,
'etherTransferInLoop.sol': 3,
'forLoopIteratesOverDynamicArray.sol': 0
}
runModuleOnFiles(module, t, (file, report) => {
t.equal(report.length, lengthCheck[file], `${file} has right amount of etherTransferInLoop warnings`)
})
})
test('Integration test forLoopIteratesOverDynamicArray.js', function (t) { test('Integration test forLoopIteratesOverDynamicArray.js', function (t) {
t.plan(testFiles.length) t.plan(testFiles.length)
...@@ -837,6 +897,7 @@ test('Integration test forLoopIteratesOverDynamicArray.js', function (t) { ...@@ -837,6 +897,7 @@ test('Integration test forLoopIteratesOverDynamicArray.js', function (t) {
'intDivisionTruncate.sol': 0, 'intDivisionTruncate.sol': 0,
'ERC20.sol': 0, 'ERC20.sol': 0,
'stringBytesLength.sol': 0, 'stringBytesLength.sol': 0,
'etherTransferInLoop.sol': 0,
'forLoopIteratesOverDynamicArray.sol': 1 'forLoopIteratesOverDynamicArray.sol': 1
} }
......
...@@ -37,6 +37,7 @@ var testFiles = [ ...@@ -37,6 +37,7 @@ var testFiles = [
'intDivisionTruncate.sol', 'intDivisionTruncate.sol',
'ERC20.sol', 'ERC20.sol',
'stringBytesLength.sol', 'stringBytesLength.sol',
'etherTransferInLoop.sol',
'forLoopIteratesOverDynamicArray.sol' 'forLoopIteratesOverDynamicArray.sol'
] ]
...@@ -77,6 +78,7 @@ test('Integration test thisLocal.js', function (t) { ...@@ -77,6 +78,7 @@ test('Integration test thisLocal.js', function (t) {
'intDivisionTruncate.sol': 0, 'intDivisionTruncate.sol': 0,
'ERC20.sol': 0, 'ERC20.sol': 0,
'stringBytesLength.sol': 0, 'stringBytesLength.sol': 0,
'etherTransferInLoop.sol': 0,
'forLoopIteratesOverDynamicArray.sol': 0 'forLoopIteratesOverDynamicArray.sol': 0
} }
...@@ -115,6 +117,7 @@ test('Integration test checksEffectsInteraction.js', function (t) { ...@@ -115,6 +117,7 @@ test('Integration test checksEffectsInteraction.js', function (t) {
'intDivisionTruncate.sol': 0, 'intDivisionTruncate.sol': 0,
'ERC20.sol': 0, 'ERC20.sol': 0,
'stringBytesLength.sol': 0, 'stringBytesLength.sol': 0,
'etherTransferInLoop.sol': 0,
'forLoopIteratesOverDynamicArray.sol': 0 'forLoopIteratesOverDynamicArray.sol': 0
} }
...@@ -153,6 +156,7 @@ test('Integration test constantFunctions.js', function (t) { ...@@ -153,6 +156,7 @@ test('Integration test constantFunctions.js', function (t) {
'intDivisionTruncate.sol': 0, 'intDivisionTruncate.sol': 0,
'ERC20.sol': 0, 'ERC20.sol': 0,
'stringBytesLength.sol': 0, 'stringBytesLength.sol': 0,
'etherTransferInLoop.sol': 0,
'forLoopIteratesOverDynamicArray.sol': 0 'forLoopIteratesOverDynamicArray.sol': 0
} }
...@@ -191,6 +195,7 @@ test('Integration test inlineAssembly.js', function (t) { ...@@ -191,6 +195,7 @@ test('Integration test inlineAssembly.js', function (t) {
'intDivisionTruncate.sol': 0, 'intDivisionTruncate.sol': 0,
'ERC20.sol': 0, 'ERC20.sol': 0,
'stringBytesLength.sol': 0, 'stringBytesLength.sol': 0,
'etherTransferInLoop.sol': 0,
'forLoopIteratesOverDynamicArray.sol': 0 'forLoopIteratesOverDynamicArray.sol': 0
} }
...@@ -229,6 +234,7 @@ test('Integration test txOrigin.js', function (t) { ...@@ -229,6 +234,7 @@ test('Integration test txOrigin.js', function (t) {
'intDivisionTruncate.sol': 0, 'intDivisionTruncate.sol': 0,
'ERC20.sol': 0, 'ERC20.sol': 0,
'stringBytesLength.sol': 0, 'stringBytesLength.sol': 0,
'etherTransferInLoop.sol': 0,
'forLoopIteratesOverDynamicArray.sol': 0 'forLoopIteratesOverDynamicArray.sol': 0
} }
...@@ -267,6 +273,7 @@ test('Integration test gasCosts.js', function (t) { ...@@ -267,6 +273,7 @@ test('Integration test gasCosts.js', function (t) {
'intDivisionTruncate.sol': 1, 'intDivisionTruncate.sol': 1,
'ERC20.sol': 2, 'ERC20.sol': 2,
'stringBytesLength.sol': 1, 'stringBytesLength.sol': 1,
'etherTransferInLoop.sol': 3,
'forLoopIteratesOverDynamicArray.sol': 1 'forLoopIteratesOverDynamicArray.sol': 1
} }
...@@ -305,6 +312,7 @@ test('Integration test similarVariableNames.js', function (t) { ...@@ -305,6 +312,7 @@ test('Integration test similarVariableNames.js', function (t) {
'intDivisionTruncate.sol': 0, 'intDivisionTruncate.sol': 0,
'ERC20.sol': 0, 'ERC20.sol': 0,
'stringBytesLength.sol': 0, 'stringBytesLength.sol': 0,
'etherTransferInLoop.sol': 0,
'forLoopIteratesOverDynamicArray.sol': 0 'forLoopIteratesOverDynamicArray.sol': 0
} }
...@@ -343,6 +351,7 @@ test('Integration test inlineAssembly.js', function (t) { ...@@ -343,6 +351,7 @@ test('Integration test inlineAssembly.js', function (t) {
'intDivisionTruncate.sol': 0, 'intDivisionTruncate.sol': 0,
'ERC20.sol': 0, 'ERC20.sol': 0,
'stringBytesLength.sol': 0, 'stringBytesLength.sol': 0,
'etherTransferInLoop.sol': 0,
'forLoopIteratesOverDynamicArray.sol': 0 'forLoopIteratesOverDynamicArray.sol': 0
} }
...@@ -381,6 +390,7 @@ test('Integration test blockTimestamp.js', function (t) { ...@@ -381,6 +390,7 @@ test('Integration test blockTimestamp.js', function (t) {
'intDivisionTruncate.sol': 0, 'intDivisionTruncate.sol': 0,
'ERC20.sol': 0, 'ERC20.sol': 0,
'stringBytesLength.sol': 0, 'stringBytesLength.sol': 0,
'etherTransferInLoop.sol': 0,
'forLoopIteratesOverDynamicArray.sol': 0 'forLoopIteratesOverDynamicArray.sol': 0
} }
...@@ -419,6 +429,7 @@ test('Integration test lowLevelCalls.js', function (t) { ...@@ -419,6 +429,7 @@ test('Integration test lowLevelCalls.js', function (t) {
'intDivisionTruncate.sol': 0, 'intDivisionTruncate.sol': 0,
'ERC20.sol': 0, 'ERC20.sol': 0,
'stringBytesLength.sol': 0, 'stringBytesLength.sol': 0,
'etherTransferInLoop.sol': 0,
'forLoopIteratesOverDynamicArray.sol': 0 'forLoopIteratesOverDynamicArray.sol': 0
} }
...@@ -457,6 +468,7 @@ test('Integration test blockBlockhash.js', function (t) { ...@@ -457,6 +468,7 @@ test('Integration test blockBlockhash.js', function (t) {
'intDivisionTruncate.sol': 0, 'intDivisionTruncate.sol': 0,
'ERC20.sol': 0, 'ERC20.sol': 0,
'stringBytesLength.sol': 0, 'stringBytesLength.sol': 0,
'etherTransferInLoop.sol': 0,
'forLoopIteratesOverDynamicArray.sol': 0 'forLoopIteratesOverDynamicArray.sol': 0
} }
...@@ -538,6 +550,7 @@ test('Integration test selfdestruct.js', function (t) { ...@@ -538,6 +550,7 @@ test('Integration test selfdestruct.js', function (t) {
'ERC20.sol': 0, 'ERC20.sol': 0,
'intDivisionTruncate.sol': 5, 'intDivisionTruncate.sol': 5,
'stringBytesLength.sol': 0, 'stringBytesLength.sol': 0,
'etherTransferInLoop.sol': 0,
'forLoopIteratesOverDynamicArray.sol': 0 'forLoopIteratesOverDynamicArray.sol': 0
} }
...@@ -576,6 +589,7 @@ test('Integration test guardConditions.js', function (t) { ...@@ -576,6 +589,7 @@ test('Integration test guardConditions.js', function (t) {
'intDivisionTruncate.sol': 1, 'intDivisionTruncate.sol': 1,
'ERC20.sol': 0, 'ERC20.sol': 0,
'stringBytesLength.sol': 0, 'stringBytesLength.sol': 0,
'etherTransferInLoop.sol': 0,
'forLoopIteratesOverDynamicArray.sol': 0 'forLoopIteratesOverDynamicArray.sol': 0
} }
...@@ -614,6 +628,7 @@ test('Integration test deleteDynamicArrays.js', function (t) { ...@@ -614,6 +628,7 @@ test('Integration test deleteDynamicArrays.js', function (t) {
'intDivisionTruncate.sol': 0, 'intDivisionTruncate.sol': 0,
'ERC20.sol': 0, 'ERC20.sol': 0,
'stringBytesLength.sol': 0, 'stringBytesLength.sol': 0,
'etherTransferInLoop.sol': 0,
'forLoopIteratesOverDynamicArray.sol': 0 'forLoopIteratesOverDynamicArray.sol': 0
} }
...@@ -652,6 +667,7 @@ test('Integration test deleteFromDynamicArray.js', function (t) { ...@@ -652,6 +667,7 @@ test('Integration test deleteFromDynamicArray.js', function (t) {
'intDivisionTruncate.sol': 0, 'intDivisionTruncate.sol': 0,
'ERC20.sol': 0, 'ERC20.sol': 0,
'stringBytesLength.sol': 0, 'stringBytesLength.sol': 0,
'etherTransferInLoop.sol': 0,
'forLoopIteratesOverDynamicArray.sol': 0 'forLoopIteratesOverDynamicArray.sol': 0
} }
...@@ -690,6 +706,7 @@ test('Integration test assignAndCompare.js', function (t) { ...@@ -690,6 +706,7 @@ test('Integration test assignAndCompare.js', function (t) {
'intDivisionTruncate.sol': 0, 'intDivisionTruncate.sol': 0,
'ERC20.sol': 0, 'ERC20.sol': 0,
'stringBytesLength.sol': 0, 'stringBytesLength.sol': 0,
'etherTransferInLoop.sol': 0,
'forLoopIteratesOverDynamicArray.sol': 0 'forLoopIteratesOverDynamicArray.sol': 0
} }
...@@ -728,6 +745,7 @@ test('Integration test intDivisionTruncate.js', function (t) { ...@@ -728,6 +745,7 @@ test('Integration test intDivisionTruncate.js', function (t) {
'intDivisionTruncate.sol': 2, 'intDivisionTruncate.sol': 2,
'ERC20.sol': 0, 'ERC20.sol': 0,
'stringBytesLength.sol': 0, 'stringBytesLength.sol': 0,
'etherTransferInLoop.sol': 0,
'forLoopIteratesOverDynamicArray.sol': 0 'forLoopIteratesOverDynamicArray.sol': 0
} }
...@@ -766,6 +784,7 @@ test('Integration test erc20Decimal.js', function (t) { ...@@ -766,6 +784,7 @@ test('Integration test erc20Decimal.js', function (t) {
'intDivisionTruncate.sol': 0, 'intDivisionTruncate.sol': 0,
'ERC20.sol': 1, 'ERC20.sol': 1,
'stringBytesLength.sol': 0, 'stringBytesLength.sol': 0,
'etherTransferInLoop.sol': 0,
'forLoopIteratesOverDynamicArray.sol': 0 'forLoopIteratesOverDynamicArray.sol': 0
} }
...@@ -804,6 +823,7 @@ test('Integration test stringBytesLength.js', function (t) { ...@@ -804,6 +823,7 @@ test('Integration test stringBytesLength.js', function (t) {
'intDivisionTruncate.sol': 0, 'intDivisionTruncate.sol': 0,
'ERC20.sol': 0, 'ERC20.sol': 0,
'stringBytesLength.sol': 1, 'stringBytesLength.sol': 1,
'etherTransferInLoop.sol': 0,
'forLoopIteratesOverDynamicArray.sol': 0 'forLoopIteratesOverDynamicArray.sol': 0
} }
...@@ -812,6 +832,45 @@ test('Integration test stringBytesLength.js', function (t) { ...@@ -812,6 +832,45 @@ test('Integration test stringBytesLength.js', function (t) {
}) })
}) })
test('Integration test etherTransferInLoop.js', function (t) {
t.plan(testFiles.length)
var module = require('../../src/solidity-analyzer/modules/etherTransferInLoop')
var lengthCheck = {
'KingOfTheEtherThrone.sol': 0,
'assembly.sol': 0,
'ballot.sol': 0,
'ballot_reentrant.sol': 0,
'ballot_withoutWarnings.sol': 0,
'cross_contract.sol': 0,
'inheritance.sol': 0,
'modifier1.sol': 0,
'modifier2.sol': 0,
'notReentrant.sol': 0,
'structReentrant.sol': 0,
'thisLocal.sol': 0,
'globals.sol': 0,
'library.sol': 0,
'transfer.sol': 0,
'ctor.sol': 0,
'forgottenReturn.sol': 0,
'selfdestruct.sol': 0,
'deleteDynamicArray.sol': 0,
'deleteFromDynamicArray.sol': 0,
'blockLevelCompare.sol': 0,
'intDivisionTruncate.sol': 0,
'ERC20.sol': 0,
'stringBytesLength.sol': 0,
'etherTransferInLoop.sol': 3,
'forLoopIteratesOverDynamicArray.sol': 0
}
runModuleOnFiles(module, t, (file, report) => {
t.equal(report.length, lengthCheck[file], `${file} has right amount of etherTransferInLoop warnings`)
})
})
test('Integration test forLoopIteratesOverDynamicArray.js', function (t) { test('Integration test forLoopIteratesOverDynamicArray.js', function (t) {
t.plan(testFiles.length) t.plan(testFiles.length)
...@@ -842,6 +901,7 @@ test('Integration test forLoopIteratesOverDynamicArray.js', function (t) { ...@@ -842,6 +901,7 @@ test('Integration test forLoopIteratesOverDynamicArray.js', function (t) {
'intDivisionTruncate.sol': 0, 'intDivisionTruncate.sol': 0,
'ERC20.sol': 0, 'ERC20.sol': 0,
'stringBytesLength.sol': 0, 'stringBytesLength.sol': 0,
'etherTransferInLoop.sol': 0,
'forLoopIteratesOverDynamicArray.sol': 1 'forLoopIteratesOverDynamicArray.sol': 1
} }
......
pragma solidity ^0.4.24;
contract etherTransferInLoop {
address owner;
constructor() public {
owner = msg.sender;
}
function transferInForLoop(uint index) public {
for (uint i = index; i < 10; i++) {
owner.transfer(i);
}
}
function transferInWhileLoop(uint index) public {
uint i = index;
while (i < 10) {
owner.transfer(i);
i++;
}
}
function transferInDoWhileLoop(uint index) public {
uint i = index;
do {
owner.transfer(i);
i++;
} while (i < 10);
}
}
\ No newline at end of file
pragma solidity ^0.4.9;
contract loops {
uint[] array;
constructor(uint[] memory _array) public {
array = _array;
}
function fnWithForLoop(uint index) public {
for (uint i = index; i < 10; i++) {
array.push(i);
}
}
function fnWithWhileLoop(uint index) public {
uint i = index;
while (i < 10) {
array.push(i);
i++;
}
}
function fnWithDoWhileLoop(uint index) public {
uint i = index;
do{
array.push(i);
i++;
}while (i < 10);
}
}
\ No newline at end of file
pragma solidity >=0.4.9 <0.6.0;
contract etherTransferInLoop {
address payable owner;
constructor() public {
owner = msg.sender;
}
function transferInForLoop(uint index) public {
for (uint i = index; i < 10; i++) {
owner.transfer(i);
}
}
function transferInWhileLoop(uint index) public {
uint i = index;
while (i < 10) {
owner.transfer(i);
i++;
}
}
function transferInDoWhileLoop(uint index) public {
uint i = index;
do {
owner.transfer(i);
i++;
} while (i < 10);
}
}
\ No newline at end of file
pragma solidity >=0.4.9 <0.6.0;
contract loops {
uint[] array;
constructor(uint[] memory _array) public {
array = _array;
}
function fnWithForLoop(uint index) public {
for (uint i = index; i < 10; i++) {
array.push(i);
}
}
function fnWithWhileLoop(uint index) public {
uint i = index;
while (i < 10) {
array.push(i);
i++;
}
}
function fnWithDoWhileLoop(uint index) public {
uint i = index;
do{
array.push(i);
i++;
}while (i < 10);
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment