From 143d7e20849bb9abd93a0b4c35b52bcd72795d9e Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Fri, 22 Nov 2024 10:30:33 +0100 Subject: [PATCH] Rust: Use extended canonical paths to resolve calls in data flow --- .../rust/dataflow/internal/DataFlowImpl.qll | 54 ++++++++++++++++--- shared/util/codeql/util/Option.qll | 1 + 2 files changed, 49 insertions(+), 6 deletions(-) diff --git a/rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll b/rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll index 1ec8a42ee7e0..3710004b8de6 100644 --- a/rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll +++ b/rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll @@ -399,13 +399,55 @@ module RustDataFlow implements InputSig { final class ReturnKind = ReturnKindAlias; + private import codeql.util.Option + + private class CrateOrigin extends string { + CrateOrigin() { + this = [any(Item i).getCrateOrigin(), any(Resolvable r).getResolvedCrateOrigin()] + } + } + + private class CrateOriginOption = Option::Option; + + pragma[nomagic] + private predicate hasExtendedCanonicalPath( + DataFlowCallable c, CrateOriginOption crate, string path + ) { + exists(Item i | + i = c.asCfgScope() and + path = i.getExtendedCanonicalPath() + | + crate.asSome() = i.getCrateOrigin() + or + crate.isNone() and + not i.hasCrateOrigin() + ) + } + + pragma[nomagic] + private predicate resolvesExtendedCanonicalPath( + DataFlowCall c, CrateOriginOption crate, string path + ) { + exists(Resolvable r | + path = r.getResolvedPath() and + ( + r = c.asMethodCallExprCfgNode().getExpr() + or + r = c.asCallExprCfgNode().getExpr().(PathExprCfgNode).getPath() + ) + | + crate.asSome() = r.getResolvedCrateOrigin() + or + crate.isNone() and + not r.hasResolvedCrateOrigin() + ) + } + /** Gets a viable implementation of the target of the given `Call`. */ - DataFlowCallable viableCallable(DataFlowCall c) { - exists(Function f, string name | result.asCfgScope() = f and name = f.getName().toString() | - if f.getParamList().hasSelfParam() - then name = c.asMethodCallExprCfgNode().getNameRef().getText() - else - name = c.asCallExprCfgNode().getExpr().getExpr().(PathExpr).getPath().getPart().toString() + DataFlowCallable viableCallable(DataFlowCall call) { + exists(string path, CrateOriginOption crate | + hasExtendedCanonicalPath(result, crate, path) and + resolvesExtendedCanonicalPath(call, crate, path) ) } diff --git a/shared/util/codeql/util/Option.qll b/shared/util/codeql/util/Option.qll index 31df747afe87..8ba4d8e840bc 100644 --- a/shared/util/codeql/util/Option.qll +++ b/shared/util/codeql/util/Option.qll @@ -2,6 +2,7 @@ /** A type with `toString`. */ private signature class TypeWithToString { + bindingset[this] string toString(); }