Skip to content

Commit b17a93e

Browse files
authored
Merge pull request github#7316 from hvitved/ruby/is-private-join
Ruby: Tweak `Method::isPrivate` join-orders
2 parents 4d797d6 + 728e3ab commit b17a93e

File tree

1 file changed

+35
-8
lines changed

1 file changed

+35
-8
lines changed

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

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,29 @@ class MethodBase extends Callable, BodyStmt, Scope, TMethodBase {
4040
/** A call to `private`. */
4141
private class Private extends MethodCall {
4242
Private() { this.getMethodName() = "private" }
43+
44+
/** Gets the method that this `private` call applies to, if any */
45+
Expr getMethod() { result = this.getArgument(0) }
46+
47+
/**
48+
* Holds if this `private` call happens inside `c`, and refers to a
49+
* method named `name`.
50+
*/
51+
pragma[noinline]
52+
predicate isRef(ClassDeclaration c, string name) {
53+
this = c.getAStmt() and
54+
name = this.getMethod().(SymbolLiteral).getValueText()
55+
}
56+
57+
/**
58+
* Holds if this `private` call happens at position `i` inside `c`,
59+
* and the call has no arguments.
60+
*/
61+
pragma[noinline]
62+
predicate hasNoArg(ClassDeclaration c, int i) {
63+
this = c.getStmt(i) and
64+
not exists(this.getMethod())
65+
}
4366
}
4467

4568
/** A normal method. */
@@ -67,6 +90,12 @@ class Method extends MethodBase, TMethod {
6790
*/
6891
final predicate isSetter() { g.getName() instanceof Ruby::Setter }
6992

93+
pragma[noinline]
94+
private predicate isDeclaredIn(ClassDeclaration c, string name) {
95+
this = c.getAStmt() and
96+
name = this.getName()
97+
}
98+
7099
/**
71100
* Holds if this method is private. All methods with the name prefix
72101
* `private` are private below:
@@ -94,17 +123,15 @@ class Method extends MethodBase, TMethod {
94123
* ```
95124
*/
96125
predicate isPrivate() {
97-
this = any(Private p).getArgument(0)
126+
this = any(Private p).getMethod()
98127
or
99-
exists(ClassDeclaration c, Private p, SymbolLiteral s |
100-
p.getArgument(0) = s and
101-
p = c.getAStmt() and
102-
this.getName() = s.getValueText() and
103-
this = c.getAStmt()
128+
exists(ClassDeclaration c, Private p, string name |
129+
this.isDeclaredIn(c, name) and
130+
p.isRef(c, name)
104131
)
105132
or
106-
exists(ClassDeclaration c, int i, int j |
107-
c.getStmt(i).(Private).getNumberOfArguments() = 0 and
133+
exists(ClassDeclaration c, Private p, int i, int j |
134+
p.hasNoArg(c, i) and
108135
this = c.getStmt(j) and
109136
j > i
110137
)

0 commit comments

Comments
 (0)