@@ -14,6 +14,7 @@ private import codeql.rust.controlflow.ControlFlowGraph
1414private import codeql.rust.controlflow.CfgNodes
1515private import codeql.rust.dataflow.Ssa
1616private import codeql.rust.dataflow.FlowSummary
17+ private import codeql.rust.internal.TypeInference as TypeInference
1718private import Node as Node
1819private import DataFlowImpl
1920private import FlowSummaryImpl as FlowSummaryImpl
@@ -226,35 +227,53 @@ final class ExprArgumentNode extends ArgumentNode, ExprNode {
226227 private Call call_;
227228 private RustDataFlow::ArgumentPosition pos_;
228229
229- ExprArgumentNode() { isArgumentForCall(n, call_, pos_) }
230+ ExprArgumentNode() {
231+ isArgumentForCall(n, call_, pos_) and
232+ not TypeInference::implicitDeref(n) and
233+ not TypeInference::implicitBorrow(n)
234+ }
230235
231236 override predicate isArgumentOf(DataFlowCall call, RustDataFlow::ArgumentPosition pos) {
232237 call.asCall() = call_ and pos = pos_
233238 }
234239}
235240
236241/**
237- * The receiver of a method call _after_ any implicit borrow or dereferencing
238- * has taken place .
242+ * A node that represents the value of an expression _after_ implicit dereferencing
243+ * or borrowing .
239244 */
240- final class ReceiverNode extends ArgumentNode, TReceiverNode {
241- private Call n;
245+ class DerefBorrowNode extends Node, TDerefBorrowNode {
246+ AstNode n;
247+ boolean isBorrow;
242248
243- ReceiverNode () { this = TReceiverNode(n , false) }
249+ DerefBorrowNode () { this = TDerefBorrowNode(n, isBorrow , false) }
244250
245- Expr getReceiver () { result = n.getReceiver() }
251+ AstNode getNode () { result = n }
246252
247- MethodCallExpr getMethodCall () { result = n }
253+ predicate isBorrow () { isBorrow = true }
248254
249- override predicate isArgumentOf(DataFlowCall call, RustDataFlow::ArgumentPosition pos) {
250- call.asCall() = n and pos = TSelfParameterPosition()
255+ override CfgScope getCfgScope() { result = n.getEnclosingCfgScope() }
256+
257+ override Location getLocation() { result = n.getLocation() }
258+
259+ override string toString() {
260+ if isBorrow = true then result = n + " [borrowed]" else result = n + " [dereferenced]"
251261 }
262+ }
252263
253- override CfgScope getCfgScope() { result = n.getEnclosingCfgScope() }
264+ /**
265+ * A node that represents the value of an argument of a call _after_ implicit
266+ * dereferencing or borrowing.
267+ */
268+ final class DerefBorrowArgNode extends DerefBorrowNode, ArgumentNode {
269+ private DataFlowCall call_;
270+ private RustDataFlow::ArgumentPosition pos_;
254271
255- override Location getLocation () { result = this.getReceiver().getLocation( ) }
272+ DerefBorrowArgNode () { isArgumentForCall(n, call_.asCall(), pos_ ) }
256273
257- override string toString() { result = "receiver for " + this.getReceiver() }
274+ override predicate isArgumentOf(DataFlowCall call, RustDataFlow::ArgumentPosition pos) {
275+ call = call_ and pos = pos_
276+ }
258277}
259278
260279final class SummaryArgumentNode extends FlowSummaryNode, ArgumentNode {
@@ -329,15 +348,46 @@ abstract class OutNode extends Node {
329348}
330349
331350final private class ExprOutNode extends ExprNode, OutNode {
332- ExprOutNode() { this.asExpr() instanceof Call }
351+ ExprOutNode() {
352+ exists(Call call |
353+ call = this.asExpr() and
354+ not call instanceof DerefExpr // Handled by `DerefOutNode`
355+ )
356+ }
333357
334- /** Gets the underlying call CFG node that includes this out node. */
358+ /** Gets the underlying call node that includes this out node. */
335359 override DataFlowCall getCall(ReturnKind kind) {
336360 result.asCall() = n and
337361 kind = TNormalReturnKind()
338362 }
339363}
340364
365+ /**
366+ * A node that represents the value of a `*` expression _before_ implicit
367+ * dereferencing:
368+ *
369+ * `*v` equivalent to `*Deref::deref(&v)`, and this node represents the
370+ * `Deref::deref(&v)` part.
371+ */
372+ class DerefOutNode extends OutNode, TDerefOutNode {
373+ DerefExpr de;
374+
375+ DerefOutNode() { this = TDerefOutNode(de, false) }
376+
377+ DerefExpr getDerefExpr() { result = de }
378+
379+ override CfgScope getCfgScope() { result = de.getEnclosingCfgScope() }
380+
381+ override DataFlowCall getCall(ReturnKind kind) {
382+ result.asCall() = de and
383+ kind = TNormalReturnKind()
384+ }
385+
386+ override Location getLocation() { result = de.getLocation() }
387+
388+ override string toString() { result = de.toString() + " [pre-dereferenced]" }
389+ }
390+
341391final class SummaryOutNode extends FlowSummaryNode, OutNode {
342392 private DataFlowCall call;
343393 private ReturnKind kind_;
@@ -402,16 +452,29 @@ final class ExprPostUpdateNode extends PostUpdateNode, TExprPostUpdateNode {
402452 override Location getLocation() { result = e.getLocation() }
403453}
404454
405- final class ReceiverPostUpdateNode extends PostUpdateNode, TReceiverNode {
406- private Call call;
455+ final class DerefBorrowPostUpdateNode extends PostUpdateNode, TDerefBorrowNode {
456+ private Expr arg;
457+ private boolean isBorrow;
407458
408- ReceiverPostUpdateNode () { this = TReceiverNode(call , true) }
459+ DerefBorrowPostUpdateNode () { this = TDerefBorrowNode(arg, isBorrow , true) }
409460
410- override Node getPreUpdateNode() { result = TReceiverNode(call , false) }
461+ override DerefBorrowNode getPreUpdateNode() { result = TDerefBorrowNode(arg, isBorrow , false) }
411462
412- override CfgScope getCfgScope() { result = call .getEnclosingCfgScope() }
463+ override CfgScope getCfgScope() { result = arg .getEnclosingCfgScope() }
413464
414- override Location getLocation() { result = call.getReceiver().getLocation() }
465+ override Location getLocation() { result = arg.getLocation() }
466+ }
467+
468+ class DerefOutPostUpdateNode extends PostUpdateNode, TDerefOutNode {
469+ DerefExpr de;
470+
471+ DerefOutPostUpdateNode() { this = TDerefOutNode(de, true) }
472+
473+ override DerefOutNode getPreUpdateNode() { result = TDerefOutNode(de, false) }
474+
475+ override CfgScope getCfgScope() { result = de.getEnclosingCfgScope() }
476+
477+ override Location getLocation() { result = de.getLocation() }
415478}
416479
417480final class SummaryPostUpdateNode extends FlowSummaryNode, PostUpdateNode {
@@ -467,19 +530,19 @@ newtype TNode =
467530 any(IndexExpr i).getBase(), //
468531 any(FieldExpr access).getContainer(), //
469532 any(TryExpr try).getExpr(), //
470- any(PrefixExpr pe | pe.getOperatorName() = "*").getExpr(), //
471533 any(AwaitExpr a).getExpr(), //
472- any(MethodCallExpr mc).getReceiver(), //
473534 getPostUpdateReverseStep(any(PostUpdateNode n).getPreUpdateNode().asExpr(), _)
474535 ]
475536 )
476537 } or
477- TReceiverNode(Call call, Boolean isPost) {
478- call.hasEnclosingCfgScope() and
479- call.receiverImplicitlyBorrowed() and
480- // TODO: Handle index expressions as calls in data flow.
481- not call instanceof IndexExpr
538+ TDerefBorrowNode(AstNode n, boolean borrow, Boolean isPost) {
539+ TypeInference::implicitDeref(n) and
540+ borrow = false
541+ or
542+ TypeInference::implicitBorrow(n) and
543+ borrow = true
482544 } or
545+ TDerefOutNode(DerefExpr de, Boolean isPost) or
483546 TSsaNode(SsaImpl::DataFlowIntegration::SsaNode node) or
484547 TFlowSummaryNode(FlowSummaryImpl::Private::SummaryNode sn) {
485548 forall(AstNode n | n = sn.getSinkElement() or n = sn.getSourceElement() |
0 commit comments