mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
Merge pull request #19246 from hvitved/rust/cache-tweaks
This commit is contained in:
@@ -846,9 +846,11 @@ module RustDataFlow implements InputSig<Location> {
|
||||
|
||||
/** Provides logic related to captured variables. */
|
||||
module VariableCapture {
|
||||
private import codeql.rust.internal.CachedStages
|
||||
private import codeql.dataflow.VariableCapture as SharedVariableCapture
|
||||
|
||||
private predicate closureFlowStep(ExprCfgNode e1, ExprCfgNode e2) {
|
||||
Stages::DataFlowStage::ref() and
|
||||
e1 = getALastEvalNode(e2)
|
||||
or
|
||||
exists(Ssa::Definition def |
|
||||
|
||||
@@ -33,6 +33,7 @@ module Impl {
|
||||
* Gets the nearest enclosing parent of this node, which is also an `AstNode`,
|
||||
* if any.
|
||||
*/
|
||||
cached
|
||||
AstNode getParentNode() { result = getParentOfAstStep*(getImmediateParent(this)) }
|
||||
|
||||
/** Gets the immediately enclosing callable of this node, if any. */
|
||||
|
||||
@@ -68,36 +68,36 @@ module Impl {
|
||||
* where `definingNode` is the entire `Either::Left(x) | Either::Right(x)`
|
||||
* pattern.
|
||||
*/
|
||||
cached
|
||||
private predicate variableDecl(AstNode definingNode, Name name, string text) {
|
||||
(
|
||||
exists(SelfParam sp |
|
||||
name = sp.getName() and
|
||||
definingNode = name and
|
||||
text = name.getText() and
|
||||
// exclude self parameters from functions without a body as these are
|
||||
// trait method declarations without implementations
|
||||
not exists(Function f | not f.hasBody() and f.getParamList().getSelfParam() = sp)
|
||||
)
|
||||
or
|
||||
exists(IdentPat pat |
|
||||
name = pat.getName() and
|
||||
(
|
||||
definingNode = getOutermostEnclosingOrPat(pat)
|
||||
or
|
||||
not exists(getOutermostEnclosingOrPat(pat)) and definingNode = name
|
||||
) and
|
||||
text = name.getText() and
|
||||
// exclude for now anything starting with an uppercase character, which may be a reference to
|
||||
// an enum constant (e.g. `None`). This excludes static and constant variables (UPPERCASE),
|
||||
// which we don't appear to recognize yet anyway. This also assumes programmers follow the
|
||||
// naming guidelines, which they generally do, but they're not enforced.
|
||||
not text.charAt(0).isUppercase() and
|
||||
// exclude parameters from functions without a body as these are trait method declarations
|
||||
// without implementations
|
||||
not exists(Function f | not f.hasBody() and f.getParamList().getAParam().getPat() = pat) and
|
||||
// exclude parameters from function pointer types (e.g. `x` in `fn(x: i32) -> i32`)
|
||||
not exists(FnPtrTypeRepr fp | fp.getParamList().getParam(_).getPat() = pat)
|
||||
)
|
||||
Cached::ref() and
|
||||
exists(SelfParam sp |
|
||||
name = sp.getName() and
|
||||
definingNode = name and
|
||||
text = name.getText() and
|
||||
// exclude self parameters from functions without a body as these are
|
||||
// trait method declarations without implementations
|
||||
not exists(Function f | not f.hasBody() and f.getParamList().getSelfParam() = sp)
|
||||
)
|
||||
or
|
||||
exists(IdentPat pat |
|
||||
name = pat.getName() and
|
||||
(
|
||||
definingNode = getOutermostEnclosingOrPat(pat)
|
||||
or
|
||||
not exists(getOutermostEnclosingOrPat(pat)) and definingNode = name
|
||||
) and
|
||||
text = name.getText() and
|
||||
// exclude for now anything starting with an uppercase character, which may be a reference to
|
||||
// an enum constant (e.g. `None`). This excludes static and constant variables (UPPERCASE),
|
||||
// which we don't appear to recognize yet anyway. This also assumes programmers follow the
|
||||
// naming guidelines, which they generally do, but they're not enforced.
|
||||
not text.charAt(0).isUppercase() and
|
||||
// exclude parameters from functions without a body as these are trait method declarations
|
||||
// without implementations
|
||||
not exists(Function f | not f.hasBody() and f.getParamList().getAParam().getPat() = pat) and
|
||||
// exclude parameters from function pointer types (e.g. `x` in `fn(x: i32) -> i32`)
|
||||
not exists(FnPtrTypeRepr fp | fp.getParamList().getParam(_).getPat() = pat)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -156,8 +156,12 @@ module Impl {
|
||||
predicate isCaptured() { this.getAnAccess().isCapture() }
|
||||
|
||||
/** Gets the parameter that introduces this variable, if any. */
|
||||
cached
|
||||
ParamBase getParameter() {
|
||||
result = this.getSelfParam() or result.(Param).getPat() = getAVariablePatAncestor(this)
|
||||
Cached::ref() and
|
||||
result = this.getSelfParam()
|
||||
or
|
||||
result.(Param).getPat() = getAVariablePatAncestor(this)
|
||||
}
|
||||
|
||||
/** Hold is this variable is mutable. */
|
||||
@@ -614,12 +618,18 @@ module Impl {
|
||||
|
||||
/** A variable write. */
|
||||
class VariableWriteAccess extends VariableAccess {
|
||||
VariableWriteAccess() { assignmentExprDescendant(this) }
|
||||
cached
|
||||
VariableWriteAccess() {
|
||||
Cached::ref() and
|
||||
assignmentExprDescendant(this)
|
||||
}
|
||||
}
|
||||
|
||||
/** A variable read. */
|
||||
class VariableReadAccess extends VariableAccess {
|
||||
cached
|
||||
VariableReadAccess() {
|
||||
Cached::ref() and
|
||||
not this instanceof VariableWriteAccess and
|
||||
not this = any(RefExpr re).getExpr() and
|
||||
not this = any(CompoundAssignmentExpr cae).getLhs()
|
||||
@@ -638,6 +648,22 @@ module Impl {
|
||||
|
||||
cached
|
||||
private module Cached {
|
||||
cached
|
||||
predicate ref() { 1 = 1 }
|
||||
|
||||
cached
|
||||
predicate backref() {
|
||||
1 = 1
|
||||
or
|
||||
variableDecl(_, _, _)
|
||||
or
|
||||
exists(VariableReadAccess a)
|
||||
or
|
||||
exists(VariableWriteAccess a)
|
||||
or
|
||||
exists(any(Variable v).getParameter())
|
||||
}
|
||||
|
||||
cached
|
||||
newtype TVariable =
|
||||
MkVariable(AstNode definingNode, string name) { variableDecl(definingNode, _, name) }
|
||||
|
||||
@@ -123,6 +123,10 @@ module Stages {
|
||||
exists(any(ItemNode i).getASuccessor(_))
|
||||
or
|
||||
exists(any(ItemNode i).getASuccessorRec(_))
|
||||
or
|
||||
exists(any(ImplOrTraitItemNode i).getASelfPath())
|
||||
or
|
||||
any(TypeParamItemNode i).hasTraitBound()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -384,7 +384,9 @@ abstract class ImplOrTraitItemNode extends ItemNode {
|
||||
}
|
||||
|
||||
/** Gets a `Self` path that refers to this item. */
|
||||
cached
|
||||
Path getASelfPath() {
|
||||
Stages::PathResolutionStage::ref() and
|
||||
isUnqualifiedSelfPath(result) and
|
||||
this = unqualifiedPathLookup(result, _)
|
||||
}
|
||||
@@ -578,7 +580,7 @@ private class BlockExprItemNode extends ItemNode instanceof BlockExpr {
|
||||
override TypeParam getTypeParam(int i) { none() }
|
||||
}
|
||||
|
||||
private class TypeParamItemNode extends ItemNode instanceof TypeParam {
|
||||
class TypeParamItemNode extends ItemNode instanceof TypeParam {
|
||||
pragma[nomagic]
|
||||
Path getABoundPath() {
|
||||
result = super.getTypeBoundList().getABound().getTypeRepr().(PathTypeRepr).getPath()
|
||||
@@ -598,8 +600,9 @@ private class TypeParamItemNode extends ItemNode instanceof TypeParam {
|
||||
* impl<T> Foo<T> where T: Trait { ... } // has trait bound
|
||||
* ```
|
||||
*/
|
||||
pragma[nomagic]
|
||||
cached
|
||||
predicate hasTraitBound() {
|
||||
Stages::PathResolutionStage::ref() and
|
||||
exists(this.getABoundPath())
|
||||
or
|
||||
exists(ItemNode declaringItem, WherePred wp |
|
||||
|
||||
Reference in New Issue
Block a user