Skip to content

Commit 8451286

Browse files
committed
API graphs: Remove MkModule
1 parent 78b64da commit 8451286

2 files changed

Lines changed: 43 additions & 65 deletions

File tree

ql/src/codeql_ruby/ApiGraphs.qll

Lines changed: 21 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -198,13 +198,9 @@ module API {
198198
}
199199

200200
/** A node corresponding to the use of an API component. */
201-
class Use extends Node, Impl::TUse {
201+
class Use extends Node, Impl::MkUse {
202202
override string toString() {
203-
exists(string type |
204-
this = Impl::MkUse(_) and type = "Use "
205-
or
206-
this = Impl::MkModule(_) and type = "ModuleUse "
207-
|
203+
exists(string type | this = Impl::MkUse(_) and type = "Use " |
208204
result = type + getPath()
209205
or
210206
not exists(this.getPath()) and result = type + "with no path"
@@ -216,27 +212,13 @@ module API {
216212
Root root() { any() }
217213

218214
/**
219-
* Gets a node corresponding to an import of module `m`.
215+
* Gets a node corresponding to an import of top-level module `m`.
220216
*
221217
* Note: You should only use this predicate for top level modules or classes. If you want nodes corresponding to a nested module or class,
222218
* you should use `.getMember` on the parent module/class. For example, for nodes corresponding to the class `Gem::Version`,
223219
* use `moduleImport("Gem").getMember("Version")`.
224220
*/
225-
Node moduleImport(string m) {
226-
result = Impl::MkModule(m) and not m.matches("%::%")
227-
or
228-
result = Impl::MkUse(unresolvedModuleReference(m))
229-
}
230-
231-
DataFlow::Node unresolvedModuleReference(string m) {
232-
exists(ConstantReadAccess iexpr, DataFlow::Node node |
233-
not exists(resolveScopeExpr(iexpr)) and
234-
not exists(iexpr.getScopeExpr()) and
235-
m = iexpr.getName() and
236-
result = node and
237-
node.asExpr().getExpr() = iexpr
238-
)
239-
}
221+
Node moduleImport(string m) { result = root().getMember(m) }
240222

241223
/**
242224
* Provides the actual implementation of API graphs, cached for performance.
@@ -266,23 +248,30 @@ module API {
266248
newtype TApiNode =
267249
/** The root of the API graph. */
268250
MkRoot() or
269-
/** An abstract representative for imports of the module called `name`. */
270-
MkModule(string name) { exists(TResolved(name)) } or
271251
/** A use of an API member at the node `nd`. */
272-
MkUse(DataFlow::Node nd) {
273-
use(_, _, nd)
274-
or
275-
nd = unresolvedModuleReference(_)
276-
}
277-
278-
class TUse = MkModule or MkUse;
252+
MkUse(DataFlow::Node nd) { use(_, _, nd) }
279253

280254
/**
281255
* Holds if `ref` is a use of a node that should have an incoming edge from `base` labeled
282256
* `lbl` in the API graph.
283257
*/
284258
cached
285259
predicate use(TApiNode base, string lbl, DataFlow::Node ref) {
260+
base = MkRoot() and
261+
exists(string name, ExprNodes::ConstantAccessCfgNode access, ConstantReadAccess read |
262+
access = ref.asExpr() and
263+
lbl = Label::member(read.getName()) and
264+
read = access.getExpr()
265+
|
266+
TResolved(name) = resolveScopeExpr(read) and
267+
not name.matches("%::%")
268+
or
269+
name = read.getName() and
270+
not exists(resolveScopeExpr(read)) and
271+
not exists(read.getScopeExpr()) and
272+
not exists(read.getValue())
273+
)
274+
or
286275
exists(DataFlow::LocalSourceNode src, DataFlow::LocalSourceNode pred |
287276
// First, we find a predecessor of the node `ref` that we want to determine. The predecessor
288277
// is any node that is a type-tracked use of a data flow node (`src`), which is itself a
@@ -331,16 +320,7 @@ module API {
331320
* Holds if `ref` is a use of node `nd`.
332321
*/
333322
cached
334-
predicate use(TApiNode nd, DataFlow::Node ref) {
335-
exists(string name, ExprNodes::ConstantAccessCfgNode access, ConstantReadAccess read |
336-
access = ref.asExpr() and
337-
nd = MkModule(name) and
338-
read = access.getExpr() and
339-
TResolved(name) = resolveScopeExpr(read)
340-
)
341-
or
342-
nd = MkUse(ref)
343-
}
323+
predicate use(TApiNode nd, DataFlow::Node ref) { nd = MkUse(ref) }
344324

345325
/**
346326
* Gets a data-flow node to which `src`, which is a use of an API-graph node, flows.
@@ -370,14 +350,6 @@ module API {
370350
*/
371351
cached
372352
predicate edge(TApiNode pred, string lbl, TApiNode succ) {
373-
/* There's an edge from the root node for each imported module. */
374-
exists(string m |
375-
pred = MkRoot() and
376-
lbl = Label::mod(m)
377-
|
378-
succ = moduleImport(m)
379-
)
380-
or
381353
/* Every node that is a use of an API component is itself added to the API graph. */
382354
exists(DataFlow::LocalSourceNode ref |
383355
use(pred, lbl, ref) and
@@ -397,11 +369,6 @@ module API {
397369
}
398370

399371
private module Label {
400-
/** Gets the edge label for the module `m`. */
401-
bindingset[m]
402-
bindingset[result]
403-
string mod(string m) { result = "moduleImport(\"" + m + "\")" }
404-
405372
/** Gets the `member` edge label for member `m`. */
406373
bindingset[m]
407374
bindingset[result]
Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,24 @@
1-
MyModule #$ use=moduleImport("MyModule")
2-
print MyModule.foo #$ use=moduleImport("MyModule").getReturn("foo")
3-
Kernel.print(e) #$ use=moduleImport("Kernel").getReturn("print")
4-
Object::Kernel #$ use=moduleImport("Kernel")
5-
Object::Kernel.print(e) #$ use=moduleImport("Kernel").getReturn("print")
1+
MyModule #$ use=getMember("MyModule")
2+
print MyModule.foo #$ use=getMember("MyModule").getReturn("foo")
3+
Kernel.print(e) #$ use=getMember("Kernel").getReturn("print")
4+
Object::Kernel #$ use=getMember("Kernel")
5+
Object::Kernel.print(e) #$ use=getMember("Kernel").getReturn("print")
66
begin
7-
print MyModule.bar #$ use=moduleImport("MyModule").getReturn("bar")
8-
raise AttributeError #$ use=moduleImport("AttributeError")
9-
rescue AttributeError => e #$ use=moduleImport("AttributeError")
10-
Kernel.print(e) #$ use=moduleImport("Kernel").getReturn("print")
7+
print MyModule.bar #$ use=getMember("MyModule").getReturn("bar")
8+
raise AttributeError #$ use=getMember("AttributeError")
9+
rescue AttributeError => e #$ use=getMember("AttributeError")
10+
Kernel.print(e) #$ use=getMember("Kernel").getReturn("print")
1111
end
12-
Unknown.new.run #$ use=moduleImport("Unknown").instance.getReturn("run")
13-
Foo::Bar::Baz #$ use=moduleImport("Foo").getMember("Bar").getMember("Baz")
12+
Unknown.new.run #$ use=getMember("Unknown").instance.getReturn("run")
13+
Foo::Bar::Baz #$ use=getMember("Foo").getMember("Bar").getMember("Baz")
14+
15+
Const = [1, 2, 3]
16+
Const.each do |c|
17+
puts c
18+
end
19+
20+
foo = Foo #$ use=getMember("Foo")
21+
foo::Bar::Baz #$ use=getMember("Foo").getMember("Bar").getMember("Baz")
22+
23+
FooAlias = Foo #$ use=getMember("Foo")
24+
FooAlias::Bar::Baz #$ use=getMember("Foo").getMember("Bar").getMember("Baz")

0 commit comments

Comments
 (0)