staticAnaysis switch warning to be a dom node

pull/1/head
yann300 7 years ago
parent 03dd288eed
commit 8fcfb41975
  1. 5
      src/app/staticanalysis/modules/blockBlockhash.js
  2. 9
      src/app/staticanalysis/modules/blockTimestamp.js
  3. 3
      src/app/staticanalysis/modules/checksEffectsInteraction.js
  4. 5
      src/app/staticanalysis/modules/constantFunctions.js
  5. 9
      src/app/staticanalysis/modules/gasCosts.js
  6. 5
      src/app/staticanalysis/modules/inlineAssembly.js
  7. 17
      src/app/staticanalysis/modules/lowLevelCalls.js
  8. 14
      src/app/staticanalysis/modules/similarVariableNames.js
  9. 3
      src/app/staticanalysis/modules/thisLocal.js
  10. 5
      src/app/staticanalysis/modules/txOrigin.js
  11. 5
      src/app/staticanalysis/staticAnalysisView.js

@ -2,6 +2,7 @@ var name = 'Block.blockhash usage: '
var desc = 'Semantics maybe unclear' var desc = 'Semantics maybe unclear'
var categories = require('./categories') var categories = require('./categories')
var common = require('./staticAnalysisCommon') var common = require('./staticAnalysisCommon')
var yo = require('yo-yo')
function blockBlockhash () { function blockBlockhash () {
this.warningNodes = [] this.warningNodes = []
@ -14,10 +15,10 @@ 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(function (item, i) {
return { return {
warning: `use of "block.blockhash": "block.blockhash" is used to access the last 256 block hashes. warning: yo`<span>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.
By "summing up" the information in a clever way a miner can try to influence the outcome of a transaction in the current block. By "summing up" the information in a clever way a miner can try to influence the outcome of a transaction in the current block.
This is especially easy if there are only a small number of equally likely outcomes.`, This is especially easy if there are only a small number of equally likely outcomes.</span>`,
location: item.src location: item.src
} }
}) })

@ -2,6 +2,7 @@ var name = 'Block timestamp: '
var desc = 'Semantics maybe unclear' var desc = 'Semantics maybe unclear'
var categories = require('./categories') var categories = require('./categories')
var common = require('./staticAnalysisCommon') var common = require('./staticAnalysisCommon')
var yo = require('yo-yo')
function blockTimestamp () { function blockTimestamp () {
this.warningNowNodes = [] this.warningNowNodes = []
@ -16,15 +17,15 @@ 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(function (item, i) {
return { return {
warning: `use of "now": "now" does not mean current time. Now is an alias for block.timestamp. warning: yo`<span>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.</span>`,
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(function (item, i) {
return { return {
warning: `use of "block.timestamp": "block.timestamp" can be influenced by miners to a certain degree. warning: yo`<span>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.</span>`,
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'
} }

@ -4,6 +4,7 @@ var categories = require('./categories')
var common = require('./staticAnalysisCommon') var common = require('./staticAnalysisCommon')
var fcallGraph = require('./functionCallGraph') var fcallGraph = require('./functionCallGraph')
var AbstractAst = require('./abstractAstView') var AbstractAst = require('./abstractAstView')
var yo = require('yo-yo')
function checksEffectsInteraction () { function checksEffectsInteraction () {
this.abstractAst = new AbstractAst() this.abstractAst = new AbstractAst()
@ -36,7 +37,7 @@ function report (contracts, multipleContractsWithSameName) {
var comments = (hasModifiers) ? '<br/><i>Note:</i> Modifiers are currently not considered by this static analysis.' : '' var comments = (hasModifiers) ? '<br/><i>Note:</i> Modifiers are currently not considered by this static analysis.' : ''
comments += (multipleContractsWithSameName) ? '<br/><i>Note:</i> Import aliases are currently not supported by this static analysis.' : '' comments += (multipleContractsWithSameName) ? '<br/><i>Note:</i> Import aliases are currently not supported by this static analysis.' : ''
warnings.push({ warnings.push({
warning: `Potential Violation of Checks-Effects-Interaction pattern in <i>${funcName}</i>: Could potentially lead to re-entrancy vulnerability. ${comments}`, warning: yo`<span>Potential Violation of Checks-Effects-Interaction pattern in <i>${funcName}</i>: Could potentially lead to re-entrancy vulnerability. ${comments}</span>`,
location: func.src, location: func.src,
more: 'http://solidity.readthedocs.io/en/develop/security-considerations.html#re-entrancy' more: 'http://solidity.readthedocs.io/en/develop/security-considerations.html#re-entrancy'
}) })

@ -4,6 +4,7 @@ var categories = require('./categories')
var common = require('./staticAnalysisCommon') var common = require('./staticAnalysisCommon')
var fcallGraph = require('./functionCallGraph') var fcallGraph = require('./functionCallGraph')
var AbstractAst = require('./abstractAstView') var AbstractAst = require('./abstractAstView')
var yo = require('yo-yo')
function constantFunctions () { function constantFunctions () {
this.abstractAst = new AbstractAst() this.abstractAst = new AbstractAst()
@ -38,13 +39,13 @@ function report (contracts, multipleContractsWithSameName) {
comments += (multipleContractsWithSameName) ? '<br/><i>Note:</i> Import aliases are currently not supported by this static analysis.' : '' comments += (multipleContractsWithSameName) ? '<br/><i>Note:</i> Import aliases are currently not supported by this static analysis.' : ''
if (func.potentiallyshouldBeConst) { if (func.potentiallyshouldBeConst) {
warnings.push({ warnings.push({
warning: `<i>${funcName}</i>: Potentially should be constant but is not. ${comments}`, warning: yo`<span><i>${funcName}</i>: Potentially should be constant but is not. ${comments}</span>`,
location: func.src, location: func.src,
more: 'http://solidity.readthedocs.io/en/develop/contracts.html#constant-functions' more: 'http://solidity.readthedocs.io/en/develop/contracts.html#constant-functions'
}) })
} else { } else {
warnings.push({ warnings.push({
warning: `<i>${funcName}</i>: Is constant but potentially should not be. ${comments}`, warning: yo`<span><i>${funcName}</i>: Is constant but potentially should not be. ${comments}</span>`,
location: func.src, location: func.src,
more: 'http://solidity.readthedocs.io/en/develop/contracts.html#constant-functions' more: 'http://solidity.readthedocs.io/en/develop/contracts.html#constant-functions'
}) })

@ -1,6 +1,7 @@
var name = 'Gas costs: ' var name = 'Gas costs: '
var desc = 'Warn if the gas requirements of functions are too high.' var desc = 'Warn if the gas requirements of functions are too high.'
var categories = require('./categories') var categories = require('./categories')
var yo = require('yo-yo')
function gasCosts () { function gasCosts () {
} }
@ -19,8 +20,8 @@ gasCosts.prototype.report = function (compilationResults) {
if (fallback !== undefined) { if (fallback !== undefined) {
if (fallback === null || fallback >= 2100) { if (fallback === null || fallback >= 2100) {
report.push({ report.push({
warning: `Fallback function of contract ${contractName} requires too much gas (${fallback}).<br /> warning: yo`<span>Fallback function of contract ${contractName} requires too much gas (${fallback}).<br />
If the fallback function requires more than 2300 gas, the contract cannot receive Ether.` If the fallback function requires more than 2300 gas, the contract cannot receive Ether.</span>`
}) })
} }
} }
@ -33,10 +34,10 @@ gasCosts.prototype.report = function (compilationResults) {
var gasString = gas === null ? 'unknown or not constant' : 'high: ' + gas var gasString = gas === null ? 'unknown or not constant' : 'high: ' + gas
if (gas === null || gas >= 3000000) { if (gas === null || gas >= 3000000) {
report.push({ report.push({
warning: `Gas requirement of function ${contractName}.${functionName} ${gasString}.<br /> warning: yo`<span>Gas requirement of function ${contractName}.${functionName} ${gasString}.<br />
If the gas requirement of a function is higher than the block gas limit, it cannot be executed. If the gas requirement of a function is higher than the block gas limit, it cannot be executed.
Please avoid loops in your functions or actions that modify large areas of storage Please avoid loops in your functions or actions that modify large areas of storage
(this includes clearing or copying arrays in storage)` (this includes clearing or copying arrays in storage)</span>`
}) })
} }
} }

@ -2,6 +2,7 @@ var name = 'Inline assembly: '
var desc = 'Use of Inline Assembly' var desc = 'Use of Inline Assembly'
var categories = require('./categories') var categories = require('./categories')
var common = require('./staticAnalysisCommon') var common = require('./staticAnalysisCommon')
var yo = require('yo-yo')
function inlineAssembly () { function inlineAssembly () {
this.inlineAssNodes = [] this.inlineAssNodes = []
@ -14,8 +15,8 @@ inlineAssembly.prototype.visit = function (node) {
inlineAssembly.prototype.report = function (compilationResults) { inlineAssembly.prototype.report = function (compilationResults) {
return this.inlineAssNodes.map((node) => { return this.inlineAssNodes.map((node) => {
return { return {
warning: `CAUTION: The Contract uses inline assembly, this is only advised in rare cases. warning: yo`<span>CAUTION: The Contract uses inline assembly, this is only advised in rare cases.
Additionally static analysis modules do not parse inline Assembly, this can lead to wrong analysis results.`, Additionally static analysis modules do not parse inline Assembly, this can lead to wrong analysis results.</span>`,
location: node.src, location: node.src,
more: 'http://solidity.readthedocs.io/en/develop/assembly.html#solidity-assembly' more: 'http://solidity.readthedocs.io/en/develop/assembly.html#solidity-assembly'
} }

@ -2,6 +2,7 @@ var name = 'Low level calls: '
var desc = 'Semantics maybe unclear' var desc = 'Semantics maybe unclear'
var categories = require('./categories') var categories = require('./categories')
var common = require('./staticAnalysisCommon') var common = require('./staticAnalysisCommon')
var yo = require('yo-yo')
function lowLevelCalls () { function lowLevelCalls () {
this.llcNodes = [] this.llcNodes = []
@ -25,29 +26,29 @@ lowLevelCalls.prototype.report = function (compilationResults) {
var morehref = null var 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 = yo`<span>use of "call": the use of low level "call" should be avoided whenever possible.
It can lead to unexpected behavior if return value is not handled properly. It can lead to unexpected behavior if return value is not handled properly.
Please use Direct Calls via specifying the called contract's interface.<br />` Please use Direct Calls via specifying the called contract's interface.<br /></span>`
morehref = 'http://solidity.readthedocs.io/en/develop/control-structures.html?#external-function-calls' morehref = 'http://solidity.readthedocs.io/en/develop/control-structures.html?#external-function-calls'
// http://solidity.readthedocs.io/en/develop/frequently-asked-questions.html?#why-is-the-low-level-function-call-less-favorable-than-instantiating-a-contract-with-a-variable-contractb-b-and-executing-its-functions-b-dosomething // http://solidity.readthedocs.io/en/develop/frequently-asked-questions.html?#why-is-the-low-level-function-call-less-favorable-than-instantiating-a-contract-with-a-variable-contractb-b-and-executing-its-functions-b-dosomething
break break
case common.lowLevelCallTypes.CALLCODE: case common.lowLevelCallTypes.CALLCODE:
text = `use of "callcode": the use of low level "callcode" should be avoided whenever possible. text = yo`<span>use of "callcode": the use of low level "callcode" should be avoided whenever possible.
External code that is called can change the state of the calling contract and send ether form the caller's balance. External code that is called can change the state of the calling contract and send ether form the caller's balance.
If this is wantend behaviour use the Solidity library feature if possible.<br />` If this is wantend behaviour use the Solidity library feature if possible.<br /></span>`
morehref = 'http://solidity.readthedocs.io/en/develop/contracts.html#libraries' morehref = 'http://solidity.readthedocs.io/en/develop/contracts.html#libraries'
break break
case common.lowLevelCallTypes.DELEGATECALL: case common.lowLevelCallTypes.DELEGATECALL:
text = `use of "delegatecall": the use of low level "delegatecall" should be avoided whenever possible. text = yo`<span>use of "delegatecall": the use of low level "delegatecall" should be avoided whenever possible.
External code that is called can change the state of the calling contract and send ether form the caller's balance. External code that is called can change the state of the calling contract and send ether form the caller's balance.
If this is wantend behaviour use the Solidity library feature if possible.<br />` If this is wantend behaviour use the Solidity library feature if possible.<br /></span>`
morehref = 'http://solidity.readthedocs.io/en/develop/contracts.html#libraries' morehref = 'http://solidity.readthedocs.io/en/develop/contracts.html#libraries'
break break
case common.lowLevelCallTypes.SEND: case common.lowLevelCallTypes.SEND:
text = `use of "send": "send" does not throw an exception when not successful, make sure you deal with the failure case accordingly. text = yo`<span>use of "send": "send" does not throw an exception when not successful, make sure you deal with the failure case accordingly.
Use "transfer" whenever failure of the ether transfer should rollback the whole transaction. Use "transfer" whenever failure of the ether transfer should rollback the whole transaction.
Note: if you "send/transfer" ether to a contract the fallback function is called, the callees fallback function is very limited due to the limited amount of gas provided by "send/transfer". Note: if you "send/transfer" ether to a contract the fallback function is called, the callees fallback function is very limited due to the limited amount of gas provided by "send/transfer".
No state changes are possible but the callee can log the event or revert the transfer. "send/transfer" is syntactic sugar for a "call" to the fallback function with 2300 gas and a specified ether value. <br />` No state changes are possible but the callee can log the event or revert the transfer. "send/transfer" is syntactic sugar for a "call" to the fallback function with 2300 gas and a specified ether value. <br /></span>`
morehref = 'http://solidity.readthedocs.io/en/develop/security-considerations.html#sending-and-receiving-ether' morehref = 'http://solidity.readthedocs.io/en/develop/security-considerations.html#sending-and-receiving-ether'
break break
} }

@ -4,6 +4,7 @@ var categories = require('./categories')
var common = require('./staticAnalysisCommon') var common = require('./staticAnalysisCommon')
var AbstractAst = require('./abstractAstView') var AbstractAst = require('./abstractAstView')
var levenshtein = require('fast-levenshtein') var levenshtein = require('fast-levenshtein')
var yo = require('yo-yo')
function similarVariableNames () { function similarVariableNames () {
this.abstractAst = new AbstractAst() this.abstractAst = new AbstractAst()
@ -26,13 +27,20 @@ function report (contracts, multipleContractsWithSameName) {
contracts.forEach((contract) => { contracts.forEach((contract) => {
contract.functions.forEach((func) => { contract.functions.forEach((func) => {
var funcName = common.getFullQuallyfiedFuncDefinitionIdent(contract.node, func.node, func.parameters) var funcName = common.getFullQuallyfiedFuncDefinitionIdent(contract.node, func.node, func.parameters)
var comments = (hasModifiers) ? '<br/><i>Note:</i> Modifiers are currently not considered by this static analysis.' : '' var hasModifiersComments = ''
comments += (multipleContractsWithSameName) ? '<br/><i>Note:</i> Import aliases are currently not supported by this static analysis.' : '' if (hasModifiers) {
hasModifiersComments = yo`<span><br/><i>Note:</i> Modifiers are currently not considered by this static analysis.</span>`
}
var multipleContractsWithSameNameComments = ''
if (multipleContractsWithSameName) {
multipleContractsWithSameNameComments = yo`<span><br/><i>Note:</i> Import aliases are currently not supported by this static analysis.</span>`
}
var vars = getFunctionVariables(contract, func).map(common.getDeclaredVariableName) var vars = getFunctionVariables(contract, func).map(common.getDeclaredVariableName)
findSimilarVarNames(vars).map((sim) => { findSimilarVarNames(vars).map((sim) => {
warnings.push({ warnings.push({
warning: `<i>${funcName}</i>: Variables have very similar names <i>${sim.var1}</i> and <i>${sim.var2}<i>. ${comments}`, warning: yo`<span><i>${funcName}</i>: Variables have very similar names <i>${sim.var1}</i> and <i>${sim.var2}</i>. ${hasModifiersComments} ${multipleContractsWithSameNameComments}</span>`,
location: func.src location: func.src
}) })
}) })

@ -2,6 +2,7 @@ var name = 'This on local calls: '
var desc = 'Invocation of local functions via this' var desc = 'Invocation of local functions via this'
var categories = require('./categories') var categories = require('./categories')
var common = require('./staticAnalysisCommon') var common = require('./staticAnalysisCommon')
var yo = require('yo-yo')
function thisLocal () { function thisLocal () {
this.warningNodes = [] this.warningNodes = []
@ -14,7 +15,7 @@ thisLocal.prototype.visit = function (node) {
thisLocal.prototype.report = function (compilationResults) { thisLocal.prototype.report = function (compilationResults) {
return this.warningNodes.map(function (item, i) { return this.warningNodes.map(function (item, i) {
return { return {
warning: 'Use of "this" for local functions: Never use this to call functions in the same contract, it only consumes more gas than normal local calls.', warning: yo`<span>Use of "this" for local functions: Never use this to call functions in the same contract, it only consumes more gas than normal local calls.</span>`,
location: item.src, location: item.src,
more: 'http://solidity.readthedocs.io/en/develop/control-structures.html#external-function-calls' more: 'http://solidity.readthedocs.io/en/develop/control-structures.html#external-function-calls'
} }

@ -1,6 +1,7 @@
var name = 'Transaction origin: ' var name = 'Transaction origin: '
var desc = 'Warn if tx.origin is used' var desc = 'Warn if tx.origin is used'
var categories = require('./categories') var categories = require('./categories')
var yo = require('yo-yo')
function txOrigin () { function txOrigin () {
this.txOriginNodes = [] this.txOriginNodes = []
@ -20,8 +21,8 @@ txOrigin.prototype.visit = function (node) {
txOrigin.prototype.report = function () { txOrigin.prototype.report = function () {
return this.txOriginNodes.map(function (item, i) { return this.txOriginNodes.map(function (item, i) {
return { return {
warning: `Use of tx.origin: "tx.origin" is useful only in very exceptional cases.<br /> warning: yo`<span>Use of tx.origin: "tx.origin" is useful only in very exceptional cases.<br />
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.</span>`,
location: item.src location: item.src
} }
}) })

@ -115,10 +115,11 @@ staticAnalysisView.prototype.run = function () {
length: parseInt(split[1]) length: parseInt(split[1])
} }
location = self.appAPI.offsetToLineColumn(location, file) location = self.appAPI.offsetToLineColumn(location, file)
location = self.lastCompilationResult.sourceList[file] + ':' + (location.start.line + 1) + ':' + (location.start.column + 1) + ':' location = self.lastCompilationResult.sourceList[file] + ':' + (location.start.line + 1) + ':' + (location.start.column + 1) + ': '
} }
warningCount++ warningCount++
self.appAPI.renderWarning(location + ' ' + item.warning + ((item.more) ? '<br><a href="' + item.more + '" target="blank">more</a>' : ''), warningContainer, {type: 'warning', useSpan: true, isHTML: true}) var msg = yo`<span>${location} ${item.warning} ${item.more ? yo`<span><br><a href="${item.more}" target="blank">more</a></span>` : yo`<span></span>`}</span>`
self.appAPI.renderWarning(msg, warningContainer, {type: 'warning', useSpan: true})
}) })
}) })
if (warningContainer.html() === '') { if (warningContainer.html() === '') {

Loading…
Cancel
Save