diff --git a/rust/ql/lib/codeql/rust/internal/Definitions.qll b/rust/ql/lib/codeql/rust/internal/Definitions.qll index 6b380dae3321..0603146c9af2 100644 --- a/rust/ql/lib/codeql/rust/internal/Definitions.qll +++ b/rust/ql/lib/codeql/rust/internal/Definitions.qll @@ -3,6 +3,7 @@ * in the code viewer. */ +private import rust private import codeql.rust.elements.Variable private import codeql.rust.elements.Locatable private import codeql.rust.elements.FormatArgsExpr @@ -12,9 +13,12 @@ private import codeql.rust.elements.MacroCall private import codeql.rust.elements.NamedFormatArgument private import codeql.rust.elements.PositionalFormatArgument private import codeql.Locations +private import codeql.rust.internal.PathResolution /** An element with an associated definition. */ abstract class Use extends Locatable { + Use() { not this.(AstNode).isFromMacroExpansion() } + /** Gets the definition associated with this element. */ abstract Definition getDefinition(); @@ -30,7 +34,8 @@ private module Cached { newtype TDef = TVariable(Variable v) or TFormatArgsArgName(Name name) { name = any(FormatArgsArg a).getName() } or - TFormatArgsArgIndex(Expr e) { e = any(FormatArgsArg a).getExpr() } + TFormatArgsArgIndex(Expr e) { e = any(FormatArgsArg a).getExpr() } or + TItemNode(ItemNode i) /** * Gets an element, of kind `kind`, that element `use` uses, if any. @@ -51,7 +56,8 @@ class Definition extends Cached::TDef { Location getLocation() { result = this.asVariable().getLocation() or result = this.asName().getLocation() or - result = this.asExpr().getLocation() + result = this.asExpr().getLocation() or + result = this.asItemNode().getLocation() } /** Gets this definition as a `Variable` */ @@ -63,11 +69,15 @@ class Definition extends Cached::TDef { /** Gets this definition as an `Expr` */ Expr asExpr() { this = Cached::TFormatArgsArgIndex(result) } + /** Gets this definition as an `ItemNode` */ + ItemNode asItemNode() { this = Cached::TItemNode(result) } + /** Gets the string representation of this element. */ string toString() { result = this.asExpr().toString() or result = this.asVariable().toString() or - result = this.asName().getText() + result = this.asName().getText() or + result = this.asItemNode().toString() } } @@ -124,3 +134,20 @@ private class PositionalFormatArgumentUse extends Use instanceof PositionalForma override string getUseType() { result = "format argument" } } + +private class PathUse extends Use instanceof Path { + override Definition getDefinition() { result.asItemNode() = resolvePath(this) } + + override string getUseType() { result = "path" } +} + +private class FileUse extends Use instanceof Name { + override Definition getDefinition() { + exists(Module m | + this = m.getName() and + fileImport(m, result.asItemNode()) + ) + } + + override string getUseType() { result = "file" } +} diff --git a/rust/ql/lib/codeql/rust/internal/PathResolution.qll b/rust/ql/lib/codeql/rust/internal/PathResolution.qll index ca05b0fba7d1..d09172187ae8 100644 --- a/rust/ql/lib/codeql/rust/internal/PathResolution.qll +++ b/rust/ql/lib/codeql/rust/internal/PathResolution.qll @@ -1021,7 +1021,8 @@ private predicate pathAttrImport(Folder f, Module m, string relativePath) { private predicate shouldAppend(Folder f, string relativePath) { pathAttrImport(f, _, relativePath) } /** Holds if `m` is a `mod name;` item importing file `f`. */ -private predicate fileImport(Module m, SourceFile f) { +pragma[nomagic] +predicate fileImport(Module m, SourceFile f) { exists(string name, Folder parent | modImport0(m, name, _) and fileModule(f, name, parent) diff --git a/rust/ql/test/library-tests/definitions/Definitions.expected b/rust/ql/test/library-tests/definitions/Definitions.expected index 11f50118d22b..5d2a0db46c55 100644 --- a/rust/ql/test/library-tests/definitions/Definitions.expected +++ b/rust/ql/test/library-tests/definitions/Definitions.expected @@ -1,19 +1,21 @@ -| main.rs:2:9:2:13 | width | main.rs:5:29:5:33 | width | local variable | -| main.rs:2:9:2:13 | width | main.rs:6:41:6:45 | width | local variable | -| main.rs:2:9:2:13 | width | main.rs:7:36:7:40 | width | local variable | -| main.rs:3:9:3:17 | precision | main.rs:5:36:5:44 | precision | local variable | -| main.rs:3:9:3:17 | precision | main.rs:6:48:6:56 | precision | local variable | -| main.rs:4:9:4:13 | value | main.rs:6:34:6:38 | value | local variable | -| main.rs:4:9:4:13 | value | main.rs:7:29:7:33 | value | local variable | -| main.rs:5:50:5:54 | value | main.rs:5:22:5:26 | value | format argument | -| main.rs:6:34:6:38 | value | main.rs:6:22:6:22 | 0 | format argument | -| main.rs:6:41:6:45 | width | main.rs:6:25:6:25 | 1 | format argument | -| main.rs:6:48:6:56 | precision | main.rs:6:28:6:28 | 2 | format argument | -| main.rs:7:29:7:33 | value | main.rs:7:21:7:22 | {} | format argument | -| main.rs:7:36:7:40 | width | main.rs:7:24:7:25 | {} | format argument | -| main.rs:8:9:8:14 | people | main.rs:9:22:9:27 | people | local variable | -| main.rs:10:31:10:31 | 1 | main.rs:10:19:10:20 | {} | format argument | -| main.rs:10:31:10:31 | 1 | main.rs:10:23:10:23 | 0 | format argument | -| main.rs:10:34:10:34 | 2 | main.rs:10:16:10:16 | 1 | format argument | -| main.rs:10:34:10:34 | 2 | main.rs:10:26:10:27 | {} | format argument | -| main.rs:11:40:11:42 | "x" | main.rs:11:31:11:35 | {:<5} | format argument | +| main.rs:3:5:3:7 | lib | lib.rs:1:1:1:1 | SourceFile | file | +| main.rs:9:22:9:26 | value | main.rs:9:50:9:54 | value | format argument | +| main.rs:9:29:9:33 | width | main.rs:6:9:6:13 | width | local variable | +| main.rs:9:36:9:44 | precision | main.rs:7:9:7:17 | precision | local variable | +| main.rs:10:22:10:22 | 0 | main.rs:10:34:10:38 | value | format argument | +| main.rs:10:25:10:25 | 1 | main.rs:10:41:10:45 | width | format argument | +| main.rs:10:28:10:28 | 2 | main.rs:10:48:10:56 | precision | format argument | +| main.rs:10:34:10:38 | value | main.rs:8:9:8:13 | value | local variable | +| main.rs:10:41:10:45 | width | main.rs:6:9:6:13 | width | local variable | +| main.rs:10:48:10:56 | precision | main.rs:7:9:7:17 | precision | local variable | +| main.rs:11:21:11:22 | {} | main.rs:11:29:11:33 | value | format argument | +| main.rs:11:24:11:25 | {} | main.rs:11:36:11:40 | width | format argument | +| main.rs:11:29:11:33 | value | main.rs:8:9:8:13 | value | local variable | +| main.rs:11:36:11:40 | width | main.rs:6:9:6:13 | width | local variable | +| main.rs:13:22:13:27 | people | main.rs:12:9:12:14 | people | local variable | +| main.rs:14:16:14:16 | 1 | main.rs:14:34:14:34 | 2 | format argument | +| main.rs:14:19:14:20 | {} | main.rs:14:31:14:31 | 1 | format argument | +| main.rs:14:23:14:23 | 0 | main.rs:14:31:14:31 | 1 | format argument | +| main.rs:14:26:14:27 | {} | main.rs:14:34:14:34 | 2 | format argument | +| main.rs:15:31:15:35 | {:<5} | main.rs:15:40:15:42 | "x" | format argument | +| main.rs:16:13:16:13 | S | main.rs:1:1:1:9 | struct S | path | diff --git a/rust/ql/test/library-tests/definitions/Definitions.ql b/rust/ql/test/library-tests/definitions/Definitions.ql index 021d5f07e4a3..82a128670f4a 100644 --- a/rust/ql/test/library-tests/definitions/Definitions.ql +++ b/rust/ql/test/library-tests/definitions/Definitions.ql @@ -1,5 +1,7 @@ import codeql.rust.internal.Definitions from Definition def, Use use, string kind -where def = definitionOf(use, kind) -select def, use, kind +where + def = definitionOf(use, kind) and + use.fromSource() +select use, def, kind diff --git a/rust/ql/test/library-tests/definitions/main.rs b/rust/ql/test/library-tests/definitions/main.rs index a0ee62882807..bde0b8cb993b 100644 --- a/rust/ql/test/library-tests/definitions/main.rs +++ b/rust/ql/test/library-tests/definitions/main.rs @@ -1,3 +1,7 @@ +struct S; + +mod lib; + fn main() { let width = 4; let precision = 2; @@ -9,4 +13,5 @@ fn main() { println!("Hello {people}!"); println!("{1} {} {0} {}", 1, 2); assert_eq!(format!("Hello {:<5}!", "x"), "Hello x !"); + let x = S; }