From 6b7f3392877b58f6c3fa3c6cbe17a0feab287ac2 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 23 Feb 2026 19:18:07 +0000 Subject: [PATCH] Rust: Define neutralElement in the shared data flow input. --- .../codeql/rust/dataflow/internal/FlowSummaryImpl.qll | 11 +++++++++++ .../codeql/rust/dataflow/internal/ModelsAsData.qll | 11 ++++------- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/rust/ql/lib/codeql/rust/dataflow/internal/FlowSummaryImpl.qll b/rust/ql/lib/codeql/rust/dataflow/internal/FlowSummaryImpl.qll index ec468747ab6..ab0b3aff9ca 100644 --- a/rust/ql/lib/codeql/rust/dataflow/internal/FlowSummaryImpl.qll +++ b/rust/ql/lib/codeql/rust/dataflow/internal/FlowSummaryImpl.qll @@ -9,6 +9,7 @@ private import codeql.rust.dataflow.internal.DataFlowImpl private import codeql.rust.internal.PathResolution private import codeql.rust.dataflow.FlowSummary private import codeql.rust.dataflow.Ssa +private import codeql.rust.dataflow.internal.ModelsAsData private import Content predicate encodeContentTupleField(TupleFieldContent c, string arg) { @@ -46,6 +47,16 @@ module Input implements InputSig { abstract class SinkBase extends SourceSinkBase { } + predicate neutralElement( + Input::SummarizedCallableBase c, string kind, string provenance, boolean isExact + ) { + exists(string path | + neutralModel(path, kind, provenance, _) and + c.getCanonicalPath() = path and + isExact = true + ) + } + private class CallExprFunction extends SourceBase, SinkBase { private CallExpr call; diff --git a/rust/ql/lib/codeql/rust/dataflow/internal/ModelsAsData.qll b/rust/ql/lib/codeql/rust/dataflow/internal/ModelsAsData.qll index 4b83b029c78..45fb0a1b7f2 100644 --- a/rust/ql/lib/codeql/rust/dataflow/internal/ModelsAsData.qll +++ b/rust/ql/lib/codeql/rust/dataflow/internal/ModelsAsData.qll @@ -140,19 +140,14 @@ private class SummarizedCallableFromModel extends SummarizedCallable::Range { | this = f and isExact_ = true and - p_ = p and - // Do not apply generated models where there is a neutral model - not ( - p_.isGenerated() and - neutralModel(path, "summary", _, _) - ) + p_ = p or this.implements(f) and isExact_ = false and // making inherited models generated means that source code definitions and // exact generated models take precedence p_ = "hq-generated" and - // Do not apply inherited models where there is a neutral model + // Do not apply inherited models (which are considered generated) where there is a neutral model not neutralModel(path, "summary", _, _) ) } @@ -183,6 +178,7 @@ private class FlowSourceFromModel extends FlowSource::Range { model = "MaD:" + madId.toString() ) and // Only apply generated models when no neutral model exists + // (the shared code only applies neutral models to summaries at present) not ( provenance.isGenerated() and neutralModel(path, "source", _, _) @@ -204,6 +200,7 @@ private class FlowSinkFromModel extends FlowSink::Range { model = "MaD:" + madId.toString() ) and // Only apply generated models when no neutral model exists + // (the shared code only applies neutral models to summaries at present) not ( provenance.isGenerated() and neutralModel(path, "sink", _, _)