Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
B
baas-ide
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
JIRA
JIRA
Merge Requests
1
Merge Requests
1
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
guxukai
baas-ide
Commits
8ccef1c5
Commit
8ccef1c5
authored
Mar 11, 2020
by
Aniket
Committed by
Aniket
Mar 24, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
integration tests for 2 contracts updated
parent
febf8804
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
97 additions
and
59 deletions
+97
-59
index.ts
remix-analyzer/src/solidity-analyzer/index.ts
+5
-2
assignAndCompare.ts
...nalyzer/src/solidity-analyzer/modules/assignAndCompare.ts
+1
-1
blockBlockhash.ts
...-analyzer/src/solidity-analyzer/modules/blockBlockhash.ts
+1
-1
checksEffectsInteraction.ts
...src/solidity-analyzer/modules/checksEffectsInteraction.ts
+1
-1
constantFunctions.ts
...alyzer/src/solidity-analyzer/modules/constantFunctions.ts
+3
-3
etherTransferInLoop.ts
...yzer/src/solidity-analyzer/modules/etherTransferInLoop.ts
+2
-2
forLoopIteratesOverDynamicArray.ts
...idity-analyzer/modules/forLoopIteratesOverDynamicArray.ts
+2
-2
functionCallGraph.ts
...alyzer/src/solidity-analyzer/modules/functionCallGraph.ts
+5
-6
inlineAssembly.ts
...-analyzer/src/solidity-analyzer/modules/inlineAssembly.ts
+1
-1
selfdestruct.ts
remix-analyzer/src/solidity-analyzer/modules/selfdestruct.ts
+1
-1
staticAnalysisCommon.ts
...zer/src/solidity-analyzer/modules/staticAnalysisCommon.ts
+72
-35
thisLocal.ts
remix-analyzer/src/solidity-analyzer/modules/thisLocal.ts
+1
-1
staticAnalysisCommon-test.ts
remix-analyzer/test/analysis/staticAnalysisCommon-test.ts
+1
-2
staticAnalysisIntegration-test-0.5.0.ts
...zer/test/analysis/staticAnalysisIntegration-test-0.5.0.ts
+0
-0
ballot.sol
...zer/test/analysis/test-contracts/solidity-v0.5/ballot.sol
+1
-1
No files found.
remix-analyzer/src/solidity-analyzer/index.ts
View file @
8ccef1c5
...
@@ -18,7 +18,9 @@ export default class staticAnalysisRunner {
...
@@ -18,7 +18,9 @@ export default class staticAnalysisRunner {
// Also provide convenience analysis via the AST walker.
// Also provide convenience analysis via the AST walker.
const
walker
=
new
AstWalker
()
const
walker
=
new
AstWalker
()
for
(
let
k
in
compilationResult
.
sources
)
{
for
(
let
k
in
compilationResult
.
sources
)
{
walker
.
walk
(
compilationResult
.
sources
[
k
].
AST
,
{
'*'
:
(
node
)
=>
{
// console.log('Ast in walker---', compilationResult.sources[k])
walker
.
walkFull
(
compilationResult
.
sources
[
k
].
ast
,
(
node
)
=>
{
modules
.
map
((
item
,
i
)
=>
{
modules
.
map
((
item
,
i
)
=>
{
if
(
item
.
mod
.
visit
!==
undefined
)
{
if
(
item
.
mod
.
visit
!==
undefined
)
{
try
{
try
{
...
@@ -31,7 +33,8 @@ export default class staticAnalysisRunner {
...
@@ -31,7 +33,8 @@ export default class staticAnalysisRunner {
}
}
})
})
return
true
return
true
}})
}
)
}
}
// Here, modules can just collect the results from the AST walk,
// Here, modules can just collect the results from the AST walk,
...
...
remix-analyzer/src/solidity-analyzer/modules/assignAndCompare.ts
View file @
8ccef1c5
...
@@ -11,7 +11,7 @@ export default class assignAndCompare implements AnalyzerModule {
...
@@ -11,7 +11,7 @@ export default class assignAndCompare implements AnalyzerModule {
algorithm
:
ModuleAlgorithm
=
algorithm
.
EXACT
algorithm
:
ModuleAlgorithm
=
algorithm
.
EXACT
visit
(
node
:
BlockAstNode
|
IfStatementAstNode
|
WhileStatementAstNode
|
ForStatementAstNode
):
void
{
visit
(
node
:
BlockAstNode
|
IfStatementAstNode
|
WhileStatementAstNode
|
ForStatementAstNode
):
void
{
if
(
isSubScopeWithTopLevelUnAssignedBinOp
(
node
))
getUnAssignedTopLevelBinOps
(
node
).
forEach
((
n
)
=>
this
.
warningNodes
.
push
(
n
))
if
(
node
&&
node
.
nodeType
&&
isSubScopeWithTopLevelUnAssignedBinOp
(
node
))
getUnAssignedTopLevelBinOps
(
node
).
forEach
((
n
)
=>
this
.
warningNodes
.
push
(
n
))
}
}
report
(
compilationResults
:
CompilationResult
):
ReportObj
[]
{
report
(
compilationResults
:
CompilationResult
):
ReportObj
[]
{
...
...
remix-analyzer/src/solidity-analyzer/modules/blockBlockhash.ts
View file @
8ccef1c5
...
@@ -11,7 +11,7 @@ export default class blockBlockhash implements AnalyzerModule {
...
@@ -11,7 +11,7 @@ export default class blockBlockhash implements AnalyzerModule {
algorithm
:
ModuleAlgorithm
=
algorithm
.
EXACT
algorithm
:
ModuleAlgorithm
=
algorithm
.
EXACT
visit
(
node
:
FunctionCallAstNode
):
void
{
visit
(
node
:
FunctionCallAstNode
):
void
{
if
(
isBlockBlockHashAccess
(
node
))
this
.
warningNodes
.
push
(
node
)
if
(
node
.
nodeType
===
'FunctionCall'
&&
isBlockBlockHashAccess
(
node
))
this
.
warningNodes
.
push
(
node
)
}
}
report
(
compilationResults
:
CompilationResult
):
ReportObj
[]
{
report
(
compilationResults
:
CompilationResult
):
ReportObj
[]
{
...
...
remix-analyzer/src/solidity-analyzer/modules/checksEffectsInteraction.ts
View file @
8ccef1c5
...
@@ -43,7 +43,7 @@ export default class checksEffectsInteraction implements AnalyzerModule {
...
@@ -43,7 +43,7 @@ export default class checksEffectsInteraction implements AnalyzerModule {
comments
+=
(
multipleContractsWithSameName
)
?
'Note: Import aliases are currently not supported by this static analysis.'
:
''
comments
+=
(
multipleContractsWithSameName
)
?
'Note: Import aliases are currently not supported by this static analysis.'
:
''
warnings
.
push
({
warnings
.
push
({
warning
:
`Potential Violation of Checks-Effects-Interaction pattern in
${
funcName
}
: Could potentially lead to re-entrancy vulnerability.
${
comments
}
`
,
warning
:
`Potential Violation of Checks-Effects-Interaction pattern in
${
funcName
}
: Could potentially lead to re-entrancy vulnerability.
${
comments
}
`
,
location
:
func
[
'src'
],
location
:
func
.
node
[
'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'
})
})
}
}
...
...
remix-analyzer/src/solidity-analyzer/modules/constantFunctions.ts
View file @
8ccef1c5
...
@@ -64,13 +64,13 @@ export default class constantFunctions implements AnalyzerModule {
...
@@ -64,13 +64,13 @@ export default class constantFunctions implements AnalyzerModule {
if
(
func
[
'potentiallyshouldBeConst'
])
{
if
(
func
[
'potentiallyshouldBeConst'
])
{
warnings
.
push
({
warnings
.
push
({
warning
:
`
${
funcName
}
: Potentially should be constant but is not.
${
comments
}
`
,
warning
:
`
${
funcName
}
: Potentially should be constant but is not.
${
comments
}
`
,
location
:
func
[
'src'
],
location
:
func
.
node
[
'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
:
`
${
funcName
}
: Is constant but potentially should not be.
${
comments
}
`
,
warning
:
`
${
funcName
}
: Is constant but potentially should not be.
${
comments
}
`
,
location
:
func
[
'src'
],
location
:
func
.
node
[
'src'
],
more
:
'http://solidity.readthedocs.io/en/develop/contracts.html#constant-functions'
more
:
'http://solidity.readthedocs.io/en/develop/contracts.html#constant-functions'
})
})
}
}
...
@@ -88,7 +88,7 @@ export default class constantFunctions implements AnalyzerModule {
...
@@ -88,7 +88,7 @@ export default class constantFunctions implements AnalyzerModule {
return
contract
.
stateVariables
.
concat
(
func
.
localVariables
.
filter
(
isStorageVariableDeclaration
))
return
contract
.
stateVariables
.
concat
(
func
.
localVariables
.
filter
(
isStorageVariableDeclaration
))
}
}
private
checkIfShouldBeConstant
(
startFuncName
:
string
,
context
):
boolean
{
private
checkIfShouldBeConstant
(
startFuncName
:
string
,
context
:
Context
):
boolean
{
return
!
analyseCallGraph
(
context
.
callGraph
,
startFuncName
,
context
,
this
.
isConstBreaker
.
bind
(
this
))
return
!
analyseCallGraph
(
context
.
callGraph
,
startFuncName
,
context
,
this
.
isConstBreaker
.
bind
(
this
))
}
}
...
...
remix-analyzer/src/solidity-analyzer/modules/etherTransferInLoop.ts
View file @
8ccef1c5
...
@@ -12,11 +12,11 @@ export default class etherTransferInLoop implements AnalyzerModule {
...
@@ -12,11 +12,11 @@ export default class etherTransferInLoop implements AnalyzerModule {
visit
(
node
:
ForStatementAstNode
|
WhileStatementAstNode
):
void
{
visit
(
node
:
ForStatementAstNode
|
WhileStatementAstNode
):
void
{
let
transferNodes
:
ExpressionStatementAstNode
[]
=
[]
let
transferNodes
:
ExpressionStatementAstNode
[]
=
[]
if
(
node
.
body
.
nodeType
===
'Block'
)
if
(
node
.
body
&&
node
.
body
.
nodeType
===
'Block'
)
transferNodes
=
node
.
body
.
statements
.
filter
(
child
=>
(
child
.
nodeType
===
'ExpressionStatement'
&&
transferNodes
=
node
.
body
.
statements
.
filter
(
child
=>
(
child
.
nodeType
===
'ExpressionStatement'
&&
child
.
expression
.
nodeType
===
'FunctionCall'
&&
isTransfer
(
child
.
expression
.
expression
)))
child
.
expression
.
nodeType
===
'FunctionCall'
&&
isTransfer
(
child
.
expression
.
expression
)))
// When loop body is described without braces
// When loop body is described without braces
else
if
(
node
.
body
.
nodeType
===
'ExpressionStatement'
&&
node
.
body
.
expression
.
nodeType
===
'FunctionCall'
&&
isTransfer
(
node
.
body
.
expression
.
expression
))
else
if
(
node
.
body
&&
node
.
body
.
nodeType
===
'ExpressionStatement'
&&
node
.
body
.
expression
.
nodeType
===
'FunctionCall'
&&
isTransfer
(
node
.
body
.
expression
.
expression
))
transferNodes
.
push
(
node
.
body
)
transferNodes
.
push
(
node
.
body
)
if
(
transferNodes
.
length
>
0
)
{
if
(
transferNodes
.
length
>
0
)
{
this
.
relevantNodes
.
push
(...
transferNodes
)
this
.
relevantNodes
.
push
(...
transferNodes
)
...
...
remix-analyzer/src/solidity-analyzer/modules/forLoopIteratesOverDynamicArray.ts
View file @
8ccef1c5
...
@@ -13,9 +13,9 @@ export default class forLoopIteratesOverDynamicArray implements AnalyzerModule {
...
@@ -13,9 +13,9 @@ export default class forLoopIteratesOverDynamicArray implements AnalyzerModule {
visit
(
node
:
ForStatementAstNode
):
void
{
visit
(
node
:
ForStatementAstNode
):
void
{
const
{
condition
}
=
node
const
{
condition
}
=
node
// Check if condition is `i < array.length - 1`
// Check if condition is `i < array.length - 1`
if
((
condition
.
nodeType
===
"BinaryOperation"
&&
condition
.
rightExpression
.
nodeType
===
"BinaryOperation"
&&
isDynamicArrayLengthAccess
(
condition
.
rightExpression
.
leftExpression
))
||
if
((
condition
&&
condition
.
nodeType
===
"BinaryOperation"
&&
condition
.
rightExpression
.
nodeType
===
"BinaryOperation"
&&
isDynamicArrayLengthAccess
(
condition
.
rightExpression
.
leftExpression
))
||
// or condition is `i < array.length`
// or condition is `i < array.length`
(
condition
.
nodeType
===
"BinaryOperation"
&&
isDynamicArrayLengthAccess
(
condition
.
rightExpression
)))
{
(
condition
&&
condition
.
nodeType
===
"BinaryOperation"
&&
isDynamicArrayLengthAccess
(
condition
.
rightExpression
)))
{
this
.
relevantNodes
.
push
(
node
)
this
.
relevantNodes
.
push
(
node
)
}
}
}
}
...
...
remix-analyzer/src/solidity-analyzer/modules/functionCallGraph.ts
View file @
8ccef1c5
'use strict'
'use strict'
import
{
FunctionHLAst
,
ContractHLAst
,
FunctionCallGraph
,
ContractCallGraph
}
from
"types"
import
{
FunctionHLAst
,
ContractHLAst
,
FunctionCallGraph
,
ContractCallGraph
}
from
"types"
import
{
isLocalCallGraphRelevantNode
,
isExternalDirectCall
,
getFullQualifiedFunctionCallIdent
,
getFullQuallyfiedFuncDefinitionIdent
,
getContractName
}
from
'./staticAnalysisCommon'
const
common
=
require
(
'./staticAnalysisCommon'
)
function
buildLocalFuncCallGraphInternal
(
functions
:
FunctionHLAst
[],
nodeFilter
:
any
,
extractNodeIdent
:
any
,
extractFuncDefIdent
:
Function
):
Record
<
string
,
FunctionCallGraph
>
{
function
buildLocalFuncCallGraphInternal
(
functions
:
FunctionHLAst
[],
nodeFilter
:
any
,
extractNodeIdent
:
any
,
extractFuncDefIdent
:
Function
):
Record
<
string
,
FunctionCallGraph
>
{
const
callGraph
:
Record
<
string
,
FunctionCallGraph
>
=
{}
const
callGraph
:
Record
<
string
,
FunctionCallGraph
>
=
{}
...
@@ -44,11 +43,11 @@ function buildLocalFuncCallGraphInternal (functions: FunctionHLAst[], nodeFilter
...
@@ -44,11 +43,11 @@ function buildLocalFuncCallGraphInternal (functions: FunctionHLAst[], nodeFilter
export
function
buildGlobalFuncCallGraph
(
contracts
:
ContractHLAst
[]):
Record
<
string
,
ContractCallGraph
>
{
export
function
buildGlobalFuncCallGraph
(
contracts
:
ContractHLAst
[]):
Record
<
string
,
ContractCallGraph
>
{
const
callGraph
:
Record
<
string
,
ContractCallGraph
>
=
{}
const
callGraph
:
Record
<
string
,
ContractCallGraph
>
=
{}
contracts
.
forEach
((
contract
)
=>
{
contracts
.
forEach
((
contract
)
=>
{
const
filterNodes
:
Function
=
(
node
)
=>
{
return
common
.
isLocalCallGraphRelevantNode
(
node
)
||
common
.
isExternalDirectCall
(
node
)
}
const
filterNodes
:
Function
=
(
node
)
=>
{
return
isLocalCallGraphRelevantNode
(
node
)
||
isExternalDirectCall
(
node
)
}
const
getNodeIdent
:
Function
=
(
node
)
=>
{
return
common
.
getFullQualifiedFunctionCallIdent
(
contract
.
node
,
node
)
}
const
getNodeIdent
:
Function
=
(
node
)
=>
{
return
getFullQualifiedFunctionCallIdent
(
contract
.
node
,
node
)
}
const
getFunDefIdent
:
Function
=
(
funcDef
)
=>
{
return
common
.
getFullQuallyfiedFuncDefinitionIdent
(
contract
.
node
,
funcDef
.
node
,
funcDef
.
parameters
)
}
const
getFunDefIdent
:
Function
=
(
funcDef
)
=>
{
return
getFullQuallyfiedFuncDefinitionIdent
(
contract
.
node
,
funcDef
.
node
,
funcDef
.
parameters
)
}
callGraph
[
common
.
getContractName
(
contract
.
node
)]
=
{
contract
:
contract
,
functions
:
buildLocalFuncCallGraphInternal
(
contract
.
functions
,
filterNodes
,
getNodeIdent
,
getFunDefIdent
)
}
callGraph
[
getContractName
(
contract
.
node
)]
=
{
contract
:
contract
,
functions
:
buildLocalFuncCallGraphInternal
(
contract
.
functions
,
filterNodes
,
getNodeIdent
,
getFunDefIdent
)
}
})
})
return
callGraph
return
callGraph
...
...
remix-analyzer/src/solidity-analyzer/modules/inlineAssembly.ts
View file @
8ccef1c5
...
@@ -10,7 +10,7 @@ export default class inlineAssembly implements AnalyzerModule {
...
@@ -10,7 +10,7 @@ export default class inlineAssembly implements AnalyzerModule {
algorithm
:
ModuleAlgorithm
=
algorithm
.
EXACT
algorithm
:
ModuleAlgorithm
=
algorithm
.
EXACT
visit
(
node
:
InlineAssemblyAstNode
):
void
{
visit
(
node
:
InlineAssemblyAstNode
):
void
{
this
.
inlineAssNodes
.
push
(
node
)
if
(
node
.
nodeType
===
'InlineAssembly'
)
this
.
inlineAssNodes
.
push
(
node
)
}
}
report
(
compilationResults
:
CompilationResult
):
ReportObj
[]
{
report
(
compilationResults
:
CompilationResult
):
ReportObj
[]
{
...
...
remix-analyzer/src/solidity-analyzer/modules/selfdestruct.ts
View file @
8ccef1c5
...
@@ -13,7 +13,7 @@ export default class selfdestruct implements AnalyzerModule {
...
@@ -13,7 +13,7 @@ export default class selfdestruct implements AnalyzerModule {
abstractAst
:
AbstractAst
=
new
AbstractAst
()
abstractAst
:
AbstractAst
=
new
AbstractAst
()
visit
:
Function
=
this
.
abstractAst
.
build_visit
(
visit
:
Function
=
this
.
abstractAst
.
build_visit
(
(
node
:
any
)
=>
isStatement
(
node
)
||
isSelfdestructCall
(
node
.
expression
)
(
node
:
any
)
=>
isStatement
(
node
)
||
(
node
.
nodeType
===
'FunctionCall'
&&
isSelfdestructCall
(
node
.
expression
)
)
)
)
report
:
Function
=
this
.
abstractAst
.
build_report
(
this
.
_report
.
bind
(
this
))
report
:
Function
=
this
.
abstractAst
.
build_report
(
this
.
_report
.
bind
(
this
))
...
...
remix-analyzer/src/solidity-analyzer/modules/staticAnalysisCommon.ts
View file @
8ccef1c5
'use strict'
'use strict'
import
{
FunctionDefinitionAstNode
,
ModifierDefinitionAstNode
,
ParameterListAstNode
,
ForStatementAstNode
,
WhileStatementAstNode
,
VariableDeclarationAstNode
,
ContractDefinitionAstNode
,
InheritanceSpecifierAstNode
,
MemberAccessAstNode
,
BinaryOperationAstNode
,
FunctionCallAstNode
,
ExpressionStatementAstNode
,
UnaryOperationAstNode
,
IdentifierAstNode
,
MappingAstNode
,
IndexAccessAstNode
,
UserDefinedTypeNameAstNode
,
BlockAstNode
,
AssignmentAstNode
,
InlineAssemblyAstNode
,
IfStatementAstNode
}
from
"types"
import
{
FunctionDefinitionAstNode
,
ModifierDefinitionAstNode
,
ParameterListAstNode
,
ForStatementAstNode
,
WhileStatementAstNode
,
VariableDeclarationAstNode
,
ContractDefinitionAstNode
,
InheritanceSpecifierAstNode
,
MemberAccessAstNode
,
BinaryOperationAstNode
,
FunctionCallAstNode
,
ExpressionStatementAstNode
,
UnaryOperationAstNode
,
IdentifierAstNode
,
MappingAstNode
,
IndexAccessAstNode
,
UserDefinedTypeNameAstNode
,
BlockAstNode
,
AssignmentAstNode
,
InlineAssemblyAstNode
,
IfStatementAstNode
}
from
"types"
import
{
util
}
from
'remix-lib'
import
{
util
}
from
'remix-lib'
const
nodeTypes
=
{
const
nodeTypes
=
{
IDENTIFIER
:
'Identifier'
,
SOURCEUNIT
:
'SourceUnit'
,
MEMBERACCESS
:
'MemberAccess'
,
PRAGMADIRECTIVE
:
'PragmaDirective'
,
FUNCTIONCALL
:
'FunctionCall'
,
IMPORTDIRECTIVE
:
'ImportDirective'
,
CONTRACTDEFINITION
:
'ContractDefinition'
,
INHERITANCESPECIFIER
:
'InheritanceSpecifier'
,
USINGFORDIRECTIVE
:
'UsingForDirective'
,
STRUCTDEFINITION
:
'StructDefinition'
,
ENUMDEFINITION
:
'EnumDefinition'
,
ENUMVALUE
:
'EnumValue'
,
PARAMETERLIST
:
'ParameterList'
,
OVERRIDESPECIFIER
:
'OverrideSpecifier'
,
FUNCTIONDEFINITION
:
'FunctionDefinition'
,
FUNCTIONDEFINITION
:
'FunctionDefinition'
,
VARIABLEDECLARATION
:
'VariableDeclaration'
,
VARIABLEDECLARATION
:
'VariableDeclaration'
,
ASSIGNMENT
:
'Assignment'
,
CONTRACTDEFINITION
:
'ContractDefinition'
,
UNARYOPERATION
:
'UnaryOperation'
,
BINARYOPERATION
:
'BinaryOperation'
,
EXPRESSIONSTATEMENT
:
'ExpressionStatement'
,
MODIFIERDEFINITION
:
'ModifierDefinition'
,
MODIFIERDEFINITION
:
'ModifierDefinition'
,
MODIFIERINVOCATION
:
'ModifierInvocation'
,
MODIFIERINVOCATION
:
'ModifierInvocation'
,
INHERITANCESPECIFIER
:
'InheritanceSpecifier'
,
EVENTDEFINITION
:
'EventDefinition'
,
ELEMENTARYTYPENAME
:
'ElementaryTypeName'
,
USERDEFINEDTYPENAME
:
'UserDefinedTypeName'
,
USERDEFINEDTYPENAME
:
'UserDefinedTypeName'
,
INLINEASSEMBLY
:
'InlineAssembly'
,
FUNCTIONTYPENAME
:
'FunctionTypeName'
,
MAPPING
:
'Mapping'
,
ARRAYTYPENAME
:
'ArrayTypeName'
,
INLINEASSEMBLY
:
'InlineAssembly'
,
BLOCK
:
'Block'
,
BLOCK
:
'Block'
,
NEWEXPRESSION
:
'NewExpression'
,
PLACEHOLDERSTATEMENT
:
'PlaceholderStatement'
,
RETURN
:
'Return'
,
IFSTATEMENT
:
'IfStatement'
,
IFSTATEMENT
:
'IfStatement'
,
FORSTATEMENT
:
'ForStatement'
,
TRYCATCHCLAUSE
:
'TryCatchClause'
,
TRYSTATEMENT
:
'TryStatement'
,
WHILESTATEMENT
:
'WhileStatement'
,
WHILESTATEMENT
:
'WhileStatement'
,
DOWHILESTATEMENT
:
'DoWhileStatement'
,
DOWHILESTATEMENT
:
'DoWhileStatement'
,
ELEMENTARYTYPENAMEEXPRESSION
:
'ElementaryTypeNameExpression'
FORSTATEMENT
:
'ForStatement'
,
CONTINUE
:
'Continue'
,
BREAK
:
'Break'
,
RETURN
:
'Return'
,
THROW
:
'Throw'
,
EMITSTATEMENT
:
'EmitStatement'
,
VARIABLEDECLARATIONSTATEMENT
:
'VariableDeclarationStatement'
,
EXPRESSIONSTATEMENT
:
'ExpressionStatement'
,
CONDITIONAL
:
'Conditional'
,
ASSIGNMENT
:
'Assignment'
,
TUPLEEXPRESSION
:
'TupleExpression'
,
UNARYOPERATION
:
'UnaryOperation'
,
BINARYOPERATION
:
'BinaryOperation'
,
FUNCTIONCALL
:
'FunctionCall'
,
FUNCTIONCALLOPTIONS
:
'FunctionCallOptions'
,
NEWEXPRESSION
:
'NewExpression'
,
MEMBERACCESS
:
'MemberAccess'
,
INDEXACCESS
:
'IndexAccess'
,
INDEXRANGEACCESS
:
'IndexRangeAccess'
,
ELEMENTARYTYPENAMEEXPRESSION
:
'ElementaryTypeNameExpression'
,
LITERAL
:
'Literal'
,
IDENTIFIER
:
'Identifier'
,
STRUCTUREDDOCUMENTATION
:
'StructuredDocumentation'
}
}
const
basicTypes
=
{
const
basicTypes
=
{
...
@@ -401,7 +429,7 @@ function getUnAssignedTopLevelBinOps (subScope: BlockAstNode | IfStatementAstNod
...
@@ -401,7 +429,7 @@ function getUnAssignedTopLevelBinOps (subScope: BlockAstNode | IfStatementAstNod
if
(
subScope
.
nodeType
===
'Block'
)
if
(
subScope
.
nodeType
===
'Block'
)
result
=
subScope
.
statements
.
filter
(
isBinaryOpInExpression
)
result
=
subScope
.
statements
.
filter
(
isBinaryOpInExpression
)
// for 'without braces' loops
// for 'without braces' loops
else
if
(
isSubScopeStatement
(
subScope
))
{
else
if
(
subScope
&&
subScope
.
nodeType
&&
isSubScopeStatement
(
subScope
))
{
if
(
subScope
.
nodeType
===
'IfStatement'
){
if
(
subScope
.
nodeType
===
'IfStatement'
){
if
((
subScope
.
trueBody
.
nodeType
===
"ExpressionStatement"
&&
isBinaryOpInExpression
(
subScope
.
trueBody
)))
if
((
subScope
.
trueBody
.
nodeType
===
"ExpressionStatement"
&&
isBinaryOpInExpression
(
subScope
.
trueBody
)))
result
.
push
(
subScope
.
trueBody
)
result
.
push
(
subScope
.
trueBody
)
...
@@ -519,7 +547,7 @@ function isBuiltinFunctionCall (node: FunctionCallAstNode): boolean {
...
@@ -519,7 +547,7 @@ function isBuiltinFunctionCall (node: FunctionCallAstNode): boolean {
// console.log('isBuiltinFunctionCall isLocalCall', isLocalCall(node))
// console.log('isBuiltinFunctionCall isLocalCall', isLocalCall(node))
// console.log('isBuiltinFunctionCall getLocalCallName', getLocalCallName(node))
// console.log('isBuiltinFunctionCall getLocalCallName', getLocalCallName(node))
// console.log('isBuiltinFunctionCall getFunctionCallTypeParameterType', getFunctionCallTypeParameterType(node))
// console.log('isBuiltinFunctionCall getFunctionCallTypeParameterType', getFunctionCallTypeParameterType(node))
return
(
isLocalCall
(
node
)
&&
builtinFunctions
[
getLocalCallName
(
node
)
+
'('
+
getFunctionCallTypeParameterType
(
node
)
+
')'
]
===
true
)
||
isAbiNamespaceCall
(
node
)
return
(
node
.
nodeType
===
'FunctionCall'
&&
isLocalCall
(
node
)
&&
builtinFunctions
[
getLocalCallName
(
node
)
+
'('
+
getFunctionCallTypeParameterType
(
node
)
+
')'
]
===
true
)
||
isAbiNamespaceCall
(
node
)
}
}
/**
/**
...
@@ -564,6 +592,7 @@ function isRequireCall (node: FunctionCallAstNode): boolean {
...
@@ -564,6 +592,7 @@ function isRequireCall (node: FunctionCallAstNode): boolean {
* @return {bool}
* @return {bool}
*/
*/
function
isStorageVariableDeclaration
(
node
:
VariableDeclarationAstNode
):
boolean
{
function
isStorageVariableDeclaration
(
node
:
VariableDeclarationAstNode
):
boolean
{
// console.log('storage variable----------', new RegExp(basicRegex.REFTYPE).test(node.typeDescriptions.typeIdentifier))
return
node
.
storageLocation
===
'storage'
&&
new
RegExp
(
basicRegex
.
REFTYPE
).
test
(
node
.
typeDescriptions
.
typeIdentifier
)
return
node
.
storageLocation
===
'storage'
&&
new
RegExp
(
basicRegex
.
REFTYPE
).
test
(
node
.
typeDescriptions
.
typeIdentifier
)
}
}
...
@@ -652,20 +681,21 @@ function isSubScopeWithTopLevelUnAssignedBinOp (node: BlockAstNode | IfStatement
...
@@ -652,20 +681,21 @@ function isSubScopeWithTopLevelUnAssignedBinOp (node: BlockAstNode | IfStatement
if
(
node
.
nodeType
===
'Block'
)
if
(
node
.
nodeType
===
'Block'
)
return
node
.
statements
.
some
(
isBinaryOpInExpression
)
return
node
.
statements
.
some
(
isBinaryOpInExpression
)
// for 'without braces' loops
// for 'without braces' loops
else
if
(
isSubScopeStatement
(
node
))
{
else
if
(
node
&&
node
.
nodeType
&&
isSubScopeStatement
(
node
))
{
if
(
node
.
nodeType
===
'IfStatement'
)
if
(
node
.
nodeType
===
'IfStatement'
)
return
(
node
.
trueBody
.
nodeType
===
"ExpressionStatement"
&&
isBinaryOpInExpression
(
node
.
trueBody
))
||
return
(
node
.
trueBody
&&
node
.
trueBody
.
nodeType
===
"ExpressionStatement"
&&
isBinaryOpInExpression
(
node
.
trueBody
))
||
(
node
.
falseBody
.
nodeType
===
"ExpressionStatement"
&&
isBinaryOpInExpression
(
node
.
falseBody
))
(
node
.
falseBody
&&
node
.
falseBody
.
nodeType
===
"ExpressionStatement"
&&
isBinaryOpInExpression
(
node
.
falseBody
))
else
else
return
node
.
body
.
nodeType
===
"ExpressionStatement"
&&
isBinaryOpInExpression
(
node
.
body
)
return
node
.
body
&&
node
.
body
.
nodeType
===
"ExpressionStatement"
&&
isBinaryOpInExpression
(
node
.
body
)
}
}
}
}
function
isSubScopeStatement
(
node
:
IfStatementAstNode
|
WhileStatementAstNode
|
ForStatementAstNode
):
boolean
{
function
isSubScopeStatement
(
node
:
IfStatementAstNode
|
WhileStatementAstNode
|
ForStatementAstNode
):
boolean
{
if
(
node
.
nodeType
===
'IfStatement'
)
if
(
node
.
nodeType
===
'IfStatement'
)
return
!
nodeType
(
node
.
trueBody
,
exactMatch
(
nodeTypes
.
BLOCK
))
&&
!
nodeType
(
node
.
falseBody
,
exactMatch
(
nodeTypes
.
BLOCK
))
return
(
node
.
trueBody
&&
node
.
trueBody
.
nodeType
&&
!
nodeType
(
node
.
trueBody
,
exactMatch
(
nodeTypes
.
BLOCK
)))
||
(
node
.
falseBody
&&
node
.
falseBody
.
nodeType
&&
!
nodeType
(
node
.
falseBody
,
exactMatch
(
nodeTypes
.
BLOCK
)))
else
else
return
!
nodeType
(
node
.
body
,
exactMatch
(
nodeTypes
.
BLOCK
))
return
node
.
body
&&
node
.
body
.
nodeType
&&
!
nodeType
(
node
.
body
,
exactMatch
(
nodeTypes
.
BLOCK
))
}
}
/**
/**
...
@@ -809,7 +839,8 @@ function isSuperLocalCall (node: MemberAccessAstNode): boolean {
...
@@ -809,7 +839,8 @@ function isSuperLocalCall (node: MemberAccessAstNode): boolean {
* @return {bool}
* @return {bool}
*/
*/
function
isLocalCall
(
node
:
FunctionCallAstNode
):
boolean
{
function
isLocalCall
(
node
:
FunctionCallAstNode
):
boolean
{
return
node
.
kind
===
'functionCall'
&&
return
node
.
nodeType
===
'FunctionCall'
&&
node
.
kind
===
'functionCall'
&&
node
.
expression
.
nodeType
===
'Identifier'
&&
node
.
expression
.
nodeType
===
'Identifier'
&&
expressionTypeDescription
(
node
,
basicRegex
.
FUNCTIONTYPE
)
&&
expressionTypeDescription
(
node
,
basicRegex
.
FUNCTIONTYPE
)
&&
!
expressionTypeDescription
(
node
,
basicRegex
.
EXTERNALFUNCTIONTYPE
)
!
expressionTypeDescription
(
node
,
basicRegex
.
EXTERNALFUNCTIONTYPE
)
...
@@ -952,15 +983,17 @@ function isBytesLengthCheck (node: MemberAccessAstNode): boolean {
...
@@ -952,15 +983,17 @@ function isBytesLengthCheck (node: MemberAccessAstNode): boolean {
// #################### Complex Node Identification - Private
// #################### Complex Node Identification - Private
function
isMemberAccess
(
node
:
MemberAccessAstNode
,
retType
:
string
,
accessor
:
string
|
undefined
,
accessorType
:
string
,
memberName
:
string
|
undefined
):
boolean
{
function
isMemberAccess
(
node
:
MemberAccessAstNode
,
retType
:
string
,
accessor
:
string
|
undefined
,
accessorType
:
string
,
memberName
:
string
|
undefined
):
boolean
{
const
nodeTypeDef
:
boolean
=
typeDescription
(
node
,
retType
)
if
(
node
&&
nodeType
(
node
,
exactMatch
(
'MemberAccess'
)))
{
console
.
log
(
'MemberAccess typeDef ->'
,
nodeTypeDef
)
const
nodeTypeDef
:
boolean
=
typeDescription
(
node
,
retType
)
const
nodeMemName
:
boolean
=
memName
(
node
,
memberName
)
// console.log('MemberAccess typeDef ->',nodeTypeDef)
console
.
log
(
'MemberAccess nodeMemName ->'
,
nodeMemName
)
const
nodeMemName
:
boolean
=
memName
(
node
,
memberName
)
const
nodeExpMemName
:
boolean
=
memName
(
node
.
expression
,
accessor
)
// console.log('MemberAccess nodeMemName ->',nodeMemName)
console
.
log
(
'MemberAccess nodeExpMemName ->'
,
nodeExpMemName
)
const
nodeExpMemName
:
boolean
=
memName
(
node
.
expression
,
accessor
)
const
nodeExpTypeDef
:
boolean
=
expressionTypeDescription
(
node
,
accessorType
)
// console.log('MemberAccess nodeExpMemName ->',nodeExpMemName)
console
.
log
(
'MemberAccess nodeExpTypeDef ->'
,
nodeExpTypeDef
)
const
nodeExpTypeDef
:
boolean
=
expressionTypeDescription
(
node
,
accessorType
)
return
nodeTypeDef
&&
nodeMemName
&&
nodeExpTypeDef
&&
nodeExpMemName
// console.log('MemberAccess nodeExpTypeDef ->',nodeExpTypeDef)
return
nodeTypeDef
&&
nodeMemName
&&
nodeExpTypeDef
&&
nodeExpMemName
}
else
return
false
}
}
function
isSpecialVariableAccess
(
node
:
MemberAccessAstNode
,
varType
:
any
):
boolean
{
function
isSpecialVariableAccess
(
node
:
MemberAccessAstNode
,
varType
:
any
):
boolean
{
...
@@ -989,11 +1022,15 @@ function typeDescription (node: any, typeRegex: string): boolean {
...
@@ -989,11 +1022,15 @@ function typeDescription (node: any, typeRegex: string): boolean {
return
new
RegExp
(
typeRegex
).
test
(
node
.
typeDescriptions
.
typeString
)
return
new
RegExp
(
typeRegex
).
test
(
node
.
typeDescriptions
.
typeString
)
}
}
function
nodeType
(
node
,
typeRegex
)
{
function
nodeType
(
node
:
any
,
typeRegex
:
string
)
{
return
new
RegExp
(
typeRegex
).
test
(
node
.
nodeType
)
return
new
RegExp
(
typeRegex
).
test
(
node
.
nodeType
)
}
}
function
memName
(
node
,
memNameRegex
)
{
function
nodeTypeIn
(
node
:
any
,
typeRegex
:
string
[]){
return
typeRegex
.
some
((
typeRegex
)
=>
nodeType
(
node
,
typeRegex
))
}
function
memName
(
node
:
any
,
memNameRegex
:
any
)
{
// const regex = new RegExp(memNameRegex)
// const regex = new RegExp(memNameRegex)
return
(
node
&&
!
memNameRegex
)
||
new
RegExp
(
memNameRegex
).
test
(
node
.
name
)
||
new
RegExp
(
memNameRegex
).
test
(
node
.
memberName
)
return
(
node
&&
!
memNameRegex
)
||
new
RegExp
(
memNameRegex
).
test
(
node
.
name
)
||
new
RegExp
(
memNameRegex
).
test
(
node
.
memberName
)
}
}
...
...
remix-analyzer/src/solidity-analyzer/modules/thisLocal.ts
View file @
8ccef1c5
...
@@ -11,7 +11,7 @@ export default class thisLocal implements AnalyzerModule {
...
@@ -11,7 +11,7 @@ export default class thisLocal implements AnalyzerModule {
algorithm
:
ModuleAlgorithm
=
algorithm
.
EXACT
algorithm
:
ModuleAlgorithm
=
algorithm
.
EXACT
visit
(
node
:
MemberAccessAstNode
):
void
{
visit
(
node
:
MemberAccessAstNode
):
void
{
if
(
isThisLocalCall
(
node
))
this
.
warningNodes
.
push
(
node
)
if
(
node
.
nodeType
===
'MemberAccess'
&&
isThisLocalCall
(
node
))
this
.
warningNodes
.
push
(
node
)
}
}
report
(
compilationResults
:
CompilationResult
):
ReportObj
[]
{
report
(
compilationResults
:
CompilationResult
):
ReportObj
[]
{
...
...
remix-analyzer/test/analysis/staticAnalysisCommon-test.ts
View file @
8ccef1c5
...
@@ -266,9 +266,8 @@ test('staticAnalysisCommon.getFullQuallyfiedFuncDefinitionIdent', function (t) {
...
@@ -266,9 +266,8 @@ test('staticAnalysisCommon.getFullQuallyfiedFuncDefinitionIdent', function (t) {
// #################### Complex Node Identification
// #################### Complex Node Identification
test
(
'staticAnalysisCommon.isBuiltinFunctionCall'
,
function
(
t
)
{
test
(
'staticAnalysisCommon.isBuiltinFunctionCall'
,
function
(
t
)
{
t
.
plan
(
2
)
t
.
plan
(
1
)
t
.
ok
(
common
.
isBuiltinFunctionCall
(
selfdestruct
),
'selfdestruct is builtin'
)
t
.
ok
(
common
.
isBuiltinFunctionCall
(
selfdestruct
),
'selfdestruct is builtin'
)
t
.
throws
(()
=>
common
.
isBuiltinFunctionCall
(
localCall
),
Error
,
'local call is not builtin'
)
})
})
test
(
'staticAnalysisCommon.isStorageVariableDeclaration'
,
function
(
t
)
{
test
(
'staticAnalysisCommon.isStorageVariableDeclaration'
,
function
(
t
)
{
...
...
remix-analyzer/test/analysis/staticAnalysisIntegration-test-0.5.0.ts
View file @
8ccef1c5
This diff is collapsed.
Click to expand it.
remix-analyzer/test/analysis/test-contracts/solidity-v0.5/ballot.sol
View file @
8ccef1c5
...
@@ -121,7 +121,7 @@ contract Ballot {
...
@@ -121,7 +121,7 @@ contract Ballot {
/// @dev Computes the winning proposal taking all
/// @dev Computes the winning proposal taking all
/// previous votes into account.
/// previous votes into account.
function winningProposal()
view public
function winningProposal()
public view
returns (uint winningProposal)
returns (uint winningProposal)
{
{
uint winningVoteCount = 0;
uint winningVoteCount = 0;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment