Skip to content

Commit 19c413d

Browse files
committed
Ruby: Drop setsKeyValuePair/2 predicate from ActiveRecord::Persistence.ModifyAndSaveCall
1 parent ee43363 commit 19c413d

File tree

1 file changed

+20
-33
lines changed

1 file changed

+20
-33
lines changed

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

Lines changed: 20 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -324,46 +324,33 @@ private module Persistence {
324324
* the database. Examples include `create`, `insert`, and `update`.
325325
*/
326326
abstract private class ModifyAndSaveCall extends DataFlow::CallNode, PersistentWriteAccess::Range {
327-
/**
328-
* Holds if the given key-value pair is set on an object by this call.
329-
*/
330-
abstract predicate setsKeyValuePair(ExprCfgNode key, ExprCfgNode value);
331-
332327
/**
333328
* Gets the ActiveRecord model class to which this call applies.
334329
*/
335330
abstract ActiveRecordModelClass getClass();
336-
337-
final override DataFlow::Node getValue() {
338-
exists(ExprCfgNode keyExpr, ExprCfgNode valueExpr |
339-
this.setsKeyValuePair(keyExpr, valueExpr)
340-
|
341-
result.asExpr() = valueExpr
342-
)
343-
}
344331
}
345332

346333
/**
347334
* Holds if there is a hash literal argument to `call` at `argIndex`
348-
* containing a `key`-`value` pair.
335+
* containing a KV pair with value `value`.
349336
*/
350-
private predicate hashArgument(
351-
DataFlow::CallNode call, int argIndex, ExprCfgNode key, ExprCfgNode value
337+
private predicate hashArgumentWithValue(
338+
DataFlow::CallNode call, int argIndex, DataFlow::ExprNode value
352339
) {
353340
exists(ExprNodes::HashLiteralCfgNode hash, ExprNodes::PairCfgNode pair |
354341
hash = call.getArgument(argIndex).asExpr() and
355342
pair = hash.getAKeyValuePair()
356343
|
357-
key = pair.getKey() and value = pair.getValue()
344+
value.asExpr() = pair.getValue()
358345
)
359346
}
360347

361348
/**
362-
* Holds if `call` has a keyword argument of the form `key: value`.
349+
* Holds if `call` has a keyword argument of with value `value`.
363350
*/
364-
private predicate keywordArgument(DataFlow::CallNode call, ExprCfgNode key, ExprCfgNode value) {
351+
private predicate keywordArgumentWithValue(DataFlow::CallNode call, DataFlow::ExprNode value) {
365352
exists(ExprNodes::PairCfgNode pair | pair = call.getArgument(_).asExpr() |
366-
key = pair.getKey() and value = pair.getValue()
353+
value.asExpr() = pair.getValue()
367354
)
368355
}
369356

@@ -380,10 +367,10 @@ private module Persistence {
380367
]
381368
}
382369

383-
override predicate setsKeyValuePair(ExprCfgNode key, ExprCfgNode value) {
370+
override DataFlow::Node getValue() {
384371
// attrs as hash elements in arg0
385-
hashArgument(this, 0, key, value) or
386-
keywordArgument(this, key, value)
372+
hashArgumentWithValue(this, 0, result) or
373+
keywordArgumentWithValue(this, result)
387374
}
388375

389376
override ActiveRecordModelClass getClass() { result = modelCls }
@@ -398,8 +385,8 @@ private module Persistence {
398385
this.getMethodName() = ["update", "update!", "upsert"]
399386
}
400387

401-
override predicate setsKeyValuePair(ExprCfgNode key, ExprCfgNode value) {
402-
keywordArgument(this, key, value)
388+
override DataFlow::Node getValue() {
389+
keywordArgumentWithValue(this, result)
403390
or
404391
// Case where 2 array args are passed - the first an array of IDs, and the
405392
// second an array of hashes - each hash corresponding to an ID in the
@@ -412,7 +399,7 @@ private module Persistence {
412399
hash = hashesArray.getArgument(_) and
413400
pair = hash.getAKeyValuePair()
414401
|
415-
key = pair.getKey() and value = pair.getValue()
402+
result.asExpr() = pair.getValue()
416403
)
417404
)
418405
}
@@ -431,13 +418,13 @@ private module Persistence {
431418
arr = this.getArgument(0).asExpr()
432419
}
433420

434-
override predicate setsKeyValuePair(ExprCfgNode key, ExprCfgNode value) {
421+
override DataFlow::Node getValue() {
435422
// attrs as hash elements of members of array arg0
436423
exists(ExprNodes::HashLiteralCfgNode hash, ExprNodes::PairCfgNode pair |
437424
hash = arr.getArgument(_) and
438425
pair = hash.getAKeyValuePair()
439426
|
440-
key = pair.getKey() and value = pair.getValue()
427+
result.asExpr() = pair.getValue()
441428
)
442429
}
443430

@@ -451,12 +438,12 @@ private module Persistence {
451438
this.getMethodName() = ["update", "update!", "update_attributes", "update_attributes!"]
452439
}
453440

454-
override predicate setsKeyValuePair(ExprCfgNode key, ExprCfgNode value) {
441+
override DataFlow::Node getValue() {
455442
// attrs as hash elements in arg0
456-
hashArgument(this, 0, key, value)
443+
hashArgumentWithValue(this, 0, result)
457444
or
458445
// keyword arg
459-
keywordArgument(this, key, value)
446+
keywordArgumentWithValue(this, result)
460447
}
461448

462449
override ActiveRecordModelClass getClass() { result = this.getInstance().getClass() }
@@ -466,9 +453,9 @@ private module Persistence {
466453
private class UpdateAttributeCall extends ModifyAndSaveCall, ActiveRecordInstanceMethodCall {
467454
UpdateAttributeCall() { this.getMethodName() = "update_attribute" }
468455

469-
override predicate setsKeyValuePair(ExprCfgNode key, ExprCfgNode value) {
456+
override DataFlow::Node getValue() {
470457
// e.g. `foo.update_attribute(key, value)`
471-
key = this.getArgument(0).asExpr() and value = this.getArgument(1).asExpr()
458+
result = this.getArgument(1)
472459
}
473460

474461
override ActiveRecordModelClass getClass() { result = this.getInstance().getClass() }

0 commit comments

Comments
 (0)