commit
6b135401f6
@ -0,0 +1,3 @@ |
||||
module.exports = [ |
||||
require('./txOrigin') |
||||
] |
@ -0,0 +1,34 @@ |
||||
var name = 'tx origin' |
||||
var desc = 'warn if tx.origin is used' |
||||
|
||||
function txOrigin () { |
||||
this.txOriginNode = [] |
||||
} |
||||
|
||||
txOrigin.prototype.visit = function (node) { |
||||
if (node.name === 'MemberAccess' && |
||||
node.attributes.member_name === 'origin' && |
||||
node.attributes.type === 'address' && |
||||
node.children && node.children.length && |
||||
node.children[0].attributes.type === 'tx' && |
||||
node.children[0].attributes.value === 'tx') { |
||||
this.txOriginNode.push(node) |
||||
} |
||||
} |
||||
|
||||
txOrigin.prototype.report = function (node) { |
||||
var report = this.txOriginNode.length + ' use of tx.origin\n' |
||||
this.txOriginNode.map(function (item, i) { |
||||
report += item.src + '\n' |
||||
}) |
||||
return { |
||||
name: name, |
||||
report: report |
||||
} |
||||
} |
||||
|
||||
module.exports = { |
||||
name: name, |
||||
description: desc, |
||||
Module: txOrigin |
||||
} |
@ -0,0 +1,30 @@ |
||||
'use strict' |
||||
var AstWalker = require('ethereum-remix').util.AstWalker |
||||
var list = require('./modules/list') |
||||
|
||||
function staticAnalysisRunner () { |
||||
} |
||||
|
||||
staticAnalysisRunner.prototype.run = function (ast, toRun, callback) { |
||||
var walker = new AstWalker() |
||||
for (var k in ast) { |
||||
walker.walk(ast[k].AST, {'*': function (node) { |
||||
toRun.map(function (item, i) { |
||||
item.visit(node) |
||||
}) |
||||
return true |
||||
}}) |
||||
} |
||||
|
||||
var reports = [] |
||||
toRun.map(function (item, i) { |
||||
reports.push(item.report()) |
||||
}) |
||||
callback(reports) |
||||
} |
||||
|
||||
staticAnalysisRunner.prototype.modules = function () { |
||||
return list |
||||
} |
||||
|
||||
module.exports = staticAnalysisRunner |
@ -0,0 +1,79 @@ |
||||
'use strict' |
||||
var StaticAnalysisRunner = require('./staticAnalysisRunner.js') |
||||
var yo = require('yo-yo') |
||||
var $ = require('jquery') |
||||
|
||||
function staticAnalysisView (compiler, renderer) { |
||||
this.view = null |
||||
this.renderer = renderer |
||||
this.runner = new StaticAnalysisRunner() |
||||
this.modulesView = renderModules(this.runner.modules()) |
||||
this.lastASTs = null |
||||
var self = this |
||||
compiler.event.register('compilationFinished', function (success, data, source) { |
||||
self.lastASTs = null |
||||
if (success) { |
||||
self.lastASTs = data.sources |
||||
} |
||||
}) |
||||
} |
||||
|
||||
staticAnalysisView.prototype.render = function () { |
||||
var self = this |
||||
var view = yo`<div>
|
||||
<strong>Static Analysis</strong> |
||||
<div>Select analyser to run against current compiled contracts</div> |
||||
${this.modulesView} |
||||
<div> |
||||
<button onclick=${function () { self.run() }} >Run</button> |
||||
</div> |
||||
<div id='staticanalysisresult'></div> |
||||
</div>` |
||||
if (!this.view) { |
||||
this.view = view |
||||
} |
||||
return view |
||||
} |
||||
|
||||
staticAnalysisView.prototype.selectedModules = function () { |
||||
if (!this.view) { |
||||
return [] |
||||
} |
||||
var selected = this.view.querySelectorAll('[name="staticanalysismodule"]') |
||||
var toRun = [] |
||||
for (var i = 0; i < selected.length; i++) { |
||||
var el = selected[i] |
||||
if (el.checked) { |
||||
var analyser = this.runner.modules()[el.attributes['index'].value] |
||||
toRun.push(new analyser.Module()) |
||||
} |
||||
} |
||||
return toRun |
||||
} |
||||
|
||||
staticAnalysisView.prototype.run = function () { |
||||
if (!this.view) { |
||||
return |
||||
} |
||||
var selected = this.selectedModules() |
||||
var warningContainer = $('#staticanalysisresult') |
||||
warningContainer.empty() |
||||
if (this.lastASTs) { |
||||
var self = this |
||||
this.runner.run(this.lastASTs, selected, function (results) { |
||||
results.map(function (item, i) { |
||||
self.renderer.error(item.name + ':\n\n' + item.report, warningContainer, null, 'warning') |
||||
}) |
||||
}) |
||||
} else { |
||||
warningContainer.html('No compiled AST available') |
||||
} |
||||
} |
||||
|
||||
function renderModules (modules) { |
||||
return modules.map(function (item, i) { |
||||
return yo`<div><input type="checkbox" name="staticanalysismodule" checked='true' index=${i} >${item.name} (${item.description})</div>` |
||||
}) |
||||
} |
||||
|
||||
module.exports = staticAnalysisView |
@ -0,0 +1,36 @@ |
||||
'use strict' |
||||
var contractHelper = require('../helpers/contracts') |
||||
var init = require('../helpers/init') |
||||
var sauce = require('./sauce') |
||||
|
||||
var sources = { |
||||
'sources': { |
||||
'Untitled': `contract test1 { address test = tx.origin; } contract test2 {}` |
||||
} |
||||
} |
||||
|
||||
module.exports = { |
||||
before: function (browser, done) { |
||||
init(browser, done) |
||||
}, |
||||
'@sources': function () { |
||||
return sources |
||||
}, |
||||
'Static Analysis': function (browser) { |
||||
runTests(browser) |
||||
}, |
||||
tearDown: sauce |
||||
} |
||||
|
||||
function runTests (browser) { |
||||
browser |
||||
.waitForElementVisible('.newFile', 10000) |
||||
contractHelper.testContracts(browser, sources.sources.Untitled, ['test1', 'test2'], function () { |
||||
browser |
||||
.click('.staticanalysisView') |
||||
.click('#staticanalysisView button') |
||||
.waitForElementPresent('#staticanalysisresult .warning') |
||||
.assert.containsText('#staticanalysisresult .warning pre', '1 use of tx.origin') |
||||
.end() |
||||
}) |
||||
} |
Loading…
Reference in new issue