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
e9ac30cb
Commit
e9ac30cb
authored
Feb 25, 2020
by
aniket-engg
Committed by
Aniket
Mar 24, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
node identification methods removed
parent
d5548b62
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
156 additions
and
231 deletions
+156
-231
abstractAstView.ts
...analyzer/src/solidity-analyzer/modules/abstractAstView.ts
+11
-11
constantFunctions.ts
...alyzer/src/solidity-analyzer/modules/constantFunctions.ts
+7
-7
etherTransferInLoop.ts
...yzer/src/solidity-analyzer/modules/etherTransferInLoop.ts
+9
-18
forLoopIteratesOverDynamicArray.ts
...idity-analyzer/modules/forLoopIteratesOverDynamicArray.ts
+4
-4
inlineAssembly.ts
...-analyzer/src/solidity-analyzer/modules/inlineAssembly.ts
+4
-5
noReturn.ts
remix-analyzer/src/solidity-analyzer/modules/noReturn.ts
+6
-6
staticAnalysisCommon.ts
...zer/src/solidity-analyzer/modules/staticAnalysisCommon.ts
+44
-109
types.ts
remix-analyzer/src/types.ts
+2
-2
staticAnalysisCommon-test.ts
remix-analyzer/test/analysis/staticAnalysisCommon-test.ts
+69
-69
No files found.
remix-analyzer/src/solidity-analyzer/modules/abstractAstView.ts
View file @
e9ac30cb
import
{
isContractDefinition
,
getStateVariableDeclarationsFormContractNode
,
isInheritanceSpecifier
,
import
{
getStateVariableDeclarationsFormContractNode
,
getInheritsFromName
,
isModifierDefinition
,
isModifierInvocation
,
getContractName
,
getInheritsFromName
,
getContractName
,
getFunctionOrModifierDefinitionParameterPart
,
getType
,
getDeclaredVariableName
,
isVariableDeclaration
,
getFunctionOrModifierDefinitionParameterPart
,
getType
,
getDeclaredVariableName
,
getFunctionDefinitionReturnParameterPart
}
from
'./staticAnalysisCommon'
getFunctionDefinitionReturnParameterPart
}
from
'./staticAnalysisCommon'
import
{
AstWalker
}
from
'remix-astwalker'
import
{
AstWalker
}
from
'remix-astwalker'
import
{
CommonAstNode
}
from
'types'
import
{
CommonAstNode
,
FunctionDefinitionAstNode
,
ParameterListAstNode
}
from
'types'
export
default
class
abstractAstView
{
export
default
class
abstractAstView
{
contracts
=
[]
contracts
=
[]
...
@@ -49,7 +49,7 @@ export default class abstractAstView {
...
@@ -49,7 +49,7 @@ export default class abstractAstView {
*/
*/
build_visit
(
relevantNodeFilter
)
{
build_visit
(
relevantNodeFilter
)
{
var
that
=
this
var
that
=
this
return
function
(
node
:
CommonAstNode
)
{
return
function
(
node
:
any
)
{
if
(
node
.
nodeType
===
"ContractDefinition"
)
{
if
(
node
.
nodeType
===
"ContractDefinition"
)
{
that
.
setCurrentContract
(
that
,
{
that
.
setCurrentContract
(
that
,
{
node
:
node
,
node
:
node
,
...
@@ -59,7 +59,7 @@ export default class abstractAstView {
...
@@ -59,7 +59,7 @@ export default class abstractAstView {
inheritsFrom
:
[],
inheritsFrom
:
[],
stateVariables
:
getStateVariableDeclarationsFormContractNode
(
node
)
stateVariables
:
getStateVariableDeclarationsFormContractNode
(
node
)
})
})
}
else
if
(
isInheritanceSpecifier
(
node
)
)
{
}
else
if
(
node
.
nodeType
===
"InheritanceSpecifier"
)
{
const
currentContract
=
that
.
getCurrentContract
(
that
)
const
currentContract
=
that
.
getCurrentContract
(
that
)
const
inheritsFromName
=
getInheritsFromName
(
node
)
const
inheritsFromName
=
getInheritsFromName
(
node
)
currentContract
.
inheritsFrom
.
push
(
inheritsFromName
)
currentContract
.
inheritsFrom
.
push
(
inheritsFromName
)
...
@@ -78,14 +78,14 @@ export default class abstractAstView {
...
@@ -78,14 +78,14 @@ export default class abstractAstView {
that
.
getCurrentFunction
(
that
).
relevantNodes
.
push
(
item
.
node
)
that
.
getCurrentFunction
(
that
).
relevantNodes
.
push
(
item
.
node
)
}
}
})
})
}
else
if
(
isModifierDefinition
(
node
)
)
{
}
else
if
(
node
.
nodeType
===
"ModifierDefinition"
)
{
that
.
setCurrentModifier
(
that
,
{
that
.
setCurrentModifier
(
that
,
{
node
:
node
,
node
:
node
,
relevantNodes
:
[],
relevantNodes
:
[],
localVariables
:
that
.
getLocalVariables
(
node
),
localVariables
:
that
.
getLocalVariables
(
node
),
parameters
:
that
.
getLocalParameters
(
node
)
parameters
:
that
.
getLocalParameters
(
node
)
})
})
}
else
if
(
isModifierInvocation
(
node
)
)
{
}
else
if
(
node
.
nodeType
===
"ModifierInvocation"
)
{
if
(
!
that
.
isFunctionNotModifier
)
throw
new
Error
(
'abstractAstView.js: Found modifier invocation outside of function scope.'
)
if
(
!
that
.
isFunctionNotModifier
)
throw
new
Error
(
'abstractAstView.js: Found modifier invocation outside of function scope.'
)
that
.
getCurrentFunction
(
that
).
modifierInvocations
.
push
(
node
)
that
.
getCurrentFunction
(
that
).
modifierInvocations
.
push
(
node
)
}
else
if
(
relevantNodeFilter
(
node
))
{
}
else
if
(
relevantNodeFilter
(
node
))
{
...
@@ -160,7 +160,7 @@ export default class abstractAstView {
...
@@ -160,7 +160,7 @@ export default class abstractAstView {
}
}
private
getLocalParameters
(
funcNode
)
{
private
getLocalParameters
(
funcNode
)
{
return
this
.
getLocalVariables
(
getFunctionOrModifierDefinitionParameterPart
(
funcNode
))
.
map
(
getType
)
return
getFunctionOrModifierDefinitionParameterPart
(
funcNode
).
parameters
.
map
(
getType
)
}
}
private
getReturnParameters
(
funcNode
)
{
private
getReturnParameters
(
funcNode
)
{
...
@@ -172,10 +172,10 @@ export default class abstractAstView {
...
@@ -172,10 +172,10 @@ export default class abstractAstView {
})
})
}
}
private
getLocalVariables
(
funcNode
)
{
private
getLocalVariables
(
funcNode
:
ParameterListAstNode
)
{
const
locals
:
any
[]
=
[]
const
locals
:
any
[]
=
[]
new
AstWalker
().
walk
(
funcNode
,
{
'*'
:
function
(
node
)
{
new
AstWalker
().
walk
(
funcNode
,
{
'*'
:
function
(
node
)
{
if
(
isVariableDeclaration
(
node
)
)
locals
.
push
(
node
)
if
(
node
.
nodeType
===
"VariableDeclaration"
)
locals
.
push
(
node
)
return
true
return
true
}})
}})
return
locals
return
locals
...
...
remix-analyzer/src/solidity-analyzer/modules/constantFunctions.ts
View file @
e9ac30cb
import
{
default
as
category
}
from
'./categories'
import
{
default
as
category
}
from
'./categories'
import
{
isLowLevelCall
,
isTransfer
,
isExternalDirectCall
,
isEffect
,
isLocalCallGraphRelevantNode
,
import
{
isLowLevelCall
,
isTransfer
,
isExternalDirectCall
,
isEffect
,
isLocalCallGraphRelevantNode
,
is
InlineAssembly
,
isNewExpression
,
is
SelfdestructCall
,
isDeleteUnaryOperation
,
isPayableFunction
,
isSelfdestructCall
,
isDeleteUnaryOperation
,
isPayableFunction
,
isConstructor
,
getFullQuallyfiedFuncDefinitionIdent
,
hasFunctionBody
,
isConstantFunction
,
isWriteOnStateVariable
,
isConstructor
,
getFullQuallyfiedFuncDefinitionIdent
,
hasFunctionBody
,
isConstantFunction
,
isWriteOnStateVariable
,
isStorageVariableDeclaration
,
isCallToNonConstLocalFunction
,
getFullQualifiedFunctionCallIdent
}
from
'./staticAnalysisCommon'
isStorageVariableDeclaration
,
isCallToNonConstLocalFunction
,
getFullQualifiedFunctionCallIdent
}
from
'./staticAnalysisCommon'
import
{
default
as
algorithm
}
from
'./algorithmCategories'
import
{
default
as
algorithm
}
from
'./algorithmCategories'
import
{
buildGlobalFuncCallGraph
,
resolveCallGraphSymbol
,
analyseCallGraph
}
from
'./functionCallGraph'
import
{
buildGlobalFuncCallGraph
,
resolveCallGraphSymbol
,
analyseCallGraph
}
from
'./functionCallGraph'
import
AbstractAst
from
'./abstractAstView'
import
AbstractAst
from
'./abstractAstView'
import
{
AnalyzerModule
,
ModuleAlgorithm
,
ModuleCategory
,
ReportObj
,
AstNodeLegacy
,
CompilationResult
}
from
'./../../types'
import
{
AnalyzerModule
,
ModuleAlgorithm
,
ModuleCategory
,
ReportObj
,
AstNodeLegacy
,
CompilationResult
,
CommonAstNode
}
from
'./../../types'
export
default
class
constantFunctions
implements
AnalyzerModule
{
export
default
class
constantFunctions
implements
AnalyzerModule
{
name
:
string
=
'Constant functions: '
name
:
string
=
'Constant functions: '
...
@@ -17,13 +17,13 @@ export default class constantFunctions implements AnalyzerModule {
...
@@ -17,13 +17,13 @@ export default class constantFunctions implements AnalyzerModule {
abstractAst
:
AbstractAst
=
new
AbstractAst
()
abstractAst
:
AbstractAst
=
new
AbstractAst
()
visit
=
this
.
abstractAst
.
build_visit
(
visit
=
this
.
abstractAst
.
build_visit
(
(
node
:
AstNodeLegacy
)
=>
isLowLevelCall
(
node
)
||
(
node
:
CommonAstNode
)
=>
isLowLevelCall
(
node
)
||
isTransfer
(
node
)
||
isTransfer
(
node
)
||
isExternalDirectCall
(
node
)
||
isExternalDirectCall
(
node
)
||
isEffect
(
node
)
||
isEffect
(
node
)
||
isLocalCallGraphRelevantNode
(
node
)
||
isLocalCallGraphRelevantNode
(
node
)
||
isInlineAssembly
(
node
)
||
node
.
nodeType
===
"InlineAssembly"
||
isNewExpression
(
node
)
||
node
.
nodeType
===
"NewExpression"
||
isSelfdestructCall
(
node
)
||
isSelfdestructCall
(
node
)
||
isDeleteUnaryOperation
(
node
)
isDeleteUnaryOperation
(
node
)
)
)
...
@@ -98,8 +98,8 @@ export default class constantFunctions implements AnalyzerModule {
...
@@ -98,8 +98,8 @@ export default class constantFunctions implements AnalyzerModule {
isTransfer
(
node
)
||
isTransfer
(
node
)
||
this
.
isCallOnNonConstExternalInterfaceFunction
(
node
,
context
)
||
this
.
isCallOnNonConstExternalInterfaceFunction
(
node
,
context
)
||
isCallToNonConstLocalFunction
(
node
)
||
isCallToNonConstLocalFunction
(
node
)
||
isInlineAssembly
(
node
)
||
node
.
nodeType
===
"InlineAssembly"
||
isNewExpression
(
node
)
||
node
.
nodeType
===
"NewExpression"
||
isSelfdestructCall
(
node
)
||
isSelfdestructCall
(
node
)
||
isDeleteUnaryOperation
(
node
)
isDeleteUnaryOperation
(
node
)
}
}
...
...
remix-analyzer/src/solidity-analyzer/modules/etherTransferInLoop.ts
View file @
e9ac30cb
import
{
default
as
category
}
from
'./categories'
import
{
default
as
category
}
from
'./categories'
import
{
default
as
algorithm
}
from
'./algorithmCategories'
import
{
default
as
algorithm
}
from
'./algorithmCategories'
import
{
isLoop
,
isBlock
,
getLoopBlockStartIndex
,
isExpressionStatement
,
isTransfer
}
from
'./staticAnalysisCommon'
import
{
getLoopBlockStartIndex
,
isTransfer
}
from
'./staticAnalysisCommon'
import
{
AnalyzerModule
,
ModuleAlgorithm
,
ModuleCategory
,
ReportObj
,
AstNodeLegacy
,
CompilationResult
}
from
'./../../types'
import
{
AnalyzerModule
,
ModuleAlgorithm
,
ModuleCategory
,
ReportObj
,
AstNodeLegacy
,
CompilationResult
,
ForStatementAstNode
,
WhileStatementAstNode
,
CommonAstNode
,
ExpressionStatementAstNode
}
from
'./../../types'
export
default
class
etherTransferInLoop
implements
AnalyzerModule
{
export
default
class
etherTransferInLoop
implements
AnalyzerModule
{
relevantNodes
:
AstNodeLegacy
[]
=
[]
relevantNodes
:
CommonAstNode
[]
=
[]
name
:
string
=
'Ether transfer in a loop: '
name
:
string
=
'Ether transfer in a loop: '
description
:
string
=
'Avoid transferring Ether to multiple addresses in a loop'
description
:
string
=
'Avoid transferring Ether to multiple addresses in a loop'
category
:
ModuleCategory
=
category
.
GAS
category
:
ModuleCategory
=
category
.
GAS
algorithm
:
ModuleAlgorithm
=
algorithm
.
EXACT
algorithm
:
ModuleAlgorithm
=
algorithm
.
EXACT
visit
(
node
:
AstNodeLegacy
):
void
{
visit
(
node
:
ForStatementAstNode
|
WhileStatementAstNode
):
void
{
if
(
isLoop
(
node
))
{
let
transferNodes
:
CommonAstNode
[]
=
[]
let
transferNodes
:
AstNodeLegacy
[]
=
[]
transferNodes
=
node
.
body
.
statements
.
filter
(
child
=>
(
const
loopBlockStartIndex
:
number
|
undefined
=
getLoopBlockStartIndex
(
node
)
child
.
nodeType
===
'ExpressionStatement'
&&
if
(
loopBlockStartIndex
&&
node
.
children
&&
isBlock
(
node
.
children
[
loopBlockStartIndex
]))
{
child
.
expression
.
nodeType
===
'FunctionCall'
&&
const
childrenNodes
:
AstNodeLegacy
[]
|
undefined
=
node
.
children
[
loopBlockStartIndex
].
children
isTransfer
(
child
.
expression
.
expression
)
if
(
childrenNodes
)
transferNodes
=
childrenNodes
.
filter
(
child
=>
(
isExpressionStatement
(
child
)
&&
child
.
children
&&
child
.
children
[
0
].
name
===
'FunctionCall'
&&
child
.
children
[
0
].
children
&&
isTransfer
(
child
.
children
[
0
].
children
[
0
])
)
)
)
)
if
(
transferNodes
.
length
>
0
)
{
if
(
transferNodes
.
length
>
0
)
{
this
.
relevantNodes
.
push
(...
transferNodes
)
this
.
relevantNodes
.
push
(...
transferNodes
)
}
}
}
}
}
}
report
(
compilationResults
:
CompilationResult
):
ReportObj
[]
{
report
(
compilationResults
:
CompilationResult
):
ReportObj
[]
{
return
this
.
relevantNodes
.
map
((
node
)
=>
{
return
this
.
relevantNodes
.
map
((
node
)
=>
{
...
...
remix-analyzer/src/solidity-analyzer/modules/forLoopIteratesOverDynamicArray.ts
View file @
e9ac30cb
import
{
default
as
category
}
from
'./categories'
import
{
default
as
category
}
from
'./categories'
import
{
default
as
algorithm
}
from
'./algorithmCategories'
import
{
default
as
algorithm
}
from
'./algorithmCategories'
import
{
isForLoop
,
isDynamicArrayLengthAccess
,
isBinaryOperation
}
from
'./staticAnalysisCommon'
import
{
isForLoop
,
isDynamicArrayLengthAccess
,
isBinaryOperation
}
from
'./staticAnalysisCommon'
import
{
AnalyzerModule
,
ModuleAlgorithm
,
ModuleCategory
,
ReportObj
,
AstNodeLegacy
,
CompilationResult
}
from
'./../../types'
import
{
AnalyzerModule
,
ModuleAlgorithm
,
ModuleCategory
,
ReportObj
,
AstNodeLegacy
,
CompilationResult
,
CommonAstNode
}
from
'./../../types'
export
default
class
forLoopIteratesOverDynamicArray
implements
AnalyzerModule
{
export
default
class
forLoopIteratesOverDynamicArray
implements
AnalyzerModule
{
relevantNodes
:
AstNodeLegacy
[]
=
[]
relevantNodes
:
CommonAstNode
[]
=
[]
name
:
string
=
'For loop iterates over dynamic array: '
name
:
string
=
'For loop iterates over dynamic array: '
description
:
string
=
'The number of
\'
for
\'
loop iterations depends on dynamic array
\'
s size'
description
:
string
=
'The number of
\'
for
\'
loop iterations depends on dynamic array
\'
s size'
category
:
ModuleCategory
=
category
.
GAS
category
:
ModuleCategory
=
category
.
GAS
algorithm
:
ModuleAlgorithm
=
algorithm
.
EXACT
algorithm
:
ModuleAlgorithm
=
algorithm
.
EXACT
visit
(
node
:
AstNodeLegacy
):
void
{
visit
(
node
:
CommonAstNode
):
void
{
if
(
isForLoop
(
node
)
&&
node
.
children
)
{
if
(
node
.
nodeType
===
"Forstatement"
&&
node
.
children
)
{
let
conditionChildrenNode
:
AstNodeLegacy
|
null
=
null
let
conditionChildrenNode
:
AstNodeLegacy
|
null
=
null
// Access 'condition' node of 'for' loop statement
// Access 'condition' node of 'for' loop statement
const
forLoopConditionNode
:
AstNodeLegacy
=
node
.
children
[
1
]
const
forLoopConditionNode
:
AstNodeLegacy
=
node
.
children
[
1
]
...
...
remix-analyzer/src/solidity-analyzer/modules/inlineAssembly.ts
View file @
e9ac30cb
import
{
default
as
category
}
from
'./categories'
import
{
default
as
category
}
from
'./categories'
import
{
isInlineAssembly
}
from
'./staticAnalysisCommon'
import
{
default
as
algorithm
}
from
'./algorithmCategories'
import
{
default
as
algorithm
}
from
'./algorithmCategories'
import
{
AnalyzerModule
,
ModuleAlgorithm
,
ModuleCategory
,
ReportObj
,
AstNodeLegacy
,
CompilationResult
}
from
'./../../types'
import
{
AnalyzerModule
,
ModuleAlgorithm
,
ModuleCategory
,
ReportObj
,
AstNodeLegacy
,
CompilationResult
,
InlineAssemblyAstNode
}
from
'./../../types'
export
default
class
inlineAssembly
implements
AnalyzerModule
{
export
default
class
inlineAssembly
implements
AnalyzerModule
{
inlineAssNodes
:
AstNodeLegacy
[]
=
[]
inlineAssNodes
:
InlineAssemblyAstNode
[]
=
[]
name
:
string
=
'Inline assembly: '
name
:
string
=
'Inline assembly: '
description
:
string
=
'Use of Inline Assembly'
description
:
string
=
'Use of Inline Assembly'
category
:
ModuleCategory
=
category
.
SECURITY
category
:
ModuleCategory
=
category
.
SECURITY
algorithm
:
ModuleAlgorithm
=
algorithm
.
EXACT
algorithm
:
ModuleAlgorithm
=
algorithm
.
EXACT
visit
(
node
:
AstNodeLegacy
):
void
{
visit
(
node
:
InlineAssemblyAstNode
):
void
{
if
(
isInlineAssembly
(
node
))
this
.
inlineAssNodes
.
push
(
node
)
this
.
inlineAssNodes
.
push
(
node
)
}
}
report
(
compilationResults
:
CompilationResult
):
ReportObj
[]
{
report
(
compilationResults
:
CompilationResult
):
ReportObj
[]
{
...
...
remix-analyzer/src/solidity-analyzer/modules/noReturn.ts
View file @
e9ac30cb
import
{
default
as
category
}
from
'./categories'
import
{
default
as
category
}
from
'./categories'
import
{
isReturn
,
isAssignment
,
hasFunctionBody
,
getFullQuallyfiedFuncDefinitionIdent
,
getEffectedVariableName
}
from
'./staticAnalysisCommon'
import
{
hasFunctionBody
,
getFullQuallyfiedFuncDefinitionIdent
,
getEffectedVariableName
}
from
'./staticAnalysisCommon'
import
{
default
as
algorithm
}
from
'./algorithmCategories'
import
{
default
as
algorithm
}
from
'./algorithmCategories'
import
AbstractAst
from
'./abstractAstView'
import
AbstractAst
from
'./abstractAstView'
import
{
AnalyzerModule
,
ModuleAlgorithm
,
ModuleCategory
,
ReportObj
,
AstNodeLegacy
,
CompilationResult
}
from
'./../../types'
import
{
AnalyzerModule
,
ModuleAlgorithm
,
ModuleCategory
,
ReportObj
,
AstNodeLegacy
,
CompilationResult
,
CommonAstNode
,
FunctionDefinitionAstNode
}
from
'./../../types'
export
default
class
noReturn
implements
AnalyzerModule
{
export
default
class
noReturn
implements
AnalyzerModule
{
name
:
string
=
'no return: '
name
:
string
=
'no return: '
...
@@ -13,7 +13,7 @@ export default class noReturn implements AnalyzerModule {
...
@@ -13,7 +13,7 @@ export default class noReturn implements AnalyzerModule {
abstractAst
:
AbstractAst
=
new
AbstractAst
()
abstractAst
:
AbstractAst
=
new
AbstractAst
()
visit
=
this
.
abstractAst
.
build_visit
(
visit
=
this
.
abstractAst
.
build_visit
(
(
node
:
AstNodeLegacy
)
=>
isReturn
(
node
)
||
isAssignment
(
node
)
(
node
:
CommonAstNode
)
=>
node
.
nodeType
===
"Return"
||
node
.
nodeType
===
"Assignment"
)
)
report
=
this
.
abstractAst
.
build_report
(
this
.
_report
.
bind
(
this
))
report
=
this
.
abstractAst
.
build_report
(
this
.
_report
.
bind
(
this
))
...
@@ -44,13 +44,13 @@ export default class noReturn implements AnalyzerModule {
...
@@ -44,13 +44,13 @@ export default class noReturn implements AnalyzerModule {
return
func
.
returns
.
length
>
0
return
func
.
returns
.
length
>
0
}
}
private
hasReturnStatement
(
func
):
boolean
{
private
hasReturnStatement
(
func
:
CommonAstNode
):
boolean
{
return
func
.
relevantNodes
.
filter
(
isReturn
).
length
>
0
return
func
.
relevantNodes
.
filter
(
n
=>
n
.
nodeType
===
"Return"
).
length
>
0
}
}
private
hasAssignToAllNamedReturns
(
func
):
boolean
{
private
hasAssignToAllNamedReturns
(
func
):
boolean
{
const
namedReturns
=
func
.
returns
.
filter
((
n
)
=>
n
.
name
.
length
>
0
).
map
((
n
)
=>
n
.
name
)
const
namedReturns
=
func
.
returns
.
filter
((
n
)
=>
n
.
name
.
length
>
0
).
map
((
n
)
=>
n
.
name
)
const
assignedVars
=
func
.
relevantNodes
.
filter
(
isAssignment
).
map
(
getEffectedVariableName
)
const
assignedVars
=
func
.
relevantNodes
.
filter
(
n
=>
n
.
nodeType
===
"Assignment"
).
map
(
getEffectedVariableName
)
const
diff
=
namedReturns
.
filter
(
e
=>
!
assignedVars
.
includes
(
e
))
const
diff
=
namedReturns
.
filter
(
e
=>
!
assignedVars
.
includes
(
e
))
return
diff
.
length
===
0
return
diff
.
length
===
0
}
}
...
...
remix-analyzer/src/solidity-analyzer/modules/staticAnalysisCommon.ts
View file @
e9ac30cb
This diff is collapsed.
Click to expand it.
remix-analyzer/src/types.ts
View file @
e9ac30cb
...
@@ -95,7 +95,7 @@ export interface ContractDefinitionAstNode {
...
@@ -95,7 +95,7 @@ export interface ContractDefinitionAstNode {
linearizedBaseContracts
:
Array
<
number
>
linearizedBaseContracts
:
Array
<
number
>
baseContracts
:
Array
<
InheritanceSpecifierAstNode
>
baseContracts
:
Array
<
InheritanceSpecifierAstNode
>
contractDependencies
:
Array
<
number
>
contractDependencies
:
Array
<
number
>
nodes
:
Array
<
any
>
nodes
:
Array
<
CommonAstNode
>
scope
:
number
scope
:
number
}
}
...
@@ -298,7 +298,7 @@ export interface BlockAstNode {
...
@@ -298,7 +298,7 @@ export interface BlockAstNode {
id
:
number
id
:
number
nodeType
:
'Block'
nodeType
:
'Block'
src
:
string
src
:
string
statements
:
Array
<
object
>
statements
:
Array
<
CommonAstNode
>
}
}
export
interface
PlaceholderStatementAstNode
{
export
interface
PlaceholderStatementAstNode
{
...
...
remix-analyzer/test/analysis/staticAnalysisCommon-test.ts
View file @
e9ac30cb
...
@@ -317,89 +317,89 @@ test('staticAnalysisCommon.getLoopBlockStartIndex', function (t) {
...
@@ -317,89 +317,89 @@ test('staticAnalysisCommon.getLoopBlockStartIndex', function (t) {
// t.notOk(common.isFunctionDefinition(node3), 'substring should not work')
// t.notOk(common.isFunctionDefinition(node3), 'substring should not work')
// })
// })
test
(
'staticAnalysisCommon.isModifierDefinition'
,
function
(
t
)
{
//
test('staticAnalysisCommon.isModifierDefinition', function (t) {
t
.
plan
(
3
)
//
t.plan(3)
const
node1
=
{
name
:
'ModifierDefinition'
}
//
const node1 = { name: 'ModifierDefinition' }
const
node2
=
{
name
:
'MemberAccess'
}
//
const node2 = { name: 'MemberAccess' }
const
node3
=
{
name
:
'ModifierDefinitionBLABLA'
}
//
const node3 = { name: 'ModifierDefinitionBLABLA' }
t
.
ok
(
common
.
isModifierDefinition
(
node1
),
'is exact match should work'
)
//
t.ok(common.isModifierDefinition(node1), 'is exact match should work')
t
.
notOk
(
common
.
isModifierDefinition
(
node2
),
'different node should not work'
)
//
t.notOk(common.isModifierDefinition(node2), 'different node should not work')
t
.
notOk
(
common
.
isModifierDefinition
(
node3
),
'substring should not work'
)
//
t.notOk(common.isModifierDefinition(node3), 'substring should not work')
})
//
})
test
(
'staticAnalysisCommon.isModifierInvocation'
,
function
(
t
)
{
//
test('staticAnalysisCommon.isModifierInvocation', function (t) {
t
.
plan
(
3
)
//
t.plan(3)
const
node1
=
{
name
:
'ModifierInvocation'
}
//
const node1 = { name: 'ModifierInvocation' }
const
node2
=
{
name
:
'MemberAccess'
}
//
const node2 = { name: 'MemberAccess' }
const
node3
=
{
name
:
'ModifierInvocationBLABLA'
}
//
const node3 = { name: 'ModifierInvocationBLABLA' }
t
.
ok
(
common
.
isModifierInvocation
(
node1
),
'is exact match should work'
)
//
t.ok(common.isModifierInvocation(node1), 'is exact match should work')
t
.
notOk
(
common
.
isModifierInvocation
(
node2
),
'different node should not work'
)
//
t.notOk(common.isModifierInvocation(node2), 'different node should not work')
t
.
notOk
(
common
.
isModifierInvocation
(
node3
),
'substring should not work'
)
//
t.notOk(common.isModifierInvocation(node3), 'substring should not work')
})
//
})
test
(
'staticAnalysisCommon.isVariableDeclaration'
,
function
(
t
)
{
//
test('staticAnalysisCommon.isVariableDeclaration', function (t) {
t
.
plan
(
3
)
//
t.plan(3)
const
node1
=
{
name
:
'VariableDeclaration'
}
//
const node1 = { name: 'VariableDeclaration' }
const
node2
=
{
name
:
'MemberAccess'
}
//
const node2 = { name: 'MemberAccess' }
const
node3
=
{
name
:
'VariableDeclarationBLABLA'
}
//
const node3 = { name: 'VariableDeclarationBLABLA' }
t
.
ok
(
common
.
isVariableDeclaration
(
node1
),
'is exact match should work'
)
//
t.ok(common.isVariableDeclaration(node1), 'is exact match should work')
t
.
notOk
(
common
.
isVariableDeclaration
(
node2
),
'different node should not work'
)
//
t.notOk(common.isVariableDeclaration(node2), 'different node should not work')
t
.
notOk
(
common
.
isVariableDeclaration
(
node3
),
'substring should not work'
)
//
t.notOk(common.isVariableDeclaration(node3), 'substring should not work')
})
//
})
test
(
'staticAnalysisCommon.isInheritanceSpecifier'
,
function
(
t
)
{
//
test('staticAnalysisCommon.isInheritanceSpecifier', function (t) {
t
.
plan
(
3
)
//
t.plan(3)
const
node1
=
{
name
:
'InheritanceSpecifier'
}
//
const node1 = { name: 'InheritanceSpecifier' }
const
node2
=
{
name
:
'MemberAccess'
}
//
const node2 = { name: 'MemberAccess' }
const
node3
=
{
name
:
'InheritanceSpecifierBLABLA'
}
//
const node3 = { name: 'InheritanceSpecifierBLABLA' }
t
.
ok
(
common
.
isInheritanceSpecifier
(
node1
),
'is exact match should work'
)
//
t.ok(common.isInheritanceSpecifier(node1), 'is exact match should work')
t
.
notOk
(
common
.
isInheritanceSpecifier
(
node2
),
'different node should not work'
)
//
t.notOk(common.isInheritanceSpecifier(node2), 'different node should not work')
t
.
notOk
(
common
.
isInheritanceSpecifier
(
node3
),
'substring should not work'
)
//
t.notOk(common.isInheritanceSpecifier(node3), 'substring should not work')
})
//
})
test
(
'staticAnalysisCommon.isAssignment'
,
function
(
t
)
{
//
test('staticAnalysisCommon.isAssignment', function (t) {
t
.
plan
(
3
)
//
t.plan(3)
const
node1
=
{
name
:
'Assignment'
}
//
const node1 = { name: 'Assignment' }
const
node2
=
{
name
:
'MemberAccess'
}
//
const node2 = { name: 'MemberAccess' }
const
node3
=
{
name
:
'AssignmentBLABLA'
}
//
const node3 = { name: 'AssignmentBLABLA' }
t
.
ok
(
common
.
isAssignment
(
node1
),
'is exact match should work'
)
//
t.ok(common.isAssignment(node1), 'is exact match should work')
t
.
notOk
(
common
.
isAssignment
(
node2
),
'different node should not work'
)
//
t.notOk(common.isAssignment(node2), 'different node should not work')
t
.
notOk
(
common
.
isAssignment
(
node3
),
'substring should not work'
)
//
t.notOk(common.isAssignment(node3), 'substring should not work')
})
//
})
test
(
'staticAnalysisCommon.isContractDefinition'
,
function
(
t
)
{
//
test('staticAnalysisCommon.isContractDefinition', function (t) {
t
.
plan
(
3
)
//
t.plan(3)
const
node1
=
{
name
:
'ContractDefinition'
}
//
const node1 = { name: 'ContractDefinition' }
const
node2
=
{
name
:
'MemberAccess'
}
//
const node2 = { name: 'MemberAccess' }
const
node3
=
{
name
:
'ContractDefinitionBLABLA'
}
//
const node3 = { name: 'ContractDefinitionBLABLA' }
t
.
ok
(
common
.
isContractDefinition
(
node1
),
'is exact match should work'
)
//
t.ok(common.isContractDefinition(node1), 'is exact match should work')
t
.
notOk
(
common
.
isContractDefinition
(
node2
),
'different node should not work'
)
//
t.notOk(common.isContractDefinition(node2), 'different node should not work')
t
.
notOk
(
common
.
isContractDefinition
(
node3
),
'substring should not work'
)
//
t.notOk(common.isContractDefinition(node3), 'substring should not work')
})
//
})
test
(
'staticAnalysisCommon.isInlineAssembly'
,
function
(
t
)
{
//
test('staticAnalysisCommon.isInlineAssembly', function (t) {
t
.
plan
(
3
)
//
t.plan(3)
const
node1
=
{
name
:
'InlineAssembly'
}
//
const node1 = { name: 'InlineAssembly' }
const
node2
=
{
name
:
'MemberAccess'
}
//
const node2 = { name: 'MemberAccess' }
const
node3
=
{
name
:
'InlineAssemblyBLABLA'
}
//
const node3 = { name: 'InlineAssemblyBLABLA' }
t
.
ok
(
common
.
isInlineAssembly
(
node1
),
'is exact match should work'
)
//
t.ok(common.isInlineAssembly(node1), 'is exact match should work')
t
.
notOk
(
common
.
isInlineAssembly
(
node2
),
'different node should not work'
)
//
t.notOk(common.isInlineAssembly(node2), 'different node should not work')
t
.
notOk
(
common
.
isInlineAssembly
(
node3
),
'substring should not work'
)
//
t.notOk(common.isInlineAssembly(node3), 'substring should not work')
})
//
})
test
(
'staticAnalysisCommon.isLoop'
,
function
(
t
)
{
//
test('staticAnalysisCommon.isLoop', function (t) {
t
.
plan
(
3
)
//
t.plan(3)
t
.
equal
(
common
.
isLoop
(
forLoopNode
),
true
)
//
t.equal(common.isLoop(forLoopNode), true)
t
.
equal
(
common
.
isLoop
(
doWhileLoopNode
),
true
)
//
t.equal(common.isLoop(doWhileLoopNode), true)
t
.
equal
(
common
.
isLoop
(
whileLoopNode
),
true
)
//
t.equal(common.isLoop(whileLoopNode), true)
})
//
})
// #################### Complex Node Identification
// #################### Complex Node Identification
...
...
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