From 647bed9e2fe5cd3ccdb55cb72cdf47084df16d22 Mon Sep 17 00:00:00 2001 From: Simon Friis Vindum Date: Wed, 26 Nov 2025 13:09:41 +0100 Subject: [PATCH] Rust: Add extensible predicate to exclude fields and block fieldless enum types --- .../dataflow/internal/TaintTrackingImpl.qll | 32 +++++++++++++++---- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/rust/ql/lib/codeql/rust/dataflow/internal/TaintTrackingImpl.qll b/rust/ql/lib/codeql/rust/dataflow/internal/TaintTrackingImpl.qll index e4321fd8786..52bec3f0414 100644 --- a/rust/ql/lib/codeql/rust/dataflow/internal/TaintTrackingImpl.qll +++ b/rust/ql/lib/codeql/rust/dataflow/internal/TaintTrackingImpl.qll @@ -11,6 +11,20 @@ private import codeql.rust.internal.TypeInference as TypeInference private import codeql.rust.internal.Type as Type private import codeql.rust.frameworks.stdlib.Builtins as Builtins +/** + * Holds if the field `field` should, by default, be excluded from taint steps. + * The syntax used to denote the field is the same as for `Field` in + * models-as-data. + */ +extensible predicate excludeFieldTaintStep(string field); + +private predicate excludedTaintStepContent(Content c) { + exists(string arg | excludeFieldTaintStep(arg) | + FlowSummaryImpl::encodeContentStructField(c, arg) or + FlowSummaryImpl::encodeContentTupleField(c, arg) + ) +} + module RustTaintTracking implements InputSig { predicate defaultTaintSanitizer(DataFlow::Node node) { none() } @@ -36,13 +50,17 @@ module RustTaintTracking implements InputSig { // taint is propagated. We limit this to not apply if the type of the // operation is a small primitive type as these are often uninteresting // (for instance in the case of an injection query). - RustDataFlow::readContentStep(pred, _, succ) and - not exists(Struct s | - s = TypeInference::inferType(succ.asExpr()).(Type::StructType).getStruct() - | - s instanceof Builtins::NumericType or - s instanceof Builtins::Bool or - s instanceof Builtins::Char + exists(Content c | + RustDataFlow::readContentStep(pred, c, succ) and + forex(Type::Type t | t = TypeInference::inferType(succ.asExpr()) | + not exists(Struct s | s = t.(Type::StructType).getStruct() | + s instanceof Builtins::NumericType or + s instanceof Builtins::Bool or + s instanceof Builtins::Char + ) + ) and + not excludedTaintStepContent(c) and + not TypeInference::inferType(succ.asExpr()).(Type::EnumType).getEnum().isFieldless() ) or // Let all read steps (including those from flow summaries and those that