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
04dccc92
Commit
04dccc92
authored
Feb 26, 2020
by
aniket-engg
Committed by
Aniket
Mar 24, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
method updates
parent
e9ac30cb
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
108 additions
and
117 deletions
+108
-117
abstractAstView.ts
...analyzer/src/solidity-analyzer/modules/abstractAstView.ts
+3
-3
constantFunctions.ts
...alyzer/src/solidity-analyzer/modules/constantFunctions.ts
+1
-1
deleteDynamicArrays.ts
...yzer/src/solidity-analyzer/modules/deleteDynamicArrays.ts
+3
-3
forLoopIteratesOverDynamicArray.ts
...idity-analyzer/modules/forLoopIteratesOverDynamicArray.ts
+9
-17
intDivisionTruncate.ts
...yzer/src/solidity-analyzer/modules/intDivisionTruncate.ts
+3
-3
lowLevelCalls.ts
...x-analyzer/src/solidity-analyzer/modules/lowLevelCalls.ts
+3
-3
staticAnalysisCommon.ts
...zer/src/solidity-analyzer/modules/staticAnalysisCommon.ts
+77
-76
thisLocal.ts
remix-analyzer/src/solidity-analyzer/modules/thisLocal.ts
+3
-3
types.ts
remix-analyzer/src/types.ts
+6
-8
No files found.
remix-analyzer/src/solidity-analyzer/modules/abstractAstView.ts
View file @
04dccc92
...
...
@@ -3,7 +3,7 @@ import { getStateVariableDeclarationsFormContractNode,
getFunctionOrModifierDefinitionParameterPart
,
getType
,
getDeclaredVariableName
,
getFunctionDefinitionReturnParameterPart
}
from
'./staticAnalysisCommon'
import
{
AstWalker
}
from
'remix-astwalker'
import
{
CommonAstNode
,
FunctionDefinitionAstNode
,
ParameterListAstNode
}
from
'types'
import
{
CommonAstNode
,
FunctionDefinitionAstNode
,
ParameterListAstNode
,
ModifierDefinitionAstNode
}
from
'types'
export
default
class
abstractAstView
{
contracts
=
[]
...
...
@@ -159,11 +159,11 @@ export default class abstractAstView {
return
that
.
getCurrentContract
(
that
).
modifiers
[
that
.
currentModifierIndex
]
}
private
getLocalParameters
(
funcNode
)
{
private
getLocalParameters
(
funcNode
:
FunctionDefinitionAstNode
|
ModifierDefinitionAstNode
)
{
return
getFunctionOrModifierDefinitionParameterPart
(
funcNode
).
parameters
.
map
(
getType
)
}
private
getReturnParameters
(
funcNode
)
{
private
getReturnParameters
(
funcNode
:
FunctionDefinitionAstNode
)
{
return
this
.
getLocalVariables
(
getFunctionDefinitionReturnParameterPart
(
funcNode
)).
map
((
n
)
=>
{
return
{
type
:
getType
(
n
),
...
...
remix-analyzer/src/solidity-analyzer/modules/constantFunctions.ts
View file @
04dccc92
...
...
@@ -17,7 +17,7 @@ export default class constantFunctions implements AnalyzerModule {
abstractAst
:
AbstractAst
=
new
AbstractAst
()
visit
=
this
.
abstractAst
.
build_visit
(
(
node
:
CommonAstNode
)
=>
isLowLevelCall
(
node
)
||
(
node
:
any
)
=>
isLowLevelCall
(
node
)
||
isTransfer
(
node
)
||
isExternalDirectCall
(
node
)
||
isEffect
(
node
)
||
...
...
remix-analyzer/src/solidity-analyzer/modules/deleteDynamicArrays.ts
View file @
04dccc92
import
{
default
as
category
}
from
'./categories'
import
{
isDeleteOfDynamicArray
}
from
'./staticAnalysisCommon'
import
{
default
as
algorithm
}
from
'./algorithmCategories'
import
{
AnalyzerModule
,
ModuleAlgorithm
,
ModuleCategory
,
ReportObj
,
AstNodeLegacy
,
CompilationResult
}
from
'./../../types'
import
{
AnalyzerModule
,
ModuleAlgorithm
,
ModuleCategory
,
ReportObj
,
CompilationResult
,
UnaryOperationAstNode
}
from
'./../../types'
export
default
class
deleteDynamicArrays
implements
AnalyzerModule
{
rel
:
AstNodeLegacy
[]
=
[]
rel
:
UnaryOperationAstNode
[]
=
[]
name
:
string
=
'Delete on dynamic Array: '
description
:
string
=
'Use require and appropriately'
category
:
ModuleCategory
=
category
.
GAS
algorithm
:
ModuleAlgorithm
=
algorithm
.
EXACT
visit
(
node
:
AstNodeLegacy
):
void
{
visit
(
node
:
UnaryOperationAstNode
):
void
{
if
(
isDeleteOfDynamicArray
(
node
))
this
.
rel
.
push
(
node
)
}
...
...
remix-analyzer/src/solidity-analyzer/modules/forLoopIteratesOverDynamicArray.ts
View file @
04dccc92
import
{
default
as
category
}
from
'./categories'
import
{
default
as
algorithm
}
from
'./algorithmCategories'
import
{
is
ForLoop
,
isDynamicArrayLengthAccess
,
isBinaryOperation
}
from
'./staticAnalysisCommon'
import
{
AnalyzerModule
,
ModuleAlgorithm
,
ModuleCategory
,
ReportObj
,
AstNodeLegacy
,
CompilationResult
,
Common
AstNode
}
from
'./../../types'
import
{
is
DynamicArrayLengthAccess
}
from
'./staticAnalysisCommon'
import
{
AnalyzerModule
,
ModuleAlgorithm
,
ModuleCategory
,
ReportObj
,
CompilationResult
,
ForStatement
AstNode
}
from
'./../../types'
export
default
class
forLoopIteratesOverDynamicArray
implements
AnalyzerModule
{
relevantNodes
:
Common
AstNode
[]
=
[]
relevantNodes
:
ForStatement
AstNode
[]
=
[]
name
:
string
=
'For loop iterates over dynamic array: '
description
:
string
=
'The number of
\'
for
\'
loop iterations depends on dynamic array
\'
s size'
category
:
ModuleCategory
=
category
.
GAS
algorithm
:
ModuleAlgorithm
=
algorithm
.
EXACT
visit
(
node
:
CommonAstNode
):
void
{
if
(
node
.
nodeType
===
"Forstatement"
&&
node
.
children
)
{
let
conditionChildrenNode
:
AstNodeLegacy
|
null
=
null
// Access 'condition' node of 'for' loop statement
const
forLoopConditionNode
:
AstNodeLegacy
=
node
.
children
[
1
]
// Access right side of condition as its children
if
(
forLoopConditionNode
&&
forLoopConditionNode
.
children
){
conditionChildrenNode
=
forLoopConditionNode
.
children
[
1
]
}
// Check if it is a binary operation. if yes, check if its children node access length of dynamic array
if
(
conditionChildrenNode
&&
conditionChildrenNode
.
children
&&
isBinaryOperation
(
conditionChildrenNode
)
&&
isDynamicArrayLengthAccess
(
conditionChildrenNode
.
children
[
0
]))
{
this
.
relevantNodes
.
push
(
node
)
}
else
if
(
isDynamicArrayLengthAccess
(
conditionChildrenNode
))
{
// else check if condition node itself access length of dynamic array
visit
(
node
:
ForStatementAstNode
):
void
{
const
{
condition
}
=
node
// Check if condition is `i < array.length - 1`
if
((
condition
.
nodeType
===
"BinaryOperation"
&&
condition
.
rightExpression
.
nodeType
===
"BinaryOperation"
&&
isDynamicArrayLengthAccess
(
condition
.
rightExpression
.
leftExpression
))
||
// or condition is `i < array.length`
(
condition
.
nodeType
===
"BinaryOperation"
&&
isDynamicArrayLengthAccess
(
condition
.
rightExpression
)))
{
this
.
relevantNodes
.
push
(
node
)
}
}
}
report
(
compilationResults
:
CompilationResult
):
ReportObj
[]
{
...
...
remix-analyzer/src/solidity-analyzer/modules/intDivisionTruncate.ts
View file @
04dccc92
import
{
default
as
category
}
from
'./categories'
import
{
isIntDivision
}
from
'./staticAnalysisCommon'
import
{
default
as
algorithm
}
from
'./algorithmCategories'
import
{
AnalyzerModule
,
ModuleAlgorithm
,
ModuleCategory
,
ReportObj
,
AstNodeLegacy
,
CompilationResult
}
from
'./../../types'
import
{
AnalyzerModule
,
ModuleAlgorithm
,
ModuleCategory
,
ReportObj
,
CompilationResult
,
BinaryOperationAstNode
}
from
'./../../types'
export
default
class
intDivisionTruncate
implements
AnalyzerModule
{
warningNodes
:
AstNodeLegacy
[]
=
[]
warningNodes
:
BinaryOperationAstNode
[]
=
[]
name
:
string
=
'Data Truncated: '
description
:
string
=
'Division on int/uint values truncates the result.'
category
:
ModuleCategory
=
category
.
MISC
algorithm
:
ModuleAlgorithm
=
algorithm
.
EXACT
visit
(
node
:
AstNodeLegacy
):
void
{
visit
(
node
:
BinaryOperationAstNode
):
void
{
if
(
isIntDivision
(
node
))
this
.
warningNodes
.
push
(
node
)
}
...
...
remix-analyzer/src/solidity-analyzer/modules/lowLevelCalls.ts
View file @
04dccc92
...
...
@@ -2,10 +2,10 @@ import { default as category } from './categories'
import
{
isLowLevelCallInst
,
isLowLevelCallInst050
,
isLowLevelCallcodeInst
,
isLowLevelDelegatecallInst
,
isLowLevelSendInst
,
isLowLevelSendInst050
,
isLLDelegatecallInst050
,
lowLevelCallTypes
}
from
'./staticAnalysisCommon'
import
{
default
as
algorithm
}
from
'./algorithmCategories'
import
{
AnalyzerModule
,
ModuleAlgorithm
,
ModuleCategory
,
ReportObj
,
AstNodeLegacy
,
CompilationResult
}
from
'./../../types'
import
{
AnalyzerModule
,
ModuleAlgorithm
,
ModuleCategory
,
ReportObj
,
CompilationResult
,
MemberAccessAstNode
}
from
'./../../types'
interface
llcNode
{
node
:
AstNodeLegacy
node
:
MemberAccessAstNode
type
:
{
ident
:
string
,
type
:
string
...
...
@@ -19,7 +19,7 @@ export default class lowLevelCalls implements AnalyzerModule {
category
:
ModuleCategory
=
category
.
SECURITY
algorithm
:
ModuleAlgorithm
=
algorithm
.
EXACT
visit
(
node
:
AstNodeLegacy
):
void
{
visit
(
node
:
MemberAccessAstNode
):
void
{
if
(
isLowLevelCallInst
(
node
))
{
this
.
llcNodes
.
push
({
node
:
node
,
type
:
lowLevelCallTypes
.
CALL
})
}
else
if
(
isLowLevelCallInst050
(
node
))
{
...
...
remix-analyzer/src/solidity-analyzer/modules/staticAnalysisCommon.ts
View file @
04dccc92
'use strict'
import
{
FunctionDefinitionAstNode
,
ModifierDefinitionAstNode
,
ParameterListAstNode
,
CommonAstNode
,
ForStatementAstNode
,
WhileStatementAstNode
,
VariableDeclarationAstNode
,
ContractDefinitionAstNode
,
InheritanceSpecifierAstNode
,
MemberAccessAstNode
}
from
"types"
import
{
FunctionDefinitionAstNode
,
ModifierDefinitionAstNode
,
ParameterListAstNode
,
CommonAstNode
,
ForStatementAstNode
,
WhileStatementAstNode
,
VariableDeclarationAstNode
,
ContractDefinitionAstNode
,
InheritanceSpecifierAstNode
,
MemberAccessAstNode
,
BinaryOperationAstNode
,
FunctionCallAstNode
,
ExpressionStatementAstNode
,
UnaryOperationAstNode
,
IdentifierAstNode
,
MappingAstNode
,
IndexAccessAstNode
}
from
"types"
const
remixLib
=
require
(
'remix-lib'
)
const
util
=
remixLib
.
util
...
...
@@ -433,8 +433,8 @@ function isBinaryOperation (node) {
* @funcNode {ASTNode} function defintion node
* @return {bool}
*/
function
hasFunctionBody
(
funcNode
)
{
return
f
indFirstSubNodeLTR
(
funcNode
,
exactMatch
(
nodeTypes
.
BLOCK
))
!=
null
function
hasFunctionBody
(
funcNode
:
FunctionDefinitionAstNode
)
{
return
f
uncNode
.
body
!=
null
}
/**
...
...
@@ -442,8 +442,8 @@ function hasFunctionBody (funcNode) {
* @node {ASTNode} node to check for
* @return {bool}
*/
function
isDeleteOfDynamicArray
(
node
)
{
return
isDeleteUnaryOperation
(
node
)
&&
isDynamicArrayAccess
(
node
.
children
[
0
]
)
function
isDeleteOfDynamicArray
(
node
:
UnaryOperationAstNode
)
{
return
isDeleteUnaryOperation
(
node
)
&&
isDynamicArrayAccess
(
node
.
subExpression
)
}
/**
...
...
@@ -451,8 +451,8 @@ function isDeleteOfDynamicArray (node) {
* @node {ASTNode} node to check for
* @return {bool}
*/
function
isDynamicArrayAccess
(
node
)
{
return
node
&&
nodeType
(
node
,
exactMatch
(
nodeTypes
.
IDENTIFIER
))
&&
(
node
.
attributes
.
type
.
endsWith
(
'[] storage ref'
)
||
node
.
attributes
.
type
===
'bytes storage ref'
||
node
.
attributes
.
type
===
'string storage ref'
)
function
isDynamicArrayAccess
(
node
:
IdentifierAstNode
)
{
return
typeDescription
(
node
,
'[] storage ref'
)
||
typeDescription
(
node
,
'bytes storage ref'
)
||
typeDescription
(
node
,
'string storage ref'
)
}
/**
...
...
@@ -460,11 +460,9 @@ function isDynamicArrayAccess (node) {
* @node {ASTNode} node to check for
* @return {bool}
*/
function
isDynamicArrayLengthAccess
(
node
)
{
return
node
&&
// if node exists
nodeType
(
node
,
exactMatch
(
nodeTypes
.
MEMBERACCESS
))
&&
// is memberAccess Node
(
node
.
attributes
.
member_name
===
'length'
)
&&
// accessing 'length' member
node
.
children
[
0
].
attributes
.
type
.
indexOf
(
'[]'
)
!==
-
1
// member is accessed from dynamic array, notice [] without any number
function
isDynamicArrayLengthAccess
(
node
:
MemberAccessAstNode
)
{
return
(
node
.
memberName
===
'length'
)
&&
// accessing 'length' member
node
.
expression
[
'typeDescriptions'
][
'typeString'
].
indexOf
(
'[]'
)
!==
-
1
// member is accessed from dynamic array, notice [] without any number
}
/**
...
...
@@ -627,8 +625,8 @@ function isConstructor (node: FunctionDefinitionAstNode): boolean {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function
isIntDivision
(
node
)
{
return
isBinaryOperation
(
node
)
&&
operator
(
node
,
exactMatch
(
util
.
escapeRegExp
(
'/'
)))
&&
expressionType
(
node
,
util
.
escapeRegExp
(
'int'
))
function
isIntDivision
(
node
:
BinaryOperationAstNode
)
{
return
operator
(
node
,
exactMatch
(
util
.
escapeRegExp
(
'/'
)))
&&
typeDescription
(
node
.
rightExpression
,
util
.
escapeRegExp
(
'int'
))
}
/**
...
...
@@ -646,7 +644,7 @@ function isSubScopeStatement (node) {
nodeType
(
node
,
exactMatch
(
nodeTypes
.
FORSTATEMENT
))
||
nodeType
(
node
,
exactMatch
(
nodeTypes
.
WHILESTATEMENT
))
||
nodeType
(
node
,
exactMatch
(
nodeTypes
.
DOWHILESTATEMENT
)))
&&
minNrOfChildren
(
node
,
2
)
&&
!
nodeType
(
node
.
children
[
1
],
exactMatch
(
nodeTypes
.
BLOCK
))
!
nodeType
(
node
.
children
[
1
],
exactMatch
(
nodeTypes
.
BLOCK
))
}
/**
...
...
@@ -654,8 +652,8 @@ function isSubScopeStatement (node) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function
isBinaryOpInExpression
(
node
)
{
return
node
.
nodeType
===
"ExpressionStatement"
&&
n
rOfChildren
(
node
,
1
)
&&
isBinaryOperation
(
node
.
children
[
0
])
function
isBinaryOpInExpression
(
node
:
ExpressionStatementAstNode
)
{
return
node
.
nodeType
===
"ExpressionStatement"
&&
n
ode
.
expression
.
nodeType
===
"BinaryOperation"
}
/**
...
...
@@ -663,8 +661,8 @@ function isBinaryOpInExpression (node) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function
isPlusPlusUnaryOperation
(
node
)
{
return
node
Type
(
node
,
exactMatch
(
nodeTypes
.
UNARYOPERATION
))
&&
operator
(
node
,
exactMatch
(
util
.
escapeRegExp
(
'++'
)))
function
isPlusPlusUnaryOperation
(
node
:
UnaryOperationAstNode
)
{
return
node
.
operator
===
'++'
}
/**
...
...
@@ -672,8 +670,8 @@ function isPlusPlusUnaryOperation (node) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function
isDeleteUnaryOperation
(
node
)
{
return
node
Type
(
node
,
exactMatch
(
nodeTypes
.
UNARYOPERATION
))
&&
operator
(
node
,
exactMatch
(
util
.
escapeRegExp
(
'delete'
)))
function
isDeleteUnaryOperation
(
node
:
UnaryOperationAstNode
)
{
return
node
.
operator
===
'delete'
}
/**
...
...
@@ -681,8 +679,8 @@ function isDeleteUnaryOperation (node) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function
isMinusMinusUnaryOperation
(
node
)
{
return
node
Type
(
node
,
exactMatch
(
nodeTypes
.
UNARYOPERATION
))
&&
operator
(
node
,
exactMatch
(
util
.
escapeRegExp
(
'--'
)))
function
isMinusMinusUnaryOperation
(
node
:
UnaryOperationAstNode
)
{
return
node
.
operator
===
'--'
}
/**
...
...
@@ -690,8 +688,8 @@ function isMinusMinusUnaryOperation (node) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function
isFullyImplementedContract
(
node
)
{
return
node
Type
(
node
,
exactMatch
(
nodeTypes
.
CONTRACTDEFINITION
))
&&
node
.
attributes
.
fullyImplemented
===
true
function
isFullyImplementedContract
(
node
:
ContractDefinitionAstNode
)
{
return
node
.
fullyImplemented
===
true
}
/**
...
...
@@ -699,8 +697,8 @@ function isFullyImplementedContract (node) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function
isLibrary
(
node
)
{
return
node
Type
(
node
,
exactMatch
(
nodeTypes
.
CONTRACTDEFINITION
))
&&
node
.
attributes
.
isLibrary
===
true
function
isLibrary
(
node
:
ContractDefinitionAstNode
)
{
return
node
.
contractKind
===
'library'
}
/**
...
...
@@ -708,8 +706,8 @@ function isLibrary (node) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function
isCallToNonConstLocalFunction
(
node
)
{
return
isLocalCall
(
node
)
&&
!
expressionType
(
node
.
children
[
0
]
,
basicRegex
.
CONSTANTFUNCTIONTYPE
)
function
isCallToNonConstLocalFunction
(
node
:
FunctionCallAstNode
)
{
return
isLocalCall
(
node
)
&&
!
expressionType
(
node
,
basicRegex
.
CONSTANTFUNCTIONTYPE
)
}
/**
...
...
@@ -717,7 +715,7 @@ function isCallToNonConstLocalFunction (node) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function
isLibraryCall
(
node
)
{
function
isLibraryCall
(
node
:
MemberAccessAstNode
)
{
return
isMemberAccess
(
node
,
basicRegex
.
FUNCTIONTYPE
,
undefined
,
basicRegex
.
LIBRARYTYPE
,
undefined
)
}
...
...
@@ -726,7 +724,7 @@ function isLibraryCall (node) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function
isExternalDirectCall
(
node
)
{
function
isExternalDirectCall
(
node
:
MemberAccessAstNode
)
{
return
isMemberAccess
(
node
,
basicRegex
.
EXTERNALFUNCTIONTYPE
,
undefined
,
basicRegex
.
CONTRACTTYPE
,
undefined
)
&&
!
isThisLocalCall
(
node
)
&&
!
isSuperLocalCall
(
node
)
}
...
...
@@ -735,10 +733,8 @@ function isExternalDirectCall (node) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function
isNowAccess
(
node
)
{
return
nodeType
(
node
,
exactMatch
(
nodeTypes
.
IDENTIFIER
))
&&
expressionType
(
node
,
exactMatch
(
basicTypes
.
UINT
))
&&
memName
(
node
,
exactMatch
(
'now'
))
function
isNowAccess
(
node
:
IdentifierAstNode
)
{
return
node
.
name
===
"now"
&&
typeDescription
(
node
,
exactMatch
(
basicTypes
.
UINT
))
}
/**
...
...
@@ -746,7 +742,7 @@ function isNowAccess (node) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function
isBlockTimestampAccess
(
node
)
{
function
isBlockTimestampAccess
(
node
:
MemberAccessAstNode
)
{
return
isSpecialVariableAccess
(
node
,
specialVariables
.
BLOCKTIMESTAMP
)
}
...
...
@@ -755,7 +751,7 @@ function isBlockTimestampAccess (node) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function
isBlockBlockHashAccess
(
node
)
{
function
isBlockBlockHashAccess
(
node
:
MemberAccessAstNode
)
{
return
isSpecialVariableAccess
(
node
,
specialVariables
.
BLOCKHASH
)
||
isBuiltinFunctionCall
(
node
)
&&
getLocalCallName
(
node
)
===
'blockhash'
}
...
...
@@ -764,7 +760,7 @@ function isBlockBlockHashAccess (node) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function
isThisLocalCall
(
node
)
{
function
isThisLocalCall
(
node
:
MemberAccessAstNode
)
{
return
isMemberAccess
(
node
,
basicRegex
.
FUNCTIONTYPE
,
exactMatch
(
'this'
),
basicRegex
.
CONTRACTTYPE
,
undefined
)
}
...
...
@@ -773,7 +769,7 @@ function isThisLocalCall (node) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function
isSuperLocalCall
(
node
)
{
function
isSuperLocalCall
(
node
:
MemberAccessAstNode
)
{
return
isMemberAccess
(
node
,
basicRegex
.
FUNCTIONTYPE
,
exactMatch
(
'super'
),
basicRegex
.
CONTRACTTYPE
,
undefined
)
}
...
...
@@ -782,13 +778,11 @@ function isSuperLocalCall (node) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function
isLocalCall
(
node
)
{
return
nodeType
(
node
,
exactMatch
(
nodeTypes
.
FUNCTIONCALL
))
&&
minNrOfChildren
(
node
,
1
)
&&
nodeType
(
node
.
children
[
0
],
exactMatch
(
nodeTypes
.
IDENTIFIER
))
&&
expressionType
(
node
.
children
[
0
],
basicRegex
.
FUNCTIONTYPE
)
&&
!
expressionType
(
node
.
children
[
0
],
basicRegex
.
EXTERNALFUNCTIONTYPE
)
&&
nrOfChildren
(
node
.
children
[
0
],
0
)
function
isLocalCall
(
node
:
FunctionCallAstNode
)
{
return
node
.
kind
===
'functionCall'
&&
node
.
expression
.
nodeType
===
'Identifier'
&&
expressionTypeDescription
(
node
,
basicRegex
.
FUNCTIONTYPE
)
&&
!
expressionTypeDescription
(
node
,
basicRegex
.
FUNCTIONTYPE
)
}
/**
...
...
@@ -811,7 +805,7 @@ function isLowLevelCall (node) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function
isLLSend050
(
node
)
{
function
isLLSend050
(
node
:
MemberAccessAstNode
)
{
return
isMemberAccess
(
node
,
exactMatch
(
util
.
escapeRegExp
(
lowLevelCallTypes
.
SEND
.
type
)),
undefined
,
exactMatch
(
basicTypes
.
PAYABLE_ADDRESS
),
exactMatch
(
lowLevelCallTypes
.
SEND
.
ident
))
...
...
@@ -822,7 +816,7 @@ function isLLSend050 (node) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function
isLLSend
(
node
)
{
function
isLLSend
(
node
:
MemberAccessAstNode
)
{
return
isMemberAccess
(
node
,
exactMatch
(
util
.
escapeRegExp
(
lowLevelCallTypes
.
SEND
.
type
)),
undefined
,
exactMatch
(
basicTypes
.
ADDRESS
),
exactMatch
(
lowLevelCallTypes
.
SEND
.
ident
))
...
...
@@ -833,7 +827,7 @@ function isLLSend (node) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function
isLLCall
(
node
)
{
function
isLLCall
(
node
:
MemberAccessAstNode
)
{
return
isMemberAccess
(
node
,
exactMatch
(
util
.
escapeRegExp
(
lowLevelCallTypes
.
CALL
.
type
)),
undefined
,
exactMatch
(
basicTypes
.
ADDRESS
),
exactMatch
(
lowLevelCallTypes
.
CALL
.
ident
))
...
...
@@ -844,7 +838,7 @@ function isLLCall (node) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function
isLLCall050
(
node
)
{
function
isLLCall050
(
node
:
MemberAccessAstNode
)
{
return
isMemberAccess
(
node
,
exactMatch
(
util
.
escapeRegExp
(
lowLevelCallTypes
[
'CALL-v0.5'
].
type
)),
undefined
,
exactMatch
(
basicTypes
.
PAYABLE_ADDRESS
),
exactMatch
(
lowLevelCallTypes
[
'CALL-v0.5'
].
ident
))
...
...
@@ -855,7 +849,7 @@ function isLLCall050 (node) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function
isLLCallcode
(
node
)
{
function
isLLCallcode
(
node
:
MemberAccessAstNode
)
{
return
isMemberAccess
(
node
,
exactMatch
(
util
.
escapeRegExp
(
lowLevelCallTypes
.
CALLCODE
.
type
)),
undefined
,
exactMatch
(
basicTypes
.
ADDRESS
),
exactMatch
(
lowLevelCallTypes
.
CALLCODE
.
ident
))
...
...
@@ -866,7 +860,7 @@ function isLLCallcode (node) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function
isLLDelegatecall
(
node
)
{
function
isLLDelegatecall
(
node
:
MemberAccessAstNode
)
{
return
isMemberAccess
(
node
,
exactMatch
(
util
.
escapeRegExp
(
lowLevelCallTypes
.
DELEGATECALL
.
type
)),
undefined
,
exactMatch
(
basicTypes
.
ADDRESS
),
exactMatch
(
lowLevelCallTypes
.
DELEGATECALL
.
ident
))
...
...
@@ -877,7 +871,7 @@ function isLLDelegatecall (node) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function
isLLDelegatecall050
(
node
)
{
function
isLLDelegatecall050
(
node
:
MemberAccessAstNode
)
{
return
isMemberAccess
(
node
,
exactMatch
(
util
.
escapeRegExp
(
lowLevelCallTypes
[
'DELEGATECALL-v0.5'
].
type
)),
undefined
,
matches
(
basicTypes
.
PAYABLE_ADDRESS
,
basicTypes
.
ADDRESS
),
exactMatch
(
lowLevelCallTypes
[
'DELEGATECALL-v0.5'
].
ident
))
...
...
@@ -888,7 +882,7 @@ function isLLDelegatecall050 (node) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function
isTransfer
(
node
)
{
function
isTransfer
(
node
:
MemberAccessAstNode
)
{
return
isMemberAccess
(
node
,
exactMatch
(
util
.
escapeRegExp
(
lowLevelCallTypes
.
TRANSFER
.
type
)),
undefined
,
matches
(
basicTypes
.
ADDRESS
,
basicTypes
.
PAYABLE_ADDRESS
),
exactMatch
(
lowLevelCallTypes
.
TRANSFER
.
ident
))
...
...
@@ -898,13 +892,13 @@ function isStringToBytesConversion (node) {
return
isExplicitCast
(
node
,
util
.
escapeRegExp
(
'string *'
),
util
.
escapeRegExp
(
'bytes'
))
}
function
isExplicitCast
(
node
,
castFromType
,
castToType
)
{
return
node
Type
(
node
,
exactMatch
(
nodeTypes
.
FUNCTIONCALL
))
&&
nrOfChildren
(
node
,
2
)
&&
nodeType
(
node
.
children
[
0
],
exactMatch
(
nodeTypes
.
ELEMENTARYTYPENAMEEXPRESSION
))
&&
memName
(
node
.
children
[
0
],
castToType
)
&&
nodeType
(
node
.
children
[
1
],
exactMatch
(
nodeTypes
.
IDENTIFIER
))
&&
expressionType
(
node
.
children
[
1
],
castFromType
)
function
isExplicitCast
(
node
:
FunctionCallAstNode
,
castFromType
:
string
,
castToType
:
string
)
{
return
node
.
kind
===
"typeConversion"
&&
nodeType
(
node
.
expression
,
exactMatch
(
nodeTypes
.
ELEMENTARYTYPENAMEEXPRESSION
))
&&
node
.
expression
.
typeName
.
name
===
castToType
&&
nodeType
(
node
.
arguments
[
0
],
exactMatch
(
nodeTypes
.
IDENTIFIER
))
&&
typeDescription
(
node
.
arguments
[
0
],
castFromType
)
}
function
isBytesLengthCheck
(
node
)
{
function
isBytesLengthCheck
(
node
:
MemberAccessAstNode
)
{
return
isMemberAccess
(
node
,
exactMatch
(
util
.
escapeRegExp
(
basicTypes
.
UINT
)),
undefined
,
util
.
escapeRegExp
(
'bytes *'
),
'length'
)
}
...
...
@@ -925,41 +919,48 @@ function isBytesLengthCheck (node) {
* @return {bool}
* TODO: This should be removed once for loop iterates Over dynamic array fixed
*/
function
isForLoop
(
node
)
{
return
nodeType
(
node
,
exactMatch
(
nodeTypes
.
FORSTATEMENT
))
}
//
function isForLoop (node) {
//
return nodeType(node, exactMatch(nodeTypes.FORSTATEMENT))
//
}
// #################### Complex Node Identification - Private
function
isMemberAccess
(
node
:
MemberAccessAstNode
,
retType
,
accessor
,
accessorType
,
memberName
)
{
function
isMemberAccess
(
node
:
MemberAccessAstNode
,
retType
:
string
,
accessor
:
string
|
undefined
,
accessorType
,
memberName
:
string
|
undefined
)
{
return
nodeType
(
node
,
exactMatch
(
nodeTypes
.
MEMBERACCESS
))
&&
expressionType
(
node
,
retType
)
&&
memName
(
node
,
memberName
)
&&
nrOfChildren
(
node
,
1
)
&&
memName
(
node
.
expression
,
accessor
)
&&
expressionType
(
node
.
expression
,
accessorType
)
}
function
isSpecialVariableAccess
(
node
,
varType
)
{
function
isSpecialVariableAccess
(
node
:
MemberAccessAstNode
,
varType
)
{
return
isMemberAccess
(
node
,
exactMatch
(
util
.
escapeRegExp
(
varType
.
type
)),
varType
.
obj
,
varType
.
obj
,
varType
.
member
)
}
// #################### Node Identification Primitives
function
nrOfChildren
(
node
,
nr
)
{
return
(
node
&&
(
nr
===
undefined
||
nr
===
null
))
||
(
node
&&
nr
===
0
&&
!
node
.
children
)
||
(
node
&&
node
.
children
&&
node
.
children
.
length
===
nr
)
// function nrOfChildren (node, nr) {
// return (node && (nr === undefined || nr === null)) || (node && nr === 0 && !node.children) || (node && node.children && node.children.length === nr)
// }
// function minNrOfChildren (node, nr) {
// return (node && (nr === undefined || nr === null)) || (node && nr === 0 && !node.children) || (node && node.children && node.children.length >= nr)
// }
function
expressionType
(
node
,
typeRegex
)
{
return
new
RegExp
(
typeRegex
).
test
(
node
.
expression
.
typeDescriptions
.
typeString
)
}
function
minNrOfChildren
(
node
,
nr
)
{
return
(
node
&&
(
nr
===
undefined
||
nr
===
null
))
||
(
node
&&
nr
===
0
&&
!
node
.
children
)
||
(
node
&&
node
.
children
&&
node
.
children
.
length
>=
nr
)
function
expressionTypeDescription
(
node
,
typeRegex
)
{
return
new
RegExp
(
typeRegex
).
test
(
node
.
expression
.
typeDescriptions
.
typeString
)
}
function
expressionType
(
node
,
typeRegex
)
{
return
(
node
&&
!
typeRegex
)
||
(
node
&&
node
.
attributes
&&
new
RegExp
(
typeRegex
).
test
(
node
.
attributes
.
type
)
)
function
typeDescription
(
node
,
typeRegex
)
{
return
new
RegExp
(
typeRegex
).
test
(
node
.
typeDescriptions
.
typeString
)
}
function
nodeType
(
node
,
typeRegex
)
{
return
(
node
&&
!
typeRegex
)
||
(
node
&&
new
RegExp
(
typeRegex
).
test
(
node
.
name
)
)
return
new
RegExp
(
typeRegex
).
test
(
node
.
nodeType
)
}
function
memName
(
node
,
memNameRegex
)
{
...
...
@@ -968,7 +969,7 @@ function memName (node, memNameRegex) {
}
function
operator
(
node
,
opRegex
)
{
return
(
node
&&
!
opRegex
)
||
(
node
&&
new
RegExp
(
opRegex
).
test
(
node
.
attributes
.
operator
)
)
return
new
RegExp
(
opRegex
).
test
(
node
.
operator
)
}
// #################### Helpers
...
...
@@ -1021,8 +1022,8 @@ function findFirstSubNodeLTR (node, type) {
}
const
helpers
=
{
nrOfChildren
,
minNrOfChildren
,
//
nrOfChildren,
//
minNrOfChildren,
expressionType
,
nodeType
,
memName
,
...
...
@@ -1104,7 +1105,7 @@ export {
isIntDivision
,
isStringToBytesConversion
,
isBytesLengthCheck
,
isForLoop
,
//
isForLoop,
// #################### Trivial Node Identification
isDeleteUnaryOperation
,
...
...
remix-analyzer/src/solidity-analyzer/modules/thisLocal.ts
View file @
04dccc92
import
{
default
as
category
}
from
'./categories'
import
{
isThisLocalCall
}
from
'./staticAnalysisCommon'
import
{
default
as
algorithm
}
from
'./algorithmCategories'
import
{
AnalyzerModule
,
ModuleAlgorithm
,
ModuleCategory
,
ReportObj
,
AstNodeLegacy
,
CompilationResult
}
from
'./../../types'
import
{
AnalyzerModule
,
ModuleAlgorithm
,
ModuleCategory
,
ReportObj
,
AstNodeLegacy
,
CompilationResult
,
MemberAccessAstNode
}
from
'./../../types'
export
default
class
thisLocal
implements
AnalyzerModule
{
warningNodes
:
AstNodeLegacy
[]
=
[]
warningNodes
:
MemberAccessAstNode
[]
=
[]
name
:
string
=
'This on local calls: '
description
:
string
=
'Invocation of local functions via this'
category
:
ModuleCategory
=
category
.
GAS
algorithm
:
ModuleAlgorithm
=
algorithm
.
EXACT
visit
(
node
:
AstNodeLegacy
):
void
{
visit
(
node
:
MemberAccessAstNode
):
void
{
if
(
isThisLocalCall
(
node
))
this
.
warningNodes
.
push
(
node
)
}
...
...
remix-analyzer/src/types.ts
View file @
04dccc92
...
...
@@ -337,7 +337,7 @@ export interface WhileStatementAstNode {
id
:
number
nodeType
:
'WhileStatement'
|
'DoWhileStatement'
src
:
string
condition
:
object
condition
:
any
body
:
BlockAstNode
}
...
...
@@ -346,7 +346,7 @@ export interface ForStatementAstNode {
nodeType
:
'ForStatement'
src
:
string
initializationExpression
:
VariableDeclarationStatementAstNode
condition
:
object
condition
:
any
loopExpression
:
ExpressionStatementAstNode
body
:
BlockAstNode
}
...
...
@@ -397,7 +397,7 @@ export interface ExpressionStatementAstNode {
id
:
number
nodeType
:
'ExpressionStatement'
src
:
string
expression
:
object
expression
:
any
}
interface
ExpressionAttributes
{
...
...
@@ -441,7 +441,7 @@ export interface UnaryOperationAstNode extends ExpressionAttributes {
src
:
string
prefix
:
boolean
operator
:
string
subExpression
:
object
subExpression
:
any
}
export
interface
BinaryOperationAstNode
extends
ExpressionAttributes
{
...
...
@@ -458,7 +458,7 @@ export interface FunctionCallAstNode extends ExpressionAttributes {
id
:
number
nodeType
:
'FunctionCall'
src
:
string
expression
:
object
expression
:
any
names
:
Array
<
any
>
arguments
:
object
tryCall
:
boolean
...
...
@@ -481,10 +481,8 @@ export interface NewExpressionAstNode extends ExpressionAttributes {
typeName
:
UserDefinedTypeNameAstNode
|
ElementaryTypeNameAstNode
}
export
interface
MemberAccessAstNode
extends
ExpressionAttributes
{
id
:
number
export
interface
MemberAccessAstNode
extends
CommonAstNode
,
ExpressionAttributes
{
nodeType
:
'MemberAccess'
src
:
string
memberName
:
string
expression
:
object
referencedDeclaration
:
number
|
null
...
...
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