Skip to content

Commit 9ee0d2e

Browse files
committed
Rust: Exclude flow summary nodes from DataFlowStep.ql
1 parent f093c49 commit 9ee0d2e

File tree

4 files changed

+318
-4146
lines changed

4 files changed

+318
-4146
lines changed

rust/ql/consistency-queries/PathResolutionConsistency.ql

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,7 @@ private import codeql.rust.elements.Locatable
1010
private import codeql.Locations
1111
import PathResolutionConsistency
1212

13-
class SourceLocatable instanceof Locatable {
14-
string toString() { result = super.toString() }
15-
13+
class SourceLocatable extends Locatable {
1614
Location getLocation() {
1715
if super.getLocation().fromSource()
1816
then result = super.getLocation()

rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll

Lines changed: 92 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -523,97 +523,103 @@ module RustDataFlow implements InputSig<Location> {
523523
exists(c)
524524
}
525525

526+
pragma[nomagic]
527+
additional predicate readContentStep(Node node1, Content c, Node node2) {
528+
exists(TupleStructPatCfgNode pat, int pos |
529+
pat = node1.asPat() and
530+
node2.asPat() = pat.getField(pos) and
531+
c = TTupleFieldContent(pat.getTupleStructPat().getTupleField(pos))
532+
)
533+
or
534+
exists(TuplePatCfgNode pat, int pos |
535+
pos = c.(TuplePositionContent).getPosition() and
536+
node1.asPat() = pat and
537+
node2.asPat() = pat.getField(pos)
538+
)
539+
or
540+
exists(StructPatCfgNode pat, string field |
541+
pat = node1.asPat() and
542+
c = TStructFieldContent(pat.getStructPat().getStructField(field)) and
543+
node2.asPat() = pat.getFieldPat(field)
544+
)
545+
or
546+
c instanceof ReferenceContent and
547+
node1.asPat().(RefPatCfgNode).getPat() = node2.asPat()
548+
or
549+
exists(FieldExprCfgNode access |
550+
node1.asExpr() = access.getContainer() and
551+
node2.asExpr() = access and
552+
access = c.(FieldContent).getAnAccess()
553+
)
554+
or
555+
exists(IndexExprCfgNode arr |
556+
c instanceof ElementContent and
557+
node1.asExpr() = arr.getBase() and
558+
node2.asExpr() = arr
559+
)
560+
or
561+
exists(ForExprCfgNode for |
562+
c instanceof ElementContent and
563+
node1.asExpr() = for.getIterable() and
564+
node2.asPat() = for.getPat()
565+
)
566+
or
567+
exists(SlicePatCfgNode pat |
568+
c instanceof ElementContent and
569+
node1.asPat() = pat and
570+
node2.asPat() = pat.getAPat()
571+
)
572+
or
573+
exists(TryExprCfgNode try |
574+
node1.asExpr() = try.getExpr() and
575+
node2.asExpr() = try and
576+
c.(TupleFieldContent)
577+
.isVariantField([any(OptionEnum o).getSome(), any(ResultEnum r).getOk()], 0)
578+
)
579+
or
580+
exists(PrefixExprCfgNode deref |
581+
c instanceof ReferenceContent and
582+
deref.getOperatorName() = "*" and
583+
node1.asExpr() = deref.getExpr() and
584+
node2.asExpr() = deref
585+
)
586+
or
587+
// Read from function return
588+
exists(DataFlowCall call |
589+
lambdaCall(call, _, node1) and
590+
call = node2.(OutNode).getCall(TNormalReturnKind()) and
591+
c instanceof FunctionCallReturnContent
592+
)
593+
or
594+
exists(AwaitExprCfgNode await |
595+
c instanceof FutureContent and
596+
node1.asExpr() = await.getExpr() and
597+
node2.asExpr() = await
598+
)
599+
or
600+
referenceExprToExpr(node2.(PostUpdateNode).getPreUpdateNode(),
601+
node1.(PostUpdateNode).getPreUpdateNode(), c)
602+
or
603+
// Step from receiver expression to receiver node, in case of an implicit
604+
// dereference.
605+
implicitDerefToReceiver(node1, node2, c)
606+
or
607+
// A read step dual to the store step for implicit borrows.
608+
implicitBorrowToReceiver(node2.(PostUpdateNode).getPreUpdateNode(),
609+
node1.(PostUpdateNode).getPreUpdateNode(), c)
610+
or
611+
VariableCapture::readStep(node1, c, node2)
612+
}
613+
526614
/**
527615
* Holds if data can flow from `node1` to `node2` via a read of `c`. Thus,
528616
* `node1` references an object with a content `c.getAReadContent()` whose
529617
* value ends up in `node2`.
530618
*/
531619
predicate readStep(Node node1, ContentSet cs, Node node2) {
532-
exists(Content c | c = cs.(SingletonContentSet).getContent() |
533-
exists(TupleStructPatCfgNode pat, int pos |
534-
pat = node1.asPat() and
535-
node2.asPat() = pat.getField(pos) and
536-
c = TTupleFieldContent(pat.getTupleStructPat().getTupleField(pos))
537-
)
538-
or
539-
exists(TuplePatCfgNode pat, int pos |
540-
pos = c.(TuplePositionContent).getPosition() and
541-
node1.asPat() = pat and
542-
node2.asPat() = pat.getField(pos)
543-
)
544-
or
545-
exists(StructPatCfgNode pat, string field |
546-
pat = node1.asPat() and
547-
c = TStructFieldContent(pat.getStructPat().getStructField(field)) and
548-
node2.asPat() = pat.getFieldPat(field)
549-
)
550-
or
551-
c instanceof ReferenceContent and
552-
node1.asPat().(RefPatCfgNode).getPat() = node2.asPat()
553-
or
554-
exists(FieldExprCfgNode access |
555-
node1.asExpr() = access.getContainer() and
556-
node2.asExpr() = access and
557-
access = c.(FieldContent).getAnAccess()
558-
)
559-
or
560-
exists(IndexExprCfgNode arr |
561-
c instanceof ElementContent and
562-
node1.asExpr() = arr.getBase() and
563-
node2.asExpr() = arr
564-
)
565-
or
566-
exists(ForExprCfgNode for |
567-
c instanceof ElementContent and
568-
node1.asExpr() = for.getIterable() and
569-
node2.asPat() = for.getPat()
570-
)
571-
or
572-
exists(SlicePatCfgNode pat |
573-
c instanceof ElementContent and
574-
node1.asPat() = pat and
575-
node2.asPat() = pat.getAPat()
576-
)
577-
or
578-
exists(TryExprCfgNode try |
579-
node1.asExpr() = try.getExpr() and
580-
node2.asExpr() = try and
581-
c.(TupleFieldContent)
582-
.isVariantField([any(OptionEnum o).getSome(), any(ResultEnum r).getOk()], 0)
583-
)
584-
or
585-
exists(PrefixExprCfgNode deref |
586-
c instanceof ReferenceContent and
587-
deref.getOperatorName() = "*" and
588-
node1.asExpr() = deref.getExpr() and
589-
node2.asExpr() = deref
590-
)
591-
or
592-
// Read from function return
593-
exists(DataFlowCall call |
594-
lambdaCall(call, _, node1) and
595-
call = node2.(OutNode).getCall(TNormalReturnKind()) and
596-
c instanceof FunctionCallReturnContent
597-
)
598-
or
599-
exists(AwaitExprCfgNode await |
600-
c instanceof FutureContent and
601-
node1.asExpr() = await.getExpr() and
602-
node2.asExpr() = await
603-
)
604-
or
605-
referenceExprToExpr(node2.(PostUpdateNode).getPreUpdateNode(),
606-
node1.(PostUpdateNode).getPreUpdateNode(), c)
607-
or
608-
// Step from receiver expression to receiver node, in case of an implicit
609-
// dereference.
610-
implicitDerefToReceiver(node1, node2, c)
611-
or
612-
// A read step dual to the store step for implicit borrows.
613-
implicitBorrowToReceiver(node2.(PostUpdateNode).getPreUpdateNode(),
614-
node1.(PostUpdateNode).getPreUpdateNode(), c)
615-
or
616-
VariableCapture::readStep(node1, c, node2)
620+
exists(Content c |
621+
c = cs.(SingletonContentSet).getContent() and
622+
readContentStep(node1, c, node2)
617623
)
618624
or
619625
FlowSummaryImpl::Private::Steps::summaryReadStep(node1.(FlowSummaryNode).getSummaryNode(), cs,
@@ -652,7 +658,7 @@ module RustDataFlow implements InputSig<Location> {
652658
}
653659

654660
pragma[nomagic]
655-
private predicate storeContentStep(Node node1, Content c, Node node2) {
661+
additional predicate storeContentStep(Node node1, Content c, Node node2) {
656662
exists(CallExprCfgNode call, int pos |
657663
node1.asExpr() = call.getArgument(pragma[only_bind_into](pos)) and
658664
node2.asExpr() = call and

0 commit comments

Comments
 (0)