Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import rust
import codeql.rust.internal.PathResolution
import utils.test.PathResolutionInlineExpectationsTest

query predicate resolveDollarCrate(RelevantPath p, Crate c) {
query predicate resolveDollarCrate(PathExt p, Crate c) {
c = resolvePath(p) and
p.isDollarCrate() and
p.fromSource() and
Expand Down
9 changes: 2 additions & 7 deletions rust/ql/lib/codeql/rust/controlflow/internal/Completion.qll
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
private import codeql.util.Boolean
private import codeql.rust.controlflow.ControlFlowGraph
private import codeql.rust.elements.internal.VariableImpl::Impl as VariableImpl
private import rust

newtype TCompletion =
Expand Down Expand Up @@ -123,13 +124,7 @@ class BooleanCompletion extends ConditionalCompletion, TBooleanCompletion {
*/
private predicate cannotCauseMatchFailure(Pat pat) {
pat instanceof RangePat or
// Identifier patterns that are in fact path patterns can cause failures. For
// instance `None`. Only if an `@ ...` part is present can we be sure that
// it's an actual identifier pattern. As a heuristic, if the identifier starts
// with a lower case letter, then we assume that it's an identifier. This
// works for code that follows the Rust naming convention for enums and
// constants.
pat = any(IdentPat p | p.hasPat() or p.getName().getText().charAt(0).isLowercase()) or
pat = any(IdentPat p | p.hasPat() or VariableImpl::variableDecl(_, p.getName(), _)) or
pat instanceof WildcardPat or
pat instanceof RestPat or
pat instanceof RefPat or
Expand Down
2 changes: 1 addition & 1 deletion rust/ql/lib/codeql/rust/elements/internal/CallImpl.qll
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ module Impl {
}

private predicate callHasTraitQualifier(CallExpr call, Trait qualifier) {
exists(RelevantPath qualifierPath |
exists(PathExt qualifierPath |
callHasQualifier(call, _, qualifierPath) and
qualifier = resolvePath(qualifierPath) and
// When the qualifier is `Self` and resolves to a trait, it's inside a
Expand Down
28 changes: 23 additions & 5 deletions rust/ql/lib/codeql/rust/elements/internal/ConstImpl.qll
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
*/

private import codeql.rust.elements.internal.generated.Const
private import codeql.rust.elements.internal.AstNodeImpl::Impl as AstNodeImpl
private import codeql.rust.elements.internal.IdentPatImpl::Impl as IdentPatImpl
private import codeql.rust.elements.internal.PathExprImpl::Impl as PathExprImpl
private import codeql.rust.internal.PathResolution

Expand Down Expand Up @@ -36,14 +38,30 @@ module Impl {
* }
* ```
*/
class ConstAccess extends PathExprImpl::PathExpr {
abstract class ConstAccess extends AstNodeImpl::AstNode {
/** Gets the constant being accessed. */
abstract Const getConst();

override string getAPrimaryQlClass() { result = "ConstAccess" }
}

private class PathExprConstAccess extends ConstAccess, PathExprImpl::PathExpr {
private Const c;

ConstAccess() { c = resolvePath(this.getPath()) }
PathExprConstAccess() { c = resolvePath(this.getPath()) }

/** Gets the constant being accessed. */
Const getConst() { result = c }
override Const getConst() { result = c }

override string getAPrimaryQlClass() { result = "ConstAccess" }
override string getAPrimaryQlClass() { result = ConstAccess.super.getAPrimaryQlClass() }
}

private class IdentPatConstAccess extends ConstAccess, IdentPatImpl::IdentPat {
private Const c;

IdentPatConstAccess() { c = resolvePath(this) }

override Const getConst() { result = c }

override string getAPrimaryQlClass() { result = ConstAccess.super.getAPrimaryQlClass() }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ module Impl {

override string toStringImpl() { result = this.getName() }

override string getAPrimaryQlClass() { result = "FormatTemplateVariableAccess" }

/** Gets the name of the variable */
string getName() { result = argument.getName() }

Expand Down
7 changes: 7 additions & 0 deletions rust/ql/lib/codeql/rust/elements/internal/PathExprImpl.qll
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* INTERNAL: Do not use.
*/

private import rust
private import codeql.rust.elements.internal.generated.PathExpr

/**
Expand All @@ -25,5 +26,11 @@ module Impl {
override string toStringImpl() { result = this.toAbbreviatedString() }

override string toAbbreviatedString() { result = this.getPath().toStringImpl() }

override string getAPrimaryQlClass() {
if this instanceof VariableAccess
then result = "VariableAccess"
else result = super.getAPrimaryQlClass()
}
}
}
19 changes: 6 additions & 13 deletions rust/ql/lib/codeql/rust/elements/internal/VariableImpl.qll
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
private import rust
private import codeql.rust.controlflow.ControlFlowGraph
private import codeql.rust.internal.PathResolution as PathResolution
private import codeql.rust.elements.internal.generated.ParentChild as ParentChild
private import codeql.rust.elements.internal.AstNodeImpl::Impl as AstNodeImpl
private import codeql.rust.elements.internal.PathImpl::Impl as PathImpl
private import codeql.rust.elements.internal.PathExprBaseImpl::Impl as PathExprBaseImpl
private import codeql.rust.elements.internal.FormatTemplateVariableAccessImpl::Impl as FormatTemplateVariableAccessImpl
private import codeql.util.DenseRank

Expand Down Expand Up @@ -98,7 +99,7 @@ module Impl {
* pattern.
*/
cached
private predicate variableDecl(AstNode definingNode, Name name, string text) {
predicate variableDecl(AstNode definingNode, Name name, string text) {
Cached::ref() and
exists(SelfParam sp |
name = sp.getName() and
Expand All @@ -117,11 +118,7 @@ module Impl {
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
not PathResolution::identPatIsResolvable(pat) 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.getAParam().getPat() = pat) and
Expand Down Expand Up @@ -666,7 +663,7 @@ module Impl {
}

/** A variable access. */
class VariableAccess extends PathExprBaseImpl::PathExprBase {
class VariableAccess extends PathExprBase {
private string name;
private Variable v;

Expand All @@ -677,10 +674,6 @@ module Impl {

/** Holds if this access is a capture. */
predicate isCapture() { this.getEnclosingCfgScope() != v.getEnclosingCfgScope() }

override string toStringImpl() { result = name }

override string getAPrimaryQlClass() { result = "VariableAccess" }
}

/** Holds if `e` occurs in the LHS of an assignment or compound assignment. */
Expand Down Expand Up @@ -722,7 +715,7 @@ module Impl {
}

/** A nested function access. */
class NestedFunctionAccess extends PathExprBaseImpl::PathExprBase {
class NestedFunctionAccess extends PathExprBase {
private Function f;

NestedFunctionAccess() { nestedFunctionAccess(_, f, this) }
Expand Down
4 changes: 1 addition & 3 deletions rust/ql/lib/codeql/rust/internal/CachedStages.qll
Original file line number Diff line number Diff line change
Expand Up @@ -115,13 +115,11 @@ module Stages {
predicate backref() {
1 = 1
or
exists(resolvePath(_))
exists(resolvePathIgnoreVariableShadowing(_))
or
exists(any(ItemNode i).getASuccessor(_, _, _))
or
exists(any(ImplOrTraitItemNode i).getASelfPath())
or
any(TypeParamItemNode i).hasTraitBound()
}
}

Expand Down
5 changes: 4 additions & 1 deletion rust/ql/lib/codeql/rust/internal/Definitions.qll
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,17 @@ private module Cached {
TFormatArgsArgIndex(Expr e) { e = any(FormatArgsArg a).getExpr() } or
TItemNode(ItemNode i)

pragma[nomagic]
private predicate isMacroCallLocation(Location loc) { loc = any(MacroCall m).getLocation() }

/**
* Gets an element, of kind `kind`, that element `use` uses, if any.
*/
cached
Definition definitionOf(Use use, string kind) {
result = use.getDefinition() and
kind = use.getUseType() and
not result.getLocation() = any(MacroCall m).getLocation()
not isMacroCallLocation(result.getLocation())
}
}

Expand Down
Loading