Skip to content

Commit f092594

Browse files
committed
Rust: add location definitions for format arguments
1 parent 997a622 commit f092594

File tree

3 files changed

+110
-14
lines changed

3 files changed

+110
-14
lines changed

rust/ql/lib/ide-contextual-queries/Definitions.qll

Lines changed: 103 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,113 @@
55

66
private import codeql.rust.elements.Variable
77
private import codeql.rust.elements.Locatable
8+
private import codeql.rust.elements.FormatArgsExpr
9+
private import codeql.rust.elements.FormatArgsArg
10+
private import codeql.rust.elements.Format
11+
private import codeql.rust.elements.NamedFormatArgument
12+
private import codeql.rust.elements.PositionalFormatArgument
13+
private import codeql.Locations
814

9-
private predicate localVariable(Locatable e, Variable def) { e = def.getAnAccess() }
15+
/** An element with an associated definition. */
16+
abstract class Use extends Locatable {
17+
/** Gets the definition associated with this element. */
18+
abstract Definition getDefinition();
19+
20+
/**
21+
* Gets the type of use.
22+
*/
23+
abstract string getUseType();
24+
}
25+
26+
private newtype TDef =
27+
TVariable(Variable v) or
28+
TFormatArgsArgName(Name name) { name = any(FormatArgsArg a).getName() } or
29+
TFormatArgsArgIndex(Expr e) { e = any(FormatArgsArg a).getExpr() }
30+
31+
/** A definition */
32+
class Definition extends TDef {
33+
/** Gets the location of this variable. */
34+
Location getLocation() {
35+
result = this.asVariable().getLocation() or
36+
result = this.asName().getLocation() or
37+
result = this.asExpr().getLocation()
38+
}
39+
40+
/** Gets this definition as a `Variable` */
41+
Variable asVariable() { this = TVariable(result) }
42+
43+
/** Gets this definition as a `Name` */
44+
Name asName() { this = TFormatArgsArgName(result) }
45+
46+
/** Gets this definition as an `Expr` */
47+
Expr asExpr() { this = TFormatArgsArgIndex(result) }
48+
49+
/** Gets the string representation of this element. */
50+
string toString() {
51+
result = this.asExpr().toString() or
52+
result = this.asVariable().toString() or
53+
result = this.asName().getText()
54+
}
55+
}
56+
57+
private class LocalVariableUse extends Use instanceof VariableAccess {
58+
private Variable def;
59+
60+
LocalVariableUse() { this = def.getAnAccess() }
61+
62+
override Definition getDefinition() { result.asVariable() = def }
63+
64+
override string getUseType() { result = "local variable" }
65+
}
66+
67+
private class NamedFormatArgumentUse extends Use instanceof NamedFormatArgument {
68+
private Name def;
69+
70+
NamedFormatArgumentUse() {
71+
exists(FormatArgsExpr parent |
72+
parent = this.getParent().getParent() and
73+
parent.getAnArg().getName() = def and
74+
this.getName() = def.getText()
75+
)
76+
}
77+
78+
override Definition getDefinition() { result.asName() = def }
79+
80+
override string getUseType() { result = "format argument" }
81+
}
82+
83+
private class PositionalFormatUse extends Use instanceof Format {
84+
PositionalFormatUse() { not exists(this.getArgumentRef()) }
85+
86+
override Definition getDefinition() {
87+
exists(FormatArgsExpr parent, int index | parent.getFormat(_) = this |
88+
this = rank[index + 1](PositionalFormatUse f, int i | parent.getFormat(i) = f | f order by i) and
89+
result.asExpr() = parent.getArg(index).getExpr()
90+
)
91+
}
92+
93+
override string getUseType() { result = "format argument" }
94+
}
95+
96+
private class PositionalFormatArgumentUse extends Use instanceof PositionalFormatArgument {
97+
private Expr def;
98+
99+
PositionalFormatArgumentUse() {
100+
exists(FormatArgsExpr parent |
101+
parent = this.getParent().getParent() and
102+
def = parent.getArg(this.getIndex()).getExpr()
103+
)
104+
}
105+
106+
override Definition getDefinition() { result.asExpr() = def }
107+
108+
override string getUseType() { result = "format argument" }
109+
}
10110

11111
/**
12112
* Gets an element, of kind `kind`, that element `use` uses, if any.
13113
*/
14114
cached
15-
Variable definitionOf(Locatable use, string kind) {
16-
localVariable(use, result) and kind = "local variable"
115+
Definition definitionOf(Use use, string kind) {
116+
result = use.getDefinition() and kind = use.getUseType()
17117
}

rust/ql/lib/ide-contextual-queries/localDefinitions.ql

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,12 @@
88
*/
99

1010
import codeql.IDEContextual
11-
import codeql.rust.elements.Variable
12-
import codeql.rust.elements.Locatable
1311
import Definitions
1412

1513
external string selectedSourceFile();
1614

17-
from Locatable e, Variable def, string kind
15+
from Use use, Definition def, string kind
1816
where
19-
def = definitionOf(e, kind) and
20-
e.getLocation().getFile() = getFileBySourceArchiveName(selectedSourceFile())
21-
select e, def, kind
17+
def = definitionOf(use, kind) and
18+
use.getLocation().getFile() = getFileBySourceArchiveName(selectedSourceFile())
19+
select use, def, kind

rust/ql/lib/ide-contextual-queries/localReferences.ql

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,12 @@
88
*/
99

1010
import codeql.IDEContextual
11-
import codeql.rust.elements.Locatable
12-
import codeql.rust.elements.Variable
1311
import Definitions
1412

1513
external string selectedSourceFile();
1614

17-
from Locatable e, Variable def, string kind
15+
from Use use, Definition def, string kind
1816
where
19-
def = definitionOf(e, kind) and
17+
def = definitionOf(use, kind) and
2018
def.getLocation().getFile() = getFileBySourceArchiveName(selectedSourceFile())
21-
select e, def, kind
19+
select use, def, kind

0 commit comments

Comments
 (0)