FazBrowse GitHub Viewer
|
Trending
|
URL:
|
Home
Tools:
[Download Repo ZIP]
[View Raw Code]
[Original HTTPS Page]
codeql/python/ql/lib/semmle/python/Scope.qll at codeql-cli/v2.27.1 · github/codeql · GitHub
github
codeql
Repository navigation
Code
Issues
1k
(1k)
Pull requests
474
(474)
Discussions
Actions
Projects
Security and quality
Insights
Expand file tree
Breadcrumbs
codeql
/
python
/
ql
/
lib
/
semmle
/
python
/
Scope.qll
Copy path
More file actions
More file actions
Latest commit
History
History
History
172 lines (148 loc) · 5.9 KB
Breadcrumbs
codeql
/
python
/
ql
/
lib
/
semmle
/
python
/
Scope.qll
Copy path
File metadata and controls
172 lines (148 loc) · 5.9 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
overlay
[
local
]
module
;
import
python
private
import
semmle.python.dataflow.new.internal.ImportResolution
/**
* Gets a name exported by module `m`, that is the names that will be added to a namespace by 'from this-module import *'.
*
* This aims to be the same as m.getAnExport(), but without using the points-to machinery.
*/
overlay
[
global
]
private
string
getAModuleExport
(
Module
m
)
{
py_exports
(
m
,
result
)
or
ImportResolution
::
module_export
(
m
,
result
,
_
)
}
/**
* A Scope. A scope is the lexical extent over which all identifiers with the same name refer to the same variable.
* Modules, Classes and Functions are all Scopes. There are no other scopes.
* The scopes for expressions that create new scopes, lambdas and comprehensions, are handled by creating an anonymous Function.
*/
class
Scope
extends
Scope_
{
Module
getEnclosingModule
(
)
{
result
=
this
.
getEnclosingScope
(
)
.
getEnclosingModule
(
)
}
/**
* Gets the scope enclosing this scope (modules have no enclosing scope).
*
* This method will be deprecated in the next release. Please use `getEnclosingScope()` instead.
* The reason for this is to avoid confusion around use of `x.getScope+()` where `x` might be an
* `AstNode` or a `Variable`. Forcing the users to write `x.getScope().getEnclosingScope*()` ensures that
* the apparent semantics and the actual semantics coincide.
*/
Scope
getScope
(
)
{
none
(
)
}
/** Gets the scope enclosing this scope (modules have no enclosing scope) */
Scope
getEnclosingScope
(
)
{
none
(
)
}
/** Gets the statements forming the body of this scope */
StmtList
getBody
(
)
{
none
(
)
}
/** Gets the nth statement of this scope */
Stmt
getStmt
(
int
n
)
{
none
(
)
}
/** Gets a top-level statement in this scope */
Stmt
getAStmt
(
)
{
none
(
)
}
Location
getLocation
(
)
{
none
(
)
}
/** Gets the name of this scope */
string
getName
(
)
{
py_strs
(
result
,
this
,
0
)
}
/** Gets the docstring for this scope */
StringLiteral
getDocString
(
)
{
result
=
this
.
getStmt
(
0
)
.
(
ExprStmt
)
.
getValue
(
)
}
/** Gets the entry point into this Scope's control flow graph */
ControlFlowNode
getEntryNode
(
)
{
py_scope_flow
(
result
,
this
,
-
1
)
}
/** Gets the non-explicit exit from this Scope's control flow graph */
ControlFlowNode
getFallthroughNode
(
)
{
py_scope_flow
(
result
,
this
,
0
)
}
/** Gets the exit of this scope following from a return statement */
ControlFlowNode
getReturnNode
(
)
{
py_scope_flow
(
result
,
this
,
2
)
}
/** Gets an exit from this Scope's control flow graph */
ControlFlowNode
getAnExitNode
(
)
{
exists
(
int
i
|
py_scope_flow
(
result
,
this
,
i
)
and
i
>=
0
)
}
/**
* Gets an exit from this Scope's control flow graph,
* that does not result from an exception
*/
ControlFlowNode
getANormalExit
(
)
{
result
=
this
.
getFallthroughNode
(
)
or
result
=
this
.
getReturnNode
(
)
}
/** Holds if this a top-level (non-nested) class or function */
predicate
isTopLevel
(
)
{
this
.
getEnclosingModule
(
)
=
this
.
getEnclosingScope
(
)
}
/** Holds if this scope is deemed to be public */
overlay
[
global
]
predicate
isPublic
(
)
{
/* Not inside a function */
not
this
.
getEnclosingScope
(
)
instanceof
Function
and
/* Not implicitly private */
this
.
getName
(
)
.
charAt
(
0
)
!=
"_"
and
(
this
instanceof
Module
or
exists
(
Module
m
|
m
=
this
.
getEnclosingScope
(
)
and
m
.
isPublic
(
)
|
// The module is implicitly exported
not
exists
(
getAModuleExport
(
m
)
)
or
// The module is explicitly exported
getAModuleExport
(
m
)
=
this
.
getName
(
)
)
or
exists
(
Class
c
|
c
=
this
.
getEnclosingScope
(
)
|
this
instanceof
Function
and
c
.
isPublic
(
)
)
)
}
predicate
contains
(
AstNode
a
)
{
this
.
getBody
(
)
.
contains
(
a
)
or
exists
(
Scope
inner
|
inner
.
getEnclosingScope
(
)
=
this
|
inner
.
contains
(
a
)
)
}
/**
* Holds if this scope can be expected to execute before `other`.
* Modules precede functions and methods in those modules
* `__init__` precedes other methods. `__enter__` precedes `__exit__`.
* NOTE that this is context-insensitive, so a module "precedes" a function
* in that module, even if that function is called from the module scope.
*/
predicate
precedes
(
Scope
other
)
{
exists
(
Function
f
,
string
name
|
f
=
other
and
name
=
f
.
getName
(
)
|
if
f
.
isMethod
(
)
then
// The __init__ method is preceded by the enclosing module
this
=
f
.
getEnclosingModule
(
)
and
name
=
"__init__"
or
exists
(
Class
c
,
string
pred_name
|
// __init__ -> __enter__ -> __exit__
// __init__ -> other-methods
f
.
getScope
(
)
=
c
and
(
pred_name
=
"__init__"
and
not
name
=
"__init__"
and
not
name
=
"__exit__"
or
pred_name
=
"__enter__"
and
name
=
"__exit__"
)
|
this
.
getScope
(
)
=
c
and
pred_name
=
this
.
(
Function
)
.
getName
(
)
or
not
exists
(
Function
pre_func
|
pre_func
.
getName
(
)
=
pred_name
and
pre_func
.
getScope
(
)
=
c
)
and
this
=
other
.
getEnclosingModule
(
)
)
else
// Normal functions are preceded by the enclosing module
this
=
f
.
getEnclosingModule
(
)
)
}
/**
* Gets the evaluation scope for code in this (lexical) scope.
* This is usually the scope itself, but may be an enclosing scope.
* Notably, for list comprehensions in Python 2.
*/
Scope
getEvaluatingScope
(
)
{
result
=
this
}
/**
* Holds if this scope is in the source archive,
* that is it is part of the code specified, not library code
*/
predicate
inSource
(
)
{
exists
(
this
.
getEnclosingModule
(
)
.
getFile
(
)
.
getRelativePath
(
)
)
}
Stmt
getLastStatement
(
)
{
result
=
this
.
getBody
(
)
.
getLastItem
(
)
.
getLastStatement
(
)
}
/** Whether this contains `inner` syntactically and `inner` has the same scope as `this` */
predicate
containsInScope
(
AstNode
inner
)
{
this
.
getBody
(
)
.
contains
(
inner
)
and
this
=
inner
.
getScope
(
)
}
}
Back
|
FazBrowse Home
|
New Git URL