Commit a5f7dd22 authored by soad003's avatar soad003

Static Analysis: improvements of messages, similar var names ignore prefixed…

Static Analysis: improvements of messages, similar var names ignore prefixed with underscore as suggested by chriseth
parent 11a6bb7a
...@@ -45,7 +45,8 @@ ...@@ -45,7 +45,8 @@
"watchify": "^3.9.0", "watchify": "^3.9.0",
"web3": "^0.18.0", "web3": "^0.18.0",
"webworkify": "^1.2.1", "webworkify": "^1.2.1",
"yo-yo": "^1.2.2" "yo-yo": "^1.2.2",
"fast-levenshtein": "^2.0.6"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
......
...@@ -14,7 +14,7 @@ blockBlockhash.prototype.visit = function (node) { ...@@ -14,7 +14,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(function (item, i) {
return { return {
warning: `use of "block.blockhash": "block.blockhash" is used to access the last 256 block hashes. A miner computes the block hash be "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.`, 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. 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.`,
location: item.src location: item.src
} }
}) })
......
...@@ -16,7 +16,7 @@ blockTimestamp.prototype.visit = function (node) { ...@@ -16,7 +16,7 @@ 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. Block.timestamp can be influenced by miners to a certain degree, be carefull.`, 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.`,
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'
} }
......
...@@ -25,20 +25,20 @@ lowLevelCalls.prototype.report = function (compilationResults) { ...@@ -25,20 +25,20 @@ 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. It can lead to unexpected behavior if return value is not handled properly. Please use Direct Calls via specifying the called contracts interface.<br />` text = `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. Please use Direct Calls via specifying the called contract's interface.<br />`
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. External code that is called can change the state of the calling contract and send ether form the callers balance. If this is wantend behaviour use the Solidity library feature if possible.<br />` text = `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. If this is wantend behaviour use the Solidity library feature if possible.<br />`
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. External code that is called can change the state of the calling contract and send ether form the callers balance. If this is wantend behaviour use the Solidity library feature if possible.<br />` text = `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. If this is wantend behaviour use the Solidity library feature if possible.<br />`
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": using "send" has several quirks. "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. Additionally if you send ether to a contract the fallback function is called which makes reentrancy vulnerabilities possible. "send" is more or less syntactic sugar for a "call" to the fallback function with 2300 gas and a specified ether value. <br />` text = `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. Additionally if you "send" 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". No state changes are possible but the callee can log the event or revert the transfer. "send" is syntactic sugar for a "call" to the fallback function with 2300 gas and a specified ether value. <br />`
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
} }
......
var name = 'Similar Variable Names' var name = 'Similar Variable Names'
var desc = 'Check if variable names are to similar' var desc = 'Check if variable names are too similar'
var categories = require('./categories') 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')
function similarVariableNames () { function similarVariableNames () {
this.abstractAst = new AbstractAst() this.abstractAst = new AbstractAst()
...@@ -45,48 +46,21 @@ function findSimilarVarNames (vars) { ...@@ -45,48 +46,21 @@ function findSimilarVarNames (vars) {
var similar = [] var similar = []
var comb = {} var comb = {}
vars.map((varName1) => vars.map((varName2) => { vars.map((varName1) => vars.map((varName2) => {
if (varName1.length > 1 && varName2.length > 1 && varName2 !== varName1 && !(comb[varName1 + ';' + varName2] || comb[varName2 + ';' + varName1])) { if (varName1.length > 1 && varName2.length > 1 && varName2 !== varName1 && !isCommonPrefixedVersion(varName1, varName2) && !(comb[varName1 + ';' + varName2] || comb[varName2 + ';' + varName1])) {
comb[varName1 + ';' + varName2] = true comb[varName1 + ';' + varName2] = true
var distance = levenshteinDistance(varName1, varName2) var 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 })
} }
})) }))
return similar return similar
} }
function getFunctionVariables (contract, func) { function isCommonPrefixedVersion (varName1, varName2) {
return contract.stateVariables.concat(func.localVariables) return (varName1.startsWith('_') || varName2.startsWith('_')) && (varName1.slice(1) === varName2 || varName1 === varName2.slice(1))
} }
/* function getFunctionVariables (contract, func) {
* Props to DerekZiemba (see https://gist.github.com/andrei-m/982927) return contract.stateVariables.concat(func.localVariables)
* Probably better solutions out there. Libs?
*/
function levenshteinDistance (a, b) {
let tmp
if (a.length === 0) return b.length
if (b.length === 0) return a.length
if (a.length > b.length) {
tmp = a
a = b
b = tmp
}
let i, j, res
let alen = a.length
let blen = b.length
let row = Array(alen)
for (i = 0; i <= alen; i++) { row[i] = i }
for (i = 1; i <= blen; i++) {
res = i
for (j = 1; j <= alen; j++) {
tmp = row[j - 1]
row[j - 1] = res
res = b[i - 1] === a[j - 1] ? tmp : Math.min(tmp + 1, Math.min(res + 1, row[j] + 1))
}
}
return res
} }
module.exports = { module.exports = {
......
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