Skip to content

Commit ee43363

Browse files
committed
Ruby: replace OrmWriteAccess with PersistentWriteAccess concept
1 parent 98dbe3a commit ee43363

File tree

10 files changed

+46
-57
lines changed

10 files changed

+46
-57
lines changed

ruby/ql/lib/codeql/ruby/Concepts.qll

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -626,33 +626,28 @@ module OrmInstantiation {
626626
}
627627

628628
/**
629-
* A data-flow node that may represent a write to the database in an ORM system.
629+
* A data flow node that writes persistent data.
630630
*
631631
* Extend this class to refine existing API models. If you want to model new APIs,
632-
* extend `OrmWriteAccess::Range` instead.
632+
* extend `PersistentWriteAccess::Range` instead.
633633
*/
634-
class OrmWriteAccess extends DataFlow::Node instanceof OrmWriteAccess::Range {
635-
/**
636-
* Gets the name of a field that is assigned to `value` by this write.
637-
*/
638-
string getFieldNameAssignedTo(DataFlow::Node value) {
639-
result = super.getFieldNameAssignedTo(value)
640-
}
634+
class PersistentWriteAccess extends DataFlow::Node instanceof PersistentWriteAccess::Range {
635+
DataFlow::Node getValue() { result = super.getValue() }
641636
}
642637

643-
/** Provides a class for modeling new ORM write access APIs. */
644-
module OrmWriteAccess {
638+
/** Provides a class for modeling new persistent write access APIs. */
639+
module PersistentWriteAccess {
645640
/**
646-
* A data-flow node that may represent a write to the database in an ORM system.
641+
* A data flow node that writes persistent data.
647642
*
648643
* Extend this class to model new APIs. If you want to refine existing API models,
649-
* extend `OrmWriteAccess` instead.
644+
* extend `PersistentWriteAccess` instead.
650645
*/
651646
abstract class Range extends DataFlow::Node {
652647
/**
653-
* Gets the name of a field that is assigned to `value` by this write.
648+
* Gets the data flow node corresponding to the written value.
654649
*/
655-
abstract string getFieldNameAssignedTo(DataFlow::Node value);
650+
abstract DataFlow::Node getValue();
656651
}
657652
}
658653

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

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,7 @@ private module Persistence {
323323
* A call to a method that may modify or create a model object and write it to
324324
* the database. Examples include `create`, `insert`, and `update`.
325325
*/
326-
abstract private class ModifyAndSaveCall extends DataFlow::CallNode, OrmWriteAccess::Range {
326+
abstract private class ModifyAndSaveCall extends DataFlow::CallNode, PersistentWriteAccess::Range {
327327
/**
328328
* Holds if the given key-value pair is set on an object by this call.
329329
*/
@@ -334,14 +334,11 @@ private module Persistence {
334334
*/
335335
abstract ActiveRecordModelClass getClass();
336336

337-
final override string getFieldNameAssignedTo(DataFlow::Node value) {
337+
final override DataFlow::Node getValue() {
338338
exists(ExprCfgNode keyExpr, ExprCfgNode valueExpr |
339339
this.setsKeyValuePair(keyExpr, valueExpr)
340340
|
341-
keyExpr.getConstantValue().isStringOrSymbol(result) and
342-
// avoid vacuous matches where the key is not a string or not a symbol
343-
not result = "" and
344-
value.asExpr() = valueExpr
341+
result.asExpr() = valueExpr
345342
)
346343
}
347344
}
@@ -480,24 +477,21 @@ private module Persistence {
480477
/**
481478
* An assignment like `user.name = "foo"`. Though this does not write to the
482479
* database without a subsequent call to persist the object, it is considered
483-
* as an `OrmWriteAccess` to avoid missing cases where the path to a
480+
* as an `PersistentWriteAccess` to avoid missing cases where the path to a
484481
* subsequent write is not clear.
485482
*/
486-
private class AssignAttribute extends DataFlow::Node, OrmWriteAccess::Range {
487-
private DataFlow::CallNode setter;
483+
private class AssignAttribute extends DataFlow::Node, PersistentWriteAccess::Range {
488484
private ExprNodes::AssignExprCfgNode assignNode;
489485

490486
AssignAttribute() {
491-
assignNode = this.asExpr() and
492-
setter.getArgument(0) = this and
493-
setter instanceof ActiveRecordInstanceMethodCall and
494-
setter.asExpr().getExpr() instanceof SetterMethodCall
487+
exists(DataFlow::CallNode setter |
488+
assignNode = this.asExpr() and
489+
setter.getArgument(0) = this and
490+
setter instanceof ActiveRecordInstanceMethodCall and
491+
setter.asExpr().getExpr() instanceof SetterMethodCall
492+
)
495493
}
496494

497-
override string getFieldNameAssignedTo(DataFlow::Node value) {
498-
result + "=" = setter.getMethodName() and
499-
// match RHS
500-
assignNode.getRhs() = value.asExpr()
501-
}
495+
override DataFlow::Node getValue() { assignNode.getRhs() = result.asExpr() }
502496
}
503497
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
| app/controllers/users_controller.rb:5:7:5:44 | call to create! | app/controllers/users_controller.rb:5:26:5:29 | "U1" |
2+
| app/controllers/users_controller.rb:5:7:5:44 | call to create! | app/controllers/users_controller.rb:5:37:5:43 | call to get_uid |
3+
| app/controllers/users_controller.rb:6:7:6:29 | call to create | app/controllers/users_controller.rb:6:25:6:28 | "U2" |
4+
| app/controllers/users_controller.rb:7:7:7:31 | call to insert | app/controllers/users_controller.rb:7:26:7:29 | "U3" |
5+
| app/controllers/users_controller.rb:10:7:10:32 | call to update | app/controllers/users_controller.rb:10:28:10:31 | "U4" |
6+
| app/controllers/users_controller.rb:11:7:11:73 | call to update! | app/controllers/users_controller.rb:11:39:11:42 | "U5" |
7+
| app/controllers/users_controller.rb:11:7:11:73 | call to update! | app/controllers/users_controller.rb:11:53:11:56 | "U6" |
8+
| app/controllers/users_controller.rb:11:7:11:73 | call to update! | app/controllers/users_controller.rb:11:67:11:70 | "U7" |
9+
| app/controllers/users_controller.rb:14:7:14:66 | call to insert_all | app/controllers/users_controller.rb:14:31:14:34 | "U8" |
10+
| app/controllers/users_controller.rb:14:7:14:66 | call to insert_all | app/controllers/users_controller.rb:14:45:14:48 | "U9" |
11+
| app/controllers/users_controller.rb:14:7:14:66 | call to insert_all | app/controllers/users_controller.rb:14:59:14:63 | "U10" |
12+
| app/controllers/users_controller.rb:19:7:19:30 | call to update | app/controllers/users_controller.rb:19:25:19:29 | "U11" |
13+
| app/controllers/users_controller.rb:20:7:20:57 | call to update_attributes | app/controllers/users_controller.rb:20:37:20:41 | "U12" |
14+
| app/controllers/users_controller.rb:20:7:20:57 | call to update_attributes | app/controllers/users_controller.rb:20:49:20:55 | call to get_uid |
15+
| app/controllers/users_controller.rb:23:7:23:42 | call to update_attribute | app/controllers/users_controller.rb:23:37:23:41 | "U13" |
16+
| app/controllers/users_controller.rb:26:7:26:15 | ... = ... | app/controllers/users_controller.rb:26:19:26:23 | "U14" |
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import codeql.ruby.DataFlow
2+
import codeql.ruby.Concepts
3+
4+
query predicate persistentWriteAccesses(PersistentWriteAccess acc, DataFlow::Node value) {
5+
value = acc.getValue()
6+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
class User < ActiveRecord::Base
2+
end

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

Lines changed: 0 additions & 16 deletions
This file was deleted.

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

Lines changed: 0 additions & 6 deletions
This file was deleted.

ruby/ql/test/library-tests/frameworks/app/models/user.rb

Lines changed: 0 additions & 2 deletions
This file was deleted.

0 commit comments

Comments
 (0)