mirror of
https://github.com/github/codeql.git
synced 2026-02-12 05:01:06 +01:00
Merge pull request #21161 from hvitved/rust/restrict-implicit-deref-borrow-nodes
Rust: Restrict `ImplicitDerefBorrowNode` to nodes with enclosing CFG scope
This commit is contained in:
@@ -62,8 +62,8 @@ final class DataFlowCall extends TDataFlowCall {
|
||||
/** Gets the underlying call, if any. */
|
||||
Call asCall() { this = TCall(result) }
|
||||
|
||||
predicate isImplicitDerefCall(AstNode n, DerefChain derefChain, int i, Function target) {
|
||||
this = TImplicitDerefCall(n, derefChain, i, target)
|
||||
predicate isImplicitDerefCall(Expr e, DerefChain derefChain, int i, Function target) {
|
||||
this = TImplicitDerefCall(e, derefChain, i, target)
|
||||
}
|
||||
|
||||
predicate isSummaryCall(
|
||||
@@ -75,8 +75,7 @@ final class DataFlowCall extends TDataFlowCall {
|
||||
DataFlowCallable getEnclosingCallable() {
|
||||
result.asCfgScope() = this.asCall().getEnclosingCfgScope()
|
||||
or
|
||||
result.asCfgScope() =
|
||||
any(AstNode n | this.isImplicitDerefCall(n, _, _, _)).getEnclosingCfgScope()
|
||||
result.asCfgScope() = any(Expr e | this.isImplicitDerefCall(e, _, _, _)).getEnclosingCfgScope()
|
||||
or
|
||||
this.isSummaryCall(result.asSummarizedCallable(), _)
|
||||
}
|
||||
@@ -84,9 +83,9 @@ final class DataFlowCall extends TDataFlowCall {
|
||||
string toString() {
|
||||
result = this.asCall().toString()
|
||||
or
|
||||
exists(AstNode n, DerefChain derefChain, int i |
|
||||
this.isImplicitDerefCall(n, derefChain, i, _) and
|
||||
result = "[implicit deref call " + i + " in " + derefChain.toString() + "] " + n
|
||||
exists(Expr e, DerefChain derefChain, int i |
|
||||
this.isImplicitDerefCall(e, derefChain, i, _) and
|
||||
result = "[implicit deref call " + i + " in " + derefChain.toString() + "] " + e
|
||||
)
|
||||
or
|
||||
exists(
|
||||
@@ -100,7 +99,7 @@ final class DataFlowCall extends TDataFlowCall {
|
||||
Location getLocation() {
|
||||
result = this.asCall().getLocation()
|
||||
or
|
||||
result = any(AstNode n | this.isImplicitDerefCall(n, _, _, _)).getLocation()
|
||||
result = any(Expr e | this.isImplicitDerefCall(e, _, _, _)).getLocation()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1095,9 +1094,10 @@ private module Cached {
|
||||
Stages::DataFlowStage::ref() and
|
||||
call.hasEnclosingCfgScope()
|
||||
} or
|
||||
TImplicitDerefCall(AstNode n, DerefChain derefChain, int i, Function target) {
|
||||
TypeInference::implicitDerefChainBorrow(n, derefChain, _) and
|
||||
target = derefChain.getElement(i).getDerefFunction()
|
||||
TImplicitDerefCall(Expr e, DerefChain derefChain, int i, Function target) {
|
||||
TypeInference::implicitDerefChainBorrow(e, derefChain, _) and
|
||||
target = derefChain.getElement(i).getDerefFunction() and
|
||||
e.hasEnclosingCfgScope()
|
||||
} or
|
||||
TSummaryCall(
|
||||
FlowSummaryImpl::Public::SummarizedCallable c, FlowSummaryImpl::Private::SummaryNode receiver
|
||||
|
||||
@@ -277,11 +277,11 @@ abstract class ImplicitDerefBorrowNode extends Node {
|
||||
*/
|
||||
abstract Node getBorrowInputNode();
|
||||
|
||||
abstract AstNode getUnderlyingAstNode();
|
||||
abstract Expr getExpr();
|
||||
|
||||
override CfgScope getCfgScope() { result = this.getUnderlyingAstNode().getEnclosingCfgScope() }
|
||||
override CfgScope getCfgScope() { result = this.getExpr().getEnclosingCfgScope() }
|
||||
|
||||
override Location getLocation() { result = this.getUnderlyingAstNode().getLocation() }
|
||||
override Location getLocation() { result = this.getExpr().getLocation() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -292,24 +292,24 @@ abstract class ImplicitDerefBorrowNode extends Node {
|
||||
* is in.
|
||||
*/
|
||||
class ImplicitDerefNode extends ImplicitDerefBorrowNode, TImplicitDerefNode {
|
||||
AstNode n;
|
||||
Expr e;
|
||||
DerefChain derefChain;
|
||||
ImplicitDerefNodeState state;
|
||||
int i;
|
||||
|
||||
ImplicitDerefNode() { this = TImplicitDerefNode(n, derefChain, state, i, false) }
|
||||
ImplicitDerefNode() { this = TImplicitDerefNode(e, derefChain, state, i, false) }
|
||||
|
||||
override AstNode getUnderlyingAstNode() { result = n }
|
||||
override Expr getExpr() { result = e }
|
||||
|
||||
private predicate isBuiltinDeref() { derefChain.isBuiltinDeref(i) }
|
||||
|
||||
private Node getInputNode() {
|
||||
// The first implicit deref has the underlying AST node as input
|
||||
i = 0 and
|
||||
result.(AstNodeNode).getAstNode() = n
|
||||
result.asExpr() = e
|
||||
or
|
||||
// Subsequent implicit derefs have the previous implicit deref as input
|
||||
result = TImplicitDerefNode(n, derefChain, TImplicitDerefNodeAfterDerefState(), i - 1, false)
|
||||
result = TImplicitDerefNode(e, derefChain, TImplicitDerefNodeAfterDerefState(), i - 1, false)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -334,19 +334,19 @@ class ImplicitDerefNode extends ImplicitDerefBorrowNode, TImplicitDerefNode {
|
||||
*/
|
||||
Node getDerefOutputNode() {
|
||||
state = TImplicitDerefNodeBeforeDerefState() and
|
||||
result = TImplicitDerefNode(n, derefChain, TImplicitDerefNodeAfterDerefState(), i, false)
|
||||
result = TImplicitDerefNode(e, derefChain, TImplicitDerefNodeAfterDerefState(), i, false)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this node represents the last implicit deref in the underlying chain.
|
||||
*/
|
||||
predicate isLast(AstNode node) {
|
||||
node = n and
|
||||
predicate isLast(Expr expr) {
|
||||
expr = e and
|
||||
state = TImplicitDerefNodeAfterDerefState() and
|
||||
i = derefChain.length() - 1
|
||||
}
|
||||
|
||||
override string toString() { result = n + " [implicit deref " + i + " in state " + state + "]" }
|
||||
override string toString() { result = e + " [implicit deref " + i + " in state " + state + "]" }
|
||||
}
|
||||
|
||||
final class ImplicitDerefArgNode extends ImplicitDerefNode, ArgumentNode {
|
||||
@@ -356,12 +356,12 @@ final class ImplicitDerefArgNode extends ImplicitDerefNode, ArgumentNode {
|
||||
ImplicitDerefArgNode() {
|
||||
not derefChain.isBuiltinDeref(i) and
|
||||
state = TImplicitDerefNodeAfterBorrowState() and
|
||||
call_.isImplicitDerefCall(n, derefChain, i, _) and
|
||||
call_.isImplicitDerefCall(e, derefChain, i, _) and
|
||||
pos_.isSelf()
|
||||
or
|
||||
this.isLast(_) and
|
||||
TypeInference::implicitDerefChainBorrow(n, derefChain, false) and
|
||||
isArgumentForCall(n, call_.asCall(), pos_)
|
||||
TypeInference::implicitDerefChainBorrow(e, derefChain, false) and
|
||||
isArgumentForCall(e, call_.asCall(), pos_)
|
||||
}
|
||||
|
||||
override predicate isArgumentOf(DataFlowCall call, RustDataFlow::ArgumentPosition pos) {
|
||||
@@ -378,7 +378,7 @@ private class ImplicitDerefOutNode extends ImplicitDerefNode, OutNode {
|
||||
}
|
||||
|
||||
override DataFlowCall getCall(ReturnKind kind) {
|
||||
result.isImplicitDerefCall(n, derefChain, i, _) and
|
||||
result.isImplicitDerefCall(e, derefChain, i, _) and
|
||||
kind = TNormalReturnKind()
|
||||
}
|
||||
}
|
||||
@@ -387,30 +387,30 @@ private class ImplicitDerefOutNode extends ImplicitDerefNode, OutNode {
|
||||
* A node that represents the value of an expression _after_ implicit borrowing.
|
||||
*/
|
||||
class ImplicitBorrowNode extends ImplicitDerefBorrowNode, TImplicitBorrowNode {
|
||||
AstNode n;
|
||||
Expr e;
|
||||
DerefChain derefChain;
|
||||
|
||||
ImplicitBorrowNode() { this = TImplicitBorrowNode(n, derefChain, false) }
|
||||
ImplicitBorrowNode() { this = TImplicitBorrowNode(e, derefChain, false) }
|
||||
|
||||
override AstNode getUnderlyingAstNode() { result = n }
|
||||
override Expr getExpr() { result = e }
|
||||
|
||||
override Node getBorrowInputNode() {
|
||||
result =
|
||||
TImplicitDerefNode(n, derefChain, TImplicitDerefNodeAfterDerefState(),
|
||||
TImplicitDerefNode(e, derefChain, TImplicitDerefNodeAfterDerefState(),
|
||||
derefChain.length() - 1, false)
|
||||
or
|
||||
derefChain.isEmpty() and
|
||||
result.(AstNodeNode).getAstNode() = n
|
||||
result.(AstNodeNode).getAstNode() = e
|
||||
}
|
||||
|
||||
override string toString() { result = n + " [implicit borrow]" }
|
||||
override string toString() { result = e + " [implicit borrow]" }
|
||||
}
|
||||
|
||||
final class ImplicitBorrowArgNode extends ImplicitBorrowNode, ArgumentNode {
|
||||
private DataFlowCall call_;
|
||||
private RustDataFlow::ArgumentPosition pos_;
|
||||
|
||||
ImplicitBorrowArgNode() { isArgumentForCall(n, call_.asCall(), pos_) }
|
||||
ImplicitBorrowArgNode() { isArgumentForCall(e, call_.asCall(), pos_) }
|
||||
|
||||
override predicate isArgumentOf(DataFlowCall call, RustDataFlow::ArgumentPosition pos) {
|
||||
call = call_ and pos = pos_
|
||||
@@ -736,13 +736,15 @@ newtype TNode =
|
||||
)
|
||||
} or
|
||||
TImplicitDerefNode(
|
||||
AstNode n, DerefChain derefChain, ImplicitDerefNodeState state, int i, Boolean isPost
|
||||
Expr e, DerefChain derefChain, ImplicitDerefNodeState state, int i, Boolean isPost
|
||||
) {
|
||||
TypeInference::implicitDerefChainBorrow(n, derefChain, _) and
|
||||
e.hasEnclosingCfgScope() and
|
||||
TypeInference::implicitDerefChainBorrow(e, derefChain, _) and
|
||||
i in [0 .. derefChain.length() - 1]
|
||||
} or
|
||||
TImplicitBorrowNode(AstNode n, DerefChain derefChain, Boolean isPost) {
|
||||
TypeInference::implicitDerefChainBorrow(n, derefChain, true)
|
||||
TImplicitBorrowNode(Expr e, DerefChain derefChain, Boolean isPost) {
|
||||
e.hasEnclosingCfgScope() and
|
||||
TypeInference::implicitDerefChainBorrow(e, derefChain, true)
|
||||
} or
|
||||
TDerefOutNode(DerefExpr de, Boolean isPost) or
|
||||
TIndexOutNode(IndexExpr ie, Boolean isPost) or
|
||||
|
||||
Reference in New Issue
Block a user