Skip to content

Commit 8419daa

Browse files
committed
Ruby: Add subclassing support to API Graphs
Given the code class A; end class B < A; end class C < A; end You can find uses of B and C with the expression API::getTopLevelMember("A").getASubclass()
1 parent 8e40899 commit 8419daa

File tree

2 files changed

+19
-4
lines changed

2 files changed

+19
-4
lines changed

ruby/ql/lib/codeql/ruby/ApiGraphs.qll

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -254,10 +254,9 @@ module API {
254254
*/
255255
pragma[nomagic]
256256
private predicate useRoot(string lbl, DataFlow::Node ref) {
257-
exists(string name, ExprNodes::ConstantAccessCfgNode access, ConstantReadAccess read |
258-
access = ref.asExpr() and
259-
lbl = Label::member(read.getName()) and
260-
read = access.getExpr()
257+
exists(string name, ConstantReadAccess read |
258+
read = ref.asExpr().getExpr() and
259+
lbl = Label::member(read.getName())
261260
|
262261
name = resolveTopLevel(read)
263262
or
@@ -389,6 +388,17 @@ module API {
389388
useStep(lbl, node, ref)
390389
)
391390
)
391+
or
392+
// `pred` is a use of class A
393+
// `succ` is a use of class B
394+
// there exists a class declaration B < A
395+
exists(ClassDeclaration c, DataFlow::Node a, DataFlow::Node b |
396+
use(pred, a) and
397+
use(succ, b) and
398+
resolveConstant(b.asExpr().getExpr()) = resolveConstantWriteAccess(c) and
399+
c.getSuperclassExpr() = a.asExpr().getExpr() and
400+
lbl = Label::subclass()
401+
)
392402
}
393403

394404
/**

ruby/ql/lib/codeql/ruby/ast/internal/Module.qll

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,12 +233,17 @@ private module ResolveImpl {
233233

234234
pragma[nomagic]
235235
private string resolveConstantReadAccessNonRec(ConstantReadAccess c, int priority) {
236+
// ::B
236237
c.hasGlobalScope() and result = c.getName() and priority = 0
237238
or
239+
// A::B
238240
exists(string name, string s | result = isDefinedConstantNonRec(s, name) |
239241
s = resolveConstantReadAccessScopeNonRec(c, priority, name)
240242
)
241243
or
244+
// module A
245+
// B
246+
// end
242247
exists(string name |
243248
exists(Namespace n, string qname |
244249
n = constantReadAccessEnclosingNameSpace(c, priority, name) and

0 commit comments

Comments
 (0)