Rework IPA injectors for constant accesses

This commit is contained in:
Tom Hvitved
2021-03-17 14:27:21 +01:00
parent eb7610c55f
commit 39aa2c6e53
3 changed files with 53 additions and 72 deletions

View File

@@ -1,5 +1,6 @@
private import codeql_ruby.AST
private import internal.AST
private import internal.Variable
private import internal.TreeSitter
/** An access to a constant. */
@@ -40,6 +41,27 @@ class ConstantAccess extends Expr, TConstantAccess {
override AstNode getAChild(string pred) { pred = "getScopeExpr" and result = this.getScopeExpr() }
}
private class TokenConstantAccess extends ConstantAccess, TTokenConstantAccess {
private Generated::Constant g;
TokenConstantAccess() { this = TTokenConstantAccess(g) }
final override string getName() { result = g.getValue() }
}
private class ScopeResolutionConstantAccess extends ConstantAccess, TScopeResolutionConstantAccess {
private Generated::ScopeResolution g;
private Generated::Constant constant;
ScopeResolutionConstantAccess() { this = TScopeResolutionConstantAccess(g, constant) }
final override string getName() { result = constant.getValue() }
final override Expr getScopeExpr() { toGenerated(result) = g.getScope() }
final override predicate hasGlobalScope() { not exists(g.getScope()) }
}
/**
* A use (read) of a constant.
*
@@ -56,36 +78,17 @@ class ConstantAccess extends Expr, TConstantAccess {
* end
* ```
*/
class ConstantReadAccess extends ConstantAccess, TConstantReadAccess {
override Expr getScopeExpr() { none() }
override predicate hasGlobalScope() { none() }
class ConstantReadAccess extends ConstantAccess {
ConstantReadAccess() {
not this instanceof ConstantWriteAccess
or
// `X` in `X ||= 10` is considered both a read and a write
this = any(AssignOperation a).getLeftOperand()
}
final override string getAPrimaryQlClass() { result = "ConstantReadAccess" }
}
private class TokenConstantReadAccess extends ConstantReadAccess, TTokenConstantReadAccess {
private Generated::Constant g;
TokenConstantReadAccess() { this = TTokenConstantReadAccess(g) }
final override string getName() { result = g.getValue() }
}
private class ScopeResolutionConstantReadAccess extends ConstantReadAccess,
TScopeResolutionConstantReadAccess {
private Generated::ScopeResolution g;
private Generated::Constant constant;
ScopeResolutionConstantReadAccess() { this = TScopeResolutionConstantReadAccess(g, constant) }
final override string getName() { result = constant.getValue() }
final override Expr getScopeExpr() { toGenerated(result) = g.getScope() }
final override predicate hasGlobalScope() { not exists(g.getScope()) }
}
/**
* A definition of a constant.
*
@@ -102,32 +105,14 @@ private class ScopeResolutionConstantReadAccess extends ConstantReadAccess,
* module M::Baz; end # defines constant Baz as a module in module M
* ```
*/
class ConstantWriteAccess extends ConstantAccess, TConstantWriteAccess {
class ConstantWriteAccess extends ConstantAccess {
ConstantWriteAccess() {
explicitAssignmentNode(toGenerated(this), _) or this instanceof TNamespace
}
override string getAPrimaryQlClass() { result = "ConstantWriteAccess" }
}
private class TokenConstantWriteAccess extends ConstantWriteAccess, TTokenConstantWriteAccess {
private Generated::Constant g;
TokenConstantWriteAccess() { this = TTokenConstantWriteAccess(g) }
final override string getName() { result = g.getValue() }
}
private class ScopeResolutionConstantWriteAccess extends ConstantWriteAccess,
TScopeResolutionConstantWriteAccess {
private Generated::ScopeResolution g;
private Generated::Constant constant;
ScopeResolutionConstantWriteAccess() { this = TScopeResolutionConstantWriteAccess(g, constant) }
final override string getName() { result = constant.getValue() }
final override Expr getScopeExpr() { toGenerated(result) = g.getScope() }
final override predicate hasGlobalScope() { not exists(g.getScope()) }
}
/**
* A definition of a constant via assignment. For example, the left-hand
* operand in the following example:
@@ -136,6 +121,6 @@ private class ScopeResolutionConstantWriteAccess extends ConstantWriteAccess,
* MAX_SIZE = 100
* ```
*/
class ConstantAssignment extends ConstantWriteAccess, LhsExpr, TConstantAssignment {
class ConstantAssignment extends ConstantWriteAccess, LhsExpr {
override string getAPrimaryQlClass() { result = "ConstantAssignment" }
}

View File

@@ -16,7 +16,9 @@ class Pattern extends AstNode {
Variable getAVariable() { none() }
}
private class LhsExpr_ = TVariableAccess or TConstantAssignment or TMethodCall or TSimpleParameter;
private class LhsExpr_ =
TVariableAccess or TTokenConstantAccess or TScopeResolutionConstantAccess or TMethodCall or
TSimpleParameter;
/**
* A "left-hand-side" expression. An `LhsExpr` can occur on the left-hand side of

View File

@@ -162,15 +162,16 @@ private module Cached {
TRescueModifierExpr(Generated::RescueModifier g) or
TRetryStmt(Generated::Retry g) or
TReturnStmt(Generated::Return g) or
TScopeResolutionConstantReadAccess(Generated::ScopeResolution g, Generated::Constant constant) {
// A tree-sitter `scope_resolution` node with a `constant` name field is a
// read of that constant in any context where an identifier would be a
// vcall.
TScopeResolutionConstantAccess(Generated::ScopeResolution g, Generated::Constant constant) {
constant = g.getName() and
vcall(g)
} or
TScopeResolutionConstantWriteAccess(Generated::ScopeResolution g, Generated::Constant constant) {
explicitAssignmentNode(g, _) and constant = g.getName()
(
// A tree-sitter `scope_resolution` node with a `constant` name field is a
// read of that constant in any context where an identifier would be a
// vcall.
vcall(g)
or
explicitAssignmentNode(g, _)
)
} or
TScopeResolutionMethodCall(Generated::ScopeResolution g, Generated::Identifier i) {
i = g.getName() and
@@ -196,12 +197,13 @@ private module Cached {
TSymbolArrayLiteral(Generated::SymbolArray g) or
TTernaryIfExpr(Generated::Conditional g) or
TThen(Generated::Then g) or
TTokenConstantReadAccess(Generated::Constant g) {
TTokenConstantAccess(Generated::Constant g) {
// A tree-sitter `constant` token is a read of that constant in any context
// where an identifier would be a vcall.
vcall(g)
or
explicitAssignmentNode(g, _)
} or
TTokenConstantWriteAccess(Generated::Constant g) { explicitAssignmentNode(g, _) } or
TTokenMethodName(MethodName::Token g) { MethodName::range(g) } or
TTokenSuperCall(Generated::Super g) { vcall(g) } or
TToplevel(Generated::Program g) { g.getLocation().getFile().getExtension() != "erb" } or
@@ -323,8 +325,7 @@ private module Cached {
n = TRescueModifierExpr(result) or
n = TRetryStmt(result) or
n = TReturnStmt(result) or
n = TScopeResolutionConstantReadAccess(result, _) or
n = TScopeResolutionConstantWriteAccess(result, _) or
n = TScopeResolutionConstantAccess(result, _) or
n = TScopeResolutionMethodCall(result, _) or
n = TSelf(result) or
n = TSimpleParameter(result) or
@@ -344,8 +345,7 @@ private module Cached {
n = TSymbolArrayLiteral(result) or
n = TTernaryIfExpr(result) or
n = TThen(result) or
n = TTokenConstantReadAccess(result) or
n = TTokenConstantWriteAccess(result) or
n = TTokenConstantAccess(result) or
n = TTokenMethodName(result) or
n = TTokenSuperCall(result) or
n = TToplevel(result) or
@@ -377,13 +377,7 @@ class TMethodCall =
class TSuperCall = TTokenSuperCall or TRegularSuperCall;
class TConstantAccess = TConstantReadAccess or TConstantWriteAccess;
class TConstantReadAccess = TTokenConstantReadAccess or TScopeResolutionConstantReadAccess;
class TConstantWriteAccess = TConstantAssignment or TNamespace;
class TConstantAssignment = TTokenConstantWriteAccess or TScopeResolutionConstantWriteAccess;
class TConstantAccess = TTokenConstantAccess or TScopeResolutionConstantAccess or TNamespace;
class TControlExpr = TConditionalExpr or TCaseExpr or TLoop;