parent
d68814df4b
commit
44327da285
@ -0,0 +1,54 @@ |
||||
'use strict' |
||||
/** |
||||
* Crawl the given AST through the function walk(ast, callback) |
||||
*/ |
||||
function AstWalker () { |
||||
} |
||||
|
||||
/** |
||||
* visit all the AST nodes |
||||
* |
||||
* @param {Object} ast - AST node |
||||
* @param {Object or Function} callback - if (Function) the function will be called for every node. |
||||
* - if (Object) callback[<Node Type>] will be called for |
||||
* every node of type <Node Type>. callback["*"] will be called fo all other nodes. |
||||
* in each case, if the callback returns false it does not descend into children. |
||||
* If no callback for the current type, children are visited. |
||||
*/ |
||||
AstWalker.prototype.walk = function (ast, callback) { |
||||
if (callback instanceof Function) { |
||||
callback = {'*': callback} |
||||
} |
||||
if (!('*' in callback)) { |
||||
callback['*'] = function () { return true } |
||||
} |
||||
if (manageCallBack(ast, callback) && ast.children && ast.children.length > 0) { |
||||
for (var k in ast.children) { |
||||
var child = ast.children[k] |
||||
this.walk(child, callback) |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* walk the given @astList |
||||
* |
||||
* @param {Object} sourcesList - sources list (containing root AST node) |
||||
* @param {Function} - callback used by AstWalker to compute response |
||||
*/ |
||||
AstWalker.prototype.walkAstList = function (sourcesList, callback) { |
||||
var walker = new AstWalker() |
||||
for (var k in sourcesList) { |
||||
walker.walk(sourcesList[k].AST, callback) |
||||
} |
||||
} |
||||
|
||||
function manageCallBack (node, callback) { |
||||
if (node.name in callback) { |
||||
return callback[node.name](node) |
||||
} else { |
||||
return callback['*'](node) |
||||
} |
||||
} |
||||
|
||||
module.exports = AstWalker |
@ -1,47 +1,192 @@ |
||||
// var test = require('tape')
|
||||
|
||||
// var common = require('../../babelify-src/app/staticanalysis/modules/staticAnalysisCommon')
|
||||
// var StatRunner = require('../../babelify-src/app/staticanalysis/staticAnalysisRunner')
|
||||
// var utils = require('../../babelify-src/app/utils')
|
||||
// var Compiler = require('../../babelify-src/app/compiler')
|
||||
|
||||
// var fs = require('fs')
|
||||
// var path = require('path')
|
||||
|
||||
// var testFiles = [
|
||||
// '/test-contracts/KingOfTheEtherThrone.sol',
|
||||
// '/test-contracts/assembly.sol',
|
||||
// '/test-contracts/ballot.sol',
|
||||
// '/test-contracts/ballot_reentrant.sol',
|
||||
// '/test-contracts/ballot_withoutWarning.sol',
|
||||
// '/test-contracts/cross_contract.sol',
|
||||
// '/test-contracts/inheritance.sol',
|
||||
// '/test-contracts/notReentrant.sol',
|
||||
// '/test-contracts/structReentrant.sol',
|
||||
// '/test-contracts/thisLocal.sol',
|
||||
// '/test-contracts/modifier1.sol',
|
||||
// '/test-contracts/modifier2.sol'
|
||||
// ]
|
||||
|
||||
// test('thisLocal.js', function (t) {
|
||||
// t.plan(0)
|
||||
|
||||
// var module = require('../../babelify-src/app/staticanalysis/modules/thisLocal')
|
||||
|
||||
// runModuleOnFiles(module, t)
|
||||
// })
|
||||
|
||||
// function runModuleOnFiles (module, t) {
|
||||
// var fakeImport = function (url, cb) { cb('Not implemented') }
|
||||
// var compiler = new Compiler(fakeImport)
|
||||
// var statRunner = new StatRunner()
|
||||
|
||||
// testFiles.map((fileName) => {
|
||||
// var contents = fs.readFileSync(path.join(__dirname, fileName), 'utf8')
|
||||
// var compres = compiler.compile({ 'test': contents }, 'test')
|
||||
|
||||
// statRunner.runWithModuleList(compres, [{ name: module.name, mod: new module.Module() }], (reports) => {
|
||||
// reports.map((r) => t.comment(r.warning))
|
||||
// })
|
||||
// })
|
||||
// }
|
||||
var test = require('tape') |
||||
|
||||
var StatRunner = require('../../babelify-src/app/staticanalysis/staticAnalysisRunner') |
||||
// const util = require('util')
|
||||
|
||||
var solc = require('solc') |
||||
|
||||
var fs = require('fs') |
||||
var path = require('path') |
||||
|
||||
var testFiles = [ |
||||
'KingOfTheEtherThrone.sol', |
||||
'assembly.sol', |
||||
'ballot.sol', |
||||
'ballot_reentrant.sol', |
||||
'ballot_withoutWarnings.sol', |
||||
'cross_contract.sol', |
||||
'inheritance.sol', |
||||
'modifier1.sol', |
||||
'modifier2.sol', |
||||
'notReentrant.sol', |
||||
'structReentrant.sol', |
||||
'thisLocal.sol' |
||||
] |
||||
|
||||
var testFileAsts = {} |
||||
|
||||
testFiles.forEach((fileName) => { |
||||
var contents = fs.readFileSync(path.join(__dirname, 'test-contracts', fileName), 'utf8') |
||||
testFileAsts[fileName] = solc.compile(contents, 0) |
||||
}) |
||||
|
||||
test('Integration test thisLocal.js', function (t) { |
||||
t.plan(testFiles.length) |
||||
|
||||
var module = require('../../babelify-src/app/staticanalysis/modules/thisLocal') |
||||
|
||||
var lengthCheck = { |
||||
'KingOfTheEtherThrone.sol': 0, |
||||
'assembly.sol': 0, |
||||
'ballot.sol': 0, |
||||
'ballot_reentrant.sol': 1, |
||||
'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': 1 |
||||
} |
||||
|
||||
runModuleOnFiles(module, t, (file, report) => { |
||||
t.equal(report.length, lengthCheck[file], `${file} has right amount of this local warnings`) |
||||
}) |
||||
}) |
||||
|
||||
test('Integration test checksEffectsInteraction.js', function (t) { |
||||
t.plan(testFiles.length) |
||||
|
||||
var module = require('../../babelify-src/app/staticanalysis/modules/checksEffectsInteraction') |
||||
|
||||
var lengthCheck = { |
||||
'KingOfTheEtherThrone.sol': 1, |
||||
'assembly.sol': 0, |
||||
'ballot.sol': 0, |
||||
'ballot_reentrant.sol': 1, |
||||
'ballot_withoutWarnings.sol': 0, |
||||
'cross_contract.sol': 0, |
||||
'inheritance.sol': 1, |
||||
'modifier1.sol': 0, |
||||
'modifier2.sol': 0, |
||||
'notReentrant.sol': 0, |
||||
'structReentrant.sol': 1, |
||||
'thisLocal.sol': 0 |
||||
} |
||||
|
||||
runModuleOnFiles(module, t, (file, report) => { |
||||
t.equal(report.length, lengthCheck[file], `${file} has right amount of checks-effects-interaction warnings`) |
||||
}) |
||||
}) |
||||
|
||||
test('Integration test constatnFunctions.js', function (t) { |
||||
t.plan(testFiles.length) |
||||
|
||||
var module = require('../../babelify-src/app/staticanalysis/modules/constantFunctions') |
||||
|
||||
var lengthCheck = { |
||||
'KingOfTheEtherThrone.sol': 0, |
||||
'assembly.sol': 0, |
||||
'ballot.sol': 0, |
||||
'ballot_reentrant.sol': 0, |
||||
'ballot_withoutWarnings.sol': 0, |
||||
'cross_contract.sol': 1, |
||||
'inheritance.sol': 0, |
||||
'modifier1.sol': 1, |
||||
'modifier2.sol': 0, |
||||
'notReentrant.sol': 0, |
||||
'structReentrant.sol': 0, |
||||
'thisLocal.sol': 1 |
||||
} |
||||
|
||||
runModuleOnFiles(module, t, (file, report) => { |
||||
t.equal(report.length, lengthCheck[file], `${file} has right amount of constant warnings`) |
||||
}) |
||||
}) |
||||
|
||||
test('Integration test constantFunctions.js', function (t) { |
||||
t.plan(testFiles.length) |
||||
|
||||
var module = require('../../babelify-src/app/staticanalysis/modules/inlineAssembly') |
||||
|
||||
var lengthCheck = { |
||||
'KingOfTheEtherThrone.sol': 0, |
||||
'assembly.sol': 2, |
||||
'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 |
||||
} |
||||
|
||||
runModuleOnFiles(module, t, (file, report) => { |
||||
t.equal(report.length, lengthCheck[file], `${file} has right amount of inline assembly warnings`) |
||||
}) |
||||
}) |
||||
|
||||
test('Integration test txOrigin.js', function (t) { |
||||
t.plan(testFiles.length) |
||||
|
||||
var module = require('../../babelify-src/app/staticanalysis/modules/txOrigin') |
||||
|
||||
var lengthCheck = { |
||||
'KingOfTheEtherThrone.sol': 0, |
||||
'assembly.sol': 1, |
||||
'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 |
||||
} |
||||
|
||||
runModuleOnFiles(module, t, (file, report) => { |
||||
t.equal(report.length, lengthCheck[file], `${file} has right amount of tx.origin warnings`) |
||||
}) |
||||
}) |
||||
|
||||
test('Integration test gasCosts.js', function (t) { |
||||
t.plan(testFiles.length) |
||||
|
||||
var module = require('../../babelify-src/app/staticanalysis/modules/gasCosts') |
||||
|
||||
var lengthCheck = { |
||||
'KingOfTheEtherThrone.sol': 2, |
||||
'assembly.sol': 2, |
||||
'ballot.sol': 3, |
||||
'ballot_reentrant.sol': 2, |
||||
'ballot_withoutWarnings.sol': 0, |
||||
'cross_contract.sol': 1, |
||||
'inheritance.sol': 1, |
||||
'modifier1.sol': 0, |
||||
'modifier2.sol': 1, |
||||
'notReentrant.sol': 1, |
||||
'structReentrant.sol': 1, |
||||
'thisLocal.sol': 2 |
||||
} |
||||
|
||||
runModuleOnFiles(module, t, (file, report) => { |
||||
t.equal(report.length, lengthCheck[file], `${file} has right amount of gasCost warnings`) |
||||
}) |
||||
}) |
||||
|
||||
// #################### Helpers
|
||||
function runModuleOnFiles (module, t, cb) { |
||||
var statRunner = new StatRunner() |
||||
|
||||
testFiles.forEach((fileName) => { |
||||
statRunner.runWithModuleList(testFileAsts[fileName], [{ name: module.name, mod: new module.Module() }], (reports) => { |
||||
cb(fileName, reports[0].report) |
||||
}) |
||||
}) |
||||
} |
||||
|
Loading…
Reference in new issue