Repository navigation
Expand file tree
/
Copy pathInheritanceAnalysis.ql
More file actions
129 lines (117 loc) · 3.91 KB
/
Copy pathInheritanceAnalysis.ql
File metadata and controls
129 lines (117 loc) · 3.91 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/**
* @name Inheritance chain analysis
* @description Inheritance hierarchies, overridden functions, and virtual functions.
* @id solidity/inheritance-analysis
*/
import codeql.solidity.ast.internal.TreeSitter
import codeql.solidity.callgraph.InheritanceGraph
/**
* Gets the function name from a function definition.
*/
string getFunctionName(Solidity::FunctionDefinition func) {
result = func.getName().(Solidity::AstNode).getValue()
}
/**
* Gets the contract name from a contract declaration.
*/
string getContractName(Solidity::ContractDeclaration contract) {
result = contract.getName().(Solidity::AstNode).getValue()
}
/**
* Gets the interface name.
*/
string getInterfaceName(Solidity::InterfaceDeclaration iface) {
result = iface.getName().(Solidity::AstNode).getValue()
}
/**
* Gets the library name.
*/
string getLibraryName(Solidity::LibraryDeclaration lib) {
result = lib.getName().(Solidity::AstNode).getValue()
}
/**
* Gets visibility of a function.
*/
string getFunctionVisibility(Solidity::FunctionDefinition func) {
exists(Solidity::AstNode vis |
vis.getParent() = func and
vis.toString() = "Visibility" and
result = vis.getAChild().getValue()
)
or
not exists(Solidity::AstNode vis |
vis.getParent() = func and
vis.toString() = "Visibility"
) and
result = "public"
}
/** One row per contract, with its direct bases and inheritance depth. */
query predicate contracts(
string name, boolean isAbstract, string directBases, int depth, Solidity::ContractDeclaration node
) {
name = getContractName(node) and
(
if InheritanceGraph::isAbstractContract(node) then isAbstract = true else isAbstract = false
) and
directBases =
concat(Solidity::ContractDeclaration base |
base = InheritanceGraph::getDirectBase(node)
|
getContractName(base), ","
) and
depth = InheritanceGraph::getInheritanceDepth(node)
}
/** One row per interface, with its direct base interfaces. */
query predicate interfaces(string name, string directBases, Solidity::InterfaceDeclaration node) {
name = getInterfaceName(node) and
directBases =
concat(Solidity::InterfaceDeclaration base |
base = InheritanceGraph::getDirectBaseInterface(node)
|
getInterfaceName(base), ","
)
}
/** One row per library. */
query predicate libraries(string name, Solidity::LibraryDeclaration node) {
name = getLibraryName(node)
}
/** Functions marked `override`, paired with the declaration they override. */
query predicate overriddenFunctions(
string name, string contract, string overridesContract, string visibility,
Solidity::FunctionDefinition node
) {
InheritanceGraph::isOverrideFunction(node) and
exists(Solidity::ContractDeclaration c, Solidity::FunctionDefinition overridden |
node.getParent+() = c and
overridden = InheritanceGraph::getOverriddenFunction(node) and
name = getFunctionName(node) and
contract = getContractName(c) and
overridesContract = getContractName(overridden.getParent+()) and
visibility = getFunctionVisibility(node)
)
}
/** Functions marked `virtual`. */
query predicate virtualFunctions(
string name, string contract, string visibility, Solidity::FunctionDefinition node
) {
InheritanceGraph::isVirtualFunction(node) and
exists(Solidity::ContractDeclaration c |
node.getParent+() = c and
name = getFunctionName(node) and
contract = getContractName(c) and
visibility = getFunctionVisibility(node)
)
}
/** Contracts reaching the same base through more than one intermediate. */
query predicate diamondInheritance(
string contract, string repeatedBase, Solidity::ContractDeclaration node
) {
exists(Solidity::ContractDeclaration base |
count(Solidity::ContractDeclaration intermediate |
InheritanceGraph::inheritsFrom(node, intermediate) and
InheritanceGraph::inheritsFrom(intermediate, base)
) > 1 and
contract = getContractName(node) and
repeatedBase = getContractName(base)
)
}