Skip to content

Commit f21948d

Browse files
committed
Ruby: Speed up private method modelling
1 parent 6223b16 commit f21948d

File tree

1 file changed

+30
-27
lines changed

1 file changed

+30
-27
lines changed

ruby/ql/lib/codeql/ruby/ast/Method.qll

Lines changed: 30 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -48,30 +48,37 @@ private class MethodModifier extends MethodCall {
4848
/** Gets the name of the method that this call applies to. */
4949
Expr getMethodArgument() { result = this.getArgument(0) }
5050

51-
/** Gets the method that this call applies to. */
52-
MethodBase getMethod() {
53-
result = this.getMethodArgument()
54-
or
55-
exists(Namespace n |
56-
n.getAStmt() = this and
57-
n.getAStmt() = result and
58-
result.getName() = this.getMethodArgument().(StringlikeLiteral).getValueText()
59-
)
51+
/** Holds if this call modifies a method with name `name` in namespace `n`. */
52+
predicate modifiesMethod(Namespace n, string name) {
53+
this = n.getAStmt() and
54+
[
55+
this.getMethodArgument().(StringlikeLiteral).getValueText(),
56+
this.getMethodArgument().(MethodBase).getName()
57+
] = name
6058
}
6159
}
6260

6361
/** A call to `private` or `private_class_method`. */
6462
private class Private extends MethodModifier {
65-
Private() { this.getMethodName() = "private" }
66-
67-
/**
68-
* Holds if this call happens at position `i` inside `c`,
69-
* and the call has no arguments.
70-
*/
71-
pragma[noinline]
72-
predicate hasNoArg(Namespace c, int i) {
73-
this = c.getStmt(i) and
74-
not exists(this.getMethod())
63+
private Namespace namespace;
64+
private int position;
65+
66+
Private() { this.getMethodName() = "private" and namespace.getStmt(position) = this }
67+
68+
override predicate modifiesMethod(Namespace n, string name) {
69+
n = namespace and
70+
(
71+
// def foo
72+
// ...
73+
// private :foo
74+
super.modifiesMethod(n, name)
75+
or
76+
// private
77+
// ...
78+
// def foo
79+
not exists(this.getMethodArgument()) and
80+
exists(MethodBase m, int i | n.getStmt(i) = m and m.getName() = name and i > position)
81+
)
7582
}
7683
}
7784

@@ -132,13 +139,7 @@ class Method extends MethodBase, TMethod {
132139
* ```
133140
*/
134141
override predicate isPrivate() {
135-
this = any(Private p).getMethod()
136-
or
137-
exists(Namespace c, Private p, int i, int j |
138-
p.hasNoArg(c, i) and
139-
this = c.getStmt(j) and
140-
j > i
141-
)
142+
any(Private p).modifiesMethod(this.getEnclosingModule(), this.getName())
142143
or
143144
// Top-level methods are private members of the Object class
144145
this.getEnclosingModule() instanceof Toplevel
@@ -203,7 +204,9 @@ class SingletonMethod extends MethodBase, TSingletonMethod {
203204
* end
204205
* ```
205206
*/
206-
override predicate isPrivate() { this = any(PrivateClassMethod p).getMethod() }
207+
override predicate isPrivate() {
208+
any(PrivateClassMethod p).modifiesMethod(this.getEnclosingModule(), this.getName())
209+
}
207210
}
208211

209212
/**

0 commit comments

Comments
 (0)