Skip to content

Commit 919555d

Browse files
authored
Merge pull request #9341 from alexrford/ruby/activerecordinstance-public
Ruby: Make `ActiveRecordInstance` public and fix some misidentifications
2 parents 55513e0 + 30f2469 commit 919555d

File tree

3 files changed

+32
-6
lines changed

3 files changed

+32
-6
lines changed

ruby/ql/lib/codeql/ruby/frameworks/ActiveRecord.qll

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,18 @@ private class ActiveRecordModelFinderCall extends ActiveRecordModelInstantiation
275275
exists(MethodCall call, Expr recv |
276276
call = this.asExpr().getExpr() and
277277
recv = getUltimateReceiver(call) and
278-
resolveConstant(recv) = cls.getAQualifiedName() and
278+
(
279+
// The receiver refers to an `ActiveRecordModelClass` by name
280+
resolveConstant(recv) = cls.getAQualifiedName()
281+
or
282+
// The receiver is self, and the call is within a singleton method of
283+
// the `ActiveRecordModelClass`
284+
recv instanceof SelfVariableAccess and
285+
exists(SingletonMethod callScope |
286+
callScope = call.getCfgScope() and
287+
callScope = cls.getAMethod()
288+
)
289+
) and
279290
call.getMethodName() = finderMethodName()
280291
)
281292
}
@@ -293,18 +304,24 @@ private class ActiveRecordModelClassSelfReference extends ActiveRecordModelInsta
293304
m = this.getCfgScope() and
294305
m.getEnclosingModule() = cls and
295306
m = cls.getAMethod()
296-
)
307+
) and
308+
// In a singleton method, `self` refers to the class itself rather than an
309+
// instance of that class
310+
not this.getSelfScope() instanceof SingletonMethod
297311
}
298312

299313
final override ActiveRecordModelClass getClass() { result = cls }
300314
}
301315

302-
// A (locally tracked) active record model object
303-
private class ActiveRecordInstance extends DataFlow::Node {
316+
/**
317+
* An instance of an `ActiveRecord` model object.
318+
*/
319+
class ActiveRecordInstance extends DataFlow::Node {
304320
private ActiveRecordModelInstantiation instantiation;
305321

306322
ActiveRecordInstance() { this = instantiation or instantiation.flowsTo(this) }
307323

324+
/** Gets the `ActiveRecordModelClass` that this is an instance of. */
308325
ActiveRecordModelClass getClass() { result = instantiation.getClass() }
309326
}
310327

ruby/ql/test/library-tests/frameworks/ActiveRecord.expected

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,14 @@ activeRecordModelClasses
22
| ActiveRecordInjection.rb:1:1:3:3 | UserGroup |
33
| ActiveRecordInjection.rb:5:1:17:3 | User |
44
| ActiveRecordInjection.rb:19:1:25:3 | Admin |
5+
activeRecordInstances
6+
| ActiveRecordInjection.rb:10:5:10:68 | call to find |
7+
| ActiveRecordInjection.rb:15:5:15:40 | call to find_by |
8+
| ActiveRecordInjection.rb:79:5:81:7 | if ... |
9+
| ActiveRecordInjection.rb:79:43:80:40 | then ... |
10+
| ActiveRecordInjection.rb:80:7:80:40 | call to find_by |
11+
| ActiveRecordInjection.rb:85:5:85:33 | call to find_by |
12+
| ActiveRecordInjection.rb:88:5:88:34 | call to find |
513
activeRecordSqlExecutionRanges
614
| ActiveRecordInjection.rb:10:33:10:67 | "name='#{...}' and pass='#{...}'" |
715
| ActiveRecordInjection.rb:23:16:23:24 | condition |
@@ -45,9 +53,8 @@ potentiallyUnsafeSqlExecutingMethodCall
4553
| ActiveRecordInjection.rb:75:5:75:29 | call to order |
4654
| ActiveRecordInjection.rb:80:7:80:40 | call to find_by |
4755
activeRecordModelInstantiations
48-
| ActiveRecordInjection.rb:8:3:11:5 | self (authenticate) | ActiveRecordInjection.rb:5:1:17:3 | User |
56+
| ActiveRecordInjection.rb:10:5:10:68 | call to find | ActiveRecordInjection.rb:5:1:17:3 | User |
4957
| ActiveRecordInjection.rb:15:5:15:40 | call to find_by | ActiveRecordInjection.rb:1:1:3:3 | UserGroup |
50-
| ActiveRecordInjection.rb:20:3:24:5 | self (delete_by) | ActiveRecordInjection.rb:19:1:25:3 | Admin |
5158
| ActiveRecordInjection.rb:80:7:80:40 | call to find_by | ActiveRecordInjection.rb:5:1:17:3 | User |
5259
| ActiveRecordInjection.rb:85:5:85:33 | call to find_by | ActiveRecordInjection.rb:5:1:17:3 | User |
5360
| ActiveRecordInjection.rb:88:5:88:34 | call to find | ActiveRecordInjection.rb:5:1:17:3 | User |

ruby/ql/test/library-tests/frameworks/ActiveRecord.ql

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import codeql.ruby.frameworks.ActiveRecord
33

44
query predicate activeRecordModelClasses(ActiveRecordModelClass cls) { any() }
55

6+
query predicate activeRecordInstances(ActiveRecordInstance i) { any() }
7+
68
query predicate activeRecordSqlExecutionRanges(ActiveRecordSqlExecutionRange range) { any() }
79

810
query predicate activeRecordModelClassMethodCalls(ActiveRecordModelClassMethodCall call) { any() }

0 commit comments

Comments
 (0)