mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
Override isCapturedAccess for self variables
Many `self` reads are synthesised from method calls with an implicit
`self` receiver. Synthesised nodes have no `toGenerated` result, which
the default definition of `isCapturedAccess` uses to determine if a
variable's scope matches the access's scope.
Hence we override the definition to properly identify accesses like the
call `puts` (below) as captured reads of a `self` variable defined in a
parent scope.
In other words, `puts x` is short for `self.puts x` and the `self`
refers to its value in the scope of the module `Foo`.
```ruby
module Foo
MY_PROC = -> (x) { puts x }
end
```
We also have to update the SSA `SelfDefinition` to exclude captured
`self` variables.
This commit is contained in:
@@ -147,7 +147,7 @@ class LocalVariableAccess extends VariableAccess instanceof LocalVariableAccessI
|
||||
* the access to `x` in the first `puts x` is a captured access, while
|
||||
* the access to `x` in the second `puts x` is not.
|
||||
*/
|
||||
final predicate isCapturedAccess() { isCapturedAccess(this) }
|
||||
predicate isCapturedAccess() { isCapturedAccess(this) }
|
||||
}
|
||||
|
||||
/** An access to a local variable where the value is updated. */
|
||||
@@ -195,4 +195,10 @@ class SelfVariableAccess extends LocalVariableAccess instanceof SelfVariableAcce
|
||||
}
|
||||
|
||||
/** An access to the `self` variable where the value is read. */
|
||||
class SelfVariableReadAccess extends SelfVariableAccess, VariableReadAccess { }
|
||||
class SelfVariableReadAccess extends SelfVariableAccess, VariableReadAccess {
|
||||
// We override the definition in `LocalVariableAccess` because it gives the
|
||||
// wrong result for synthesised `self` variables.
|
||||
override predicate isCapturedAccess() {
|
||||
this.getVariable().getDeclaringScope() != this.getCfgScope()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -221,12 +221,17 @@ module Ssa {
|
||||
}
|
||||
|
||||
/**
|
||||
* An SSA definition that corresponds to the value of `self` upon method entry.
|
||||
* An SSA definition that corresponds to the value of `self` upon entry to a method, class or module.
|
||||
*/
|
||||
class SelfDefinition extends Definition, SsaImplCommon::WriteDefinition {
|
||||
private SelfVariable v;
|
||||
|
||||
SelfDefinition() { this.definesAt(v, _, _) }
|
||||
SelfDefinition() {
|
||||
exists(BasicBlock bb, int i |
|
||||
this.definesAt(v, bb, i) and
|
||||
not SsaImpl::capturedEntryWrite(bb, i, v)
|
||||
)
|
||||
}
|
||||
|
||||
final override string toString() { result = "self (" + v.getDeclaringScope() + ")" }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user