Skip to content

Commit bca9cdc

Browse files
committed
Rust: Path resolution for extern crates
1 parent c4f4d68 commit bca9cdc

File tree

13 files changed

+1011
-526
lines changed

13 files changed

+1011
-526
lines changed

rust/ql/lib/codeql/rust/internal/PathResolution.qll

Lines changed: 70 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -127,12 +127,25 @@ abstract class ItemNode extends Locatable {
127127
or
128128
crateDependencyEdge(this, name, result)
129129
or
130+
externCrateEdge(this, name, result)
131+
or
130132
// items made available through `use` are available to nodes that contain the `use`
131133
exists(UseItemNode use |
132134
use = this.getASuccessorRec(_) and
133135
result = use.(ItemNode).getASuccessorRec(name)
134136
)
135137
or
138+
exists(ExternCrateItemNode ec | result = ec.(ItemNode).getASuccessorRec(name) |
139+
ec = this.getASuccessorRec(_)
140+
or
141+
// if the extern crate appears in the crate root, then the crate name is also added
142+
// to the 'extern prelude', see https://doc.rust-lang.org/reference/items/extern-crates.html
143+
exists(Crate c |
144+
ec = c.getSourceFile().(ItemNode).getASuccessorRec(_) and
145+
this = c.getASourceFile()
146+
)
147+
)
148+
or
136149
// items made available through macro calls are available to nodes that contain the macro call
137150
exists(MacroCallItemNode call |
138151
call = this.getASuccessorRec(_) and
@@ -226,6 +239,25 @@ abstract class ItemNode extends Locatable {
226239
)
227240
}
228241

242+
/** Gets the immediately enclosing item of this item, if any. */
243+
pragma[nomagic]
244+
ItemNode getACanonicalChild(string name) {
245+
this = result.getImmediateParent() and
246+
name = result.getName()
247+
or
248+
exists(UseItemNode use |
249+
use.(Use).hasVisibility() and
250+
use = this.getACanonicalChild(_) and
251+
useImportEdge(use, name, result) and
252+
not result instanceof Crate
253+
)
254+
or
255+
exists(MacroCallItemNode call |
256+
call = this.getACanonicalChild(_) and
257+
result = call.getACanonicalChild(name)
258+
)
259+
}
260+
229261
/** Holds if this item has a canonical path belonging to the crate `c`. */
230262
abstract predicate hasCanonicalPath(Crate c);
231263

@@ -353,7 +385,7 @@ class CrateItemNode extends ItemNode instanceof Crate {
353385

354386
override predicate providesCanonicalPathPrefixFor(Crate c, ItemNode child) {
355387
this.hasCanonicalPath(c) and
356-
exists(ModuleLikeNode m |
388+
exists(SourceFileItemNode m |
357389
child.getImmediateParent() = m and
358390
not m = child.(SourceFileItemNode).getSuper() and
359391
m = super.getSourceFile()
@@ -363,6 +395,20 @@ class CrateItemNode extends ItemNode instanceof Crate {
363395
override string getCanonicalPath(Crate c) { c = this and result = Crate.super.getName() }
364396
}
365397

398+
class ExternCrateItemNode extends ItemNode instanceof ExternCrate {
399+
override string getName() { result = super.getRename().getName().getText() }
400+
401+
override Namespace getNamespace() { none() }
402+
403+
override Visibility getVisibility() { none() }
404+
405+
override TypeParam getTypeParam(int i) { none() }
406+
407+
override predicate hasCanonicalPath(Crate c) { none() }
408+
409+
override string getCanonicalPath(Crate c) { none() }
410+
}
411+
366412
/** An item that can occur in a trait or an `impl` block. */
367413
abstract private class AssocItemNode extends ItemNode, AssocItem {
368414
/** Holds if this associated item has an implementation. */
@@ -793,6 +839,10 @@ class TypeAliasItemNode extends AssocItemNode instanceof TypeAlias {
793839
override Visibility getVisibility() { result = TypeAlias.super.getVisibility() }
794840

795841
override TypeParam getTypeParam(int i) { result = super.getGenericParamList().getTypeParam(i) }
842+
843+
override predicate hasCanonicalPath(Crate c) { none() }
844+
845+
override string getCanonicalPath(Crate c) { none() }
796846
}
797847

798848
private class UnionItemNode extends ItemNode instanceof Union {
@@ -1062,12 +1112,12 @@ private predicate crateDefEdge(CrateItemNode c, string name, ItemNode i) {
10621112
}
10631113

10641114
/**
1065-
* Holds if `m` depends on crate `dep` named `name`.
1115+
* Holds if `file` depends on crate `dep` named `name`.
10661116
*/
1067-
private predicate crateDependencyEdge(ModuleLikeNode m, string name, CrateItemNode dep) {
1117+
private predicate crateDependencyEdge(SourceFileItemNode file, string name, CrateItemNode dep) {
10681118
exists(CrateItemNode c |
10691119
dep = c.(Crate).getDependency(name) and
1070-
m = c.getASourceFile()
1120+
file = c.getASourceFile()
10711121
)
10721122
}
10731123

@@ -1403,6 +1453,22 @@ private predicate useImportEdge(Use use, string name, ItemNode item) {
14031453
)
14041454
}
14051455

1456+
/** Holds if `ec` imports `crate` as `name`. */
1457+
pragma[nomagic]
1458+
private predicate externCrateEdge(ExternCrateItemNode ec, string name, CrateItemNode crate) {
1459+
name = ec.getName() and
1460+
exists(SourceFile f, string s |
1461+
ec.getFile() = f.getFile() and
1462+
s = ec.(ExternCrate).getIdentifier().getText()
1463+
|
1464+
crateDependencyEdge(f, s, crate)
1465+
or
1466+
// `extern crate` is used to import the current crate
1467+
s = "self" and
1468+
ec.getFile() = crate.getASourceFile().getFile()
1469+
)
1470+
}
1471+
14061472
/**
14071473
* Holds if `i` is available inside `f` because it is reexported in
14081474
* [the `core` prelude][1] or [the `std` prelude][2].

rust/ql/test/library-tests/dataflow/sources/CONSISTENCY/PathResolutionConsistency.expected

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,64 @@
1+
multiplePathResolutions
2+
| test.rs:112:62:112:73 | ...::from | file://:0:0:0:0 | fn from |
3+
| test.rs:112:62:112:73 | ...::from | file://:0:0:0:0 | fn from |
4+
| test.rs:112:62:112:73 | ...::from | file://:0:0:0:0 | fn from |
5+
| test.rs:112:62:112:73 | ...::from | file://:0:0:0:0 | fn from |
6+
| test.rs:112:62:112:73 | ...::from | file://:0:0:0:0 | fn from |
7+
| test.rs:112:62:112:73 | ...::from | file://:0:0:0:0 | fn from |
8+
| test.rs:112:62:112:73 | ...::from | file://:0:0:0:0 | fn from |
9+
| test.rs:112:62:112:73 | ...::from | file://:0:0:0:0 | fn from |
10+
| test.rs:112:62:112:73 | ...::from | file://:0:0:0:0 | fn from |
11+
| test.rs:112:62:112:73 | ...::from | file://:0:0:0:0 | fn from |
12+
| test.rs:112:62:112:73 | ...::from | file://:0:0:0:0 | fn from |
13+
| test.rs:112:62:112:73 | ...::from | file://:0:0:0:0 | fn from |
14+
| test.rs:112:62:112:73 | ...::from | file://:0:0:0:0 | fn from |
15+
| test.rs:112:62:112:73 | ...::from | file://:0:0:0:0 | fn from |
16+
| test.rs:112:62:112:73 | ...::from | file://:0:0:0:0 | fn from |
17+
| test.rs:119:58:119:69 | ...::from | file://:0:0:0:0 | fn from |
18+
| test.rs:119:58:119:69 | ...::from | file://:0:0:0:0 | fn from |
19+
| test.rs:119:58:119:69 | ...::from | file://:0:0:0:0 | fn from |
20+
| test.rs:119:58:119:69 | ...::from | file://:0:0:0:0 | fn from |
21+
| test.rs:119:58:119:69 | ...::from | file://:0:0:0:0 | fn from |
22+
| test.rs:119:58:119:69 | ...::from | file://:0:0:0:0 | fn from |
23+
| test.rs:119:58:119:69 | ...::from | file://:0:0:0:0 | fn from |
24+
| test.rs:119:58:119:69 | ...::from | file://:0:0:0:0 | fn from |
25+
| test.rs:119:58:119:69 | ...::from | file://:0:0:0:0 | fn from |
26+
| test.rs:119:58:119:69 | ...::from | file://:0:0:0:0 | fn from |
27+
| test.rs:119:58:119:69 | ...::from | file://:0:0:0:0 | fn from |
28+
| test.rs:119:58:119:69 | ...::from | file://:0:0:0:0 | fn from |
29+
| test.rs:119:58:119:69 | ...::from | file://:0:0:0:0 | fn from |
30+
| test.rs:119:58:119:69 | ...::from | file://:0:0:0:0 | fn from |
31+
| test.rs:119:58:119:69 | ...::from | file://:0:0:0:0 | fn from |
32+
| test.rs:775:50:775:61 | ...::from | file://:0:0:0:0 | fn from |
33+
| test.rs:775:50:775:61 | ...::from | file://:0:0:0:0 | fn from |
34+
| test.rs:775:50:775:61 | ...::from | file://:0:0:0:0 | fn from |
35+
| test.rs:775:50:775:61 | ...::from | file://:0:0:0:0 | fn from |
36+
| test.rs:775:50:775:61 | ...::from | file://:0:0:0:0 | fn from |
37+
| test.rs:775:50:775:61 | ...::from | file://:0:0:0:0 | fn from |
38+
| test.rs:775:50:775:61 | ...::from | file://:0:0:0:0 | fn from |
39+
| test.rs:775:50:775:61 | ...::from | file://:0:0:0:0 | fn from |
40+
| test.rs:775:50:775:61 | ...::from | file://:0:0:0:0 | fn from |
41+
| test.rs:775:50:775:61 | ...::from | file://:0:0:0:0 | fn from |
42+
| test.rs:775:50:775:61 | ...::from | file://:0:0:0:0 | fn from |
43+
| test.rs:775:50:775:61 | ...::from | file://:0:0:0:0 | fn from |
44+
| test.rs:775:50:775:61 | ...::from | file://:0:0:0:0 | fn from |
45+
| test.rs:775:50:775:61 | ...::from | file://:0:0:0:0 | fn from |
46+
| test.rs:775:50:775:61 | ...::from | file://:0:0:0:0 | fn from |
47+
| test.rs:775:50:775:61 | ...::from | file://:0:0:0:0 | fn from |
48+
| test.rs:775:50:775:61 | ...::from | file://:0:0:0:0 | fn from |
49+
| test.rs:775:50:775:61 | ...::from | file://:0:0:0:0 | fn from |
50+
| test.rs:775:50:775:61 | ...::from | file://:0:0:0:0 | fn from |
51+
| test.rs:775:50:775:61 | ...::from | file://:0:0:0:0 | fn from |
52+
| test.rs:775:50:775:61 | ...::from | file://:0:0:0:0 | fn from |
53+
| test.rs:775:50:775:61 | ...::from | file://:0:0:0:0 | fn from |
54+
| test.rs:775:50:775:61 | ...::from | file://:0:0:0:0 | fn from |
55+
| test.rs:775:50:775:61 | ...::from | file://:0:0:0:0 | fn from |
56+
| test.rs:775:50:775:61 | ...::from | file://:0:0:0:0 | fn from |
57+
| test.rs:775:50:775:61 | ...::from | file://:0:0:0:0 | fn from |
58+
| test.rs:775:50:775:61 | ...::from | file://:0:0:0:0 | fn from |
59+
| test.rs:775:50:775:61 | ...::from | file://:0:0:0:0 | fn from |
60+
| test.rs:775:50:775:61 | ...::from | file://:0:0:0:0 | fn from |
61+
| test.rs:775:50:775:61 | ...::from | file://:0:0:0:0 | fn from |
162
multipleCanonicalPaths
263
| file://:0:0:0:0 | fn to_ordering | file://:0:0:0:0 | Crate([email protected]) | <typenum::Equal as core::cmp::Ord>::to_ordering |
364
| file://:0:0:0:0 | fn to_ordering | file://:0:0:0:0 | Crate([email protected]) | <typenum::Equal as typenum::marker_traits::Ord>::to_ordering |

rust/ql/test/library-tests/dataflow/strings/inline-taint-flow.expected

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,10 @@ edges
2222
| main.rs:57:11:57:26 | source_slice(...) | main.rs:57:6:57:7 | s1 | provenance | |
2323
| main.rs:58:6:58:7 | s2 | main.rs:59:7:59:8 | s2 | provenance | |
2424
| main.rs:58:11:58:24 | s1.to_string() | main.rs:58:6:58:7 | s2 | provenance | |
25+
| main.rs:63:9:63:9 | s | main.rs:64:16:64:16 | s | provenance | |
2526
| main.rs:63:9:63:9 | s | main.rs:64:16:64:25 | s.as_str() | provenance | MaD:3 |
2627
| main.rs:63:13:63:22 | source(...) | main.rs:63:9:63:9 | s | provenance | |
28+
| main.rs:64:16:64:16 | s | main.rs:64:16:64:25 | s.as_str() | provenance | MaD:3 |
2729
| main.rs:68:9:68:9 | s | main.rs:70:34:70:61 | MacroExpr | provenance | |
2830
| main.rs:68:9:68:9 | s | main.rs:73:34:73:59 | MacroExpr | provenance | |
2931
| main.rs:68:13:68:22 | source(...) | main.rs:68:9:68:9 | s | provenance | |
@@ -75,6 +77,7 @@ nodes
7577
| main.rs:59:7:59:8 | s2 | semmle.label | s2 |
7678
| main.rs:63:9:63:9 | s | semmle.label | s |
7779
| main.rs:63:13:63:22 | source(...) | semmle.label | source(...) |
80+
| main.rs:64:16:64:16 | s | semmle.label | s |
7881
| main.rs:64:16:64:25 | s.as_str() | semmle.label | s.as_str() |
7982
| main.rs:68:9:68:9 | s | semmle.label | s |
8083
| main.rs:68:13:68:22 | source(...) | semmle.label | source(...) |

rust/ql/test/library-tests/path-resolution/my.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ type Result<
2121
T, // T
2222
> = ::std::result::Result<
2323
T, // $ item=T
24-
String,> // $ item=Result
24+
String,> // $ item=Result $ item=String
2525
; // my::Result
2626

2727
fn int_div(

rust/ql/test/library-tests/path-resolution/path-resolution.expected

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,4 @@
11
testFailures
2-
| main.rs:288:27:288:48 | //... | Missing result: item=I71 |
3-
| main.rs:288:27:288:48 | //... | Missing result: item=I72 |
4-
| main.rs:291:22:291:34 | //... | Missing result: item=I72 |
5-
| main.rs:292:27:292:39 | //... | Missing result: item=I72 |
6-
| main.rs:293:18:293:30 | //... | Missing result: item=I71 |
7-
| main.rs:655:16:655:28 | //... | Missing result: item=I25 |
82
mod
93
| lib.rs:1:1:1:7 | mod my |
104
| main.rs:1:1:1:7 | mod my |
@@ -152,6 +146,13 @@ resolvePath
152146
| main.rs:278:16:278:16 | T | main.rs:272:7:272:7 | T |
153147
| main.rs:279:14:279:17 | Self | main.rs:270:5:280:5 | trait MyParamTrait |
154148
| main.rs:279:14:279:33 | ...::AssociatedType | main.rs:274:9:274:28 | type AssociatedType |
149+
| main.rs:288:13:288:16 | zelf | main.rs:0:0:0:0 | Crate([email protected]) |
150+
| main.rs:288:13:288:21 | ...::m13 | main.rs:283:1:296:1 | mod m13 |
151+
| main.rs:288:13:288:24 | ...::f | main.rs:284:5:284:17 | fn f |
152+
| main.rs:288:13:288:24 | ...::f | main.rs:284:19:285:19 | struct f |
153+
| main.rs:291:17:291:17 | f | main.rs:284:19:285:19 | struct f |
154+
| main.rs:292:21:292:21 | f | main.rs:284:19:285:19 | struct f |
155+
| main.rs:293:13:293:13 | f | main.rs:284:5:284:17 | fn f |
155156
| main.rs:307:9:307:14 | Trait1 | main.rs:299:5:303:5 | trait Trait1 |
156157
| main.rs:310:13:310:16 | Self | main.rs:305:5:313:5 | trait Trait2 |
157158
| main.rs:310:13:310:19 | ...::g | main.rs:302:9:302:20 | fn g |
@@ -325,6 +326,8 @@ resolvePath
325326
| main.rs:653:5:653:10 | ...::f | main.rs:547:5:551:5 | fn f |
326327
| main.rs:654:5:654:7 | m24 | main.rs:554:1:622:1 | mod m24 |
327328
| main.rs:654:5:654:10 | ...::f | main.rs:608:5:621:5 | fn f |
329+
| main.rs:655:5:655:8 | zelf | main.rs:0:0:0:0 | Crate([email protected]) |
330+
| main.rs:655:5:655:11 | ...::h | main.rs:50:1:69:1 | fn h |
328331
| my2/mod.rs:5:5:5:11 | nested2 | my2/mod.rs:1:1:1:16 | mod nested2 |
329332
| my2/mod.rs:5:5:5:20 | ...::nested3 | my2/nested2.rs:1:1:11:1 | mod nested3 |
330333
| my2/mod.rs:5:5:5:29 | ...::nested4 | my2/nested2.rs:2:5:10:5 | mod nested4 |
@@ -354,6 +357,7 @@ resolvePath
354357
| my.rs:22:5:22:17 | ...::result | file:///RUSTUP_HOME/toolchain/lib/rustlib/src/rust/library/core/src/lib.rs:356:1:356:15 | mod result |
355358
| my.rs:22:5:24:12 | ...::Result::<...> | file:///RUSTUP_HOME/toolchain/lib/rustlib/src/rust/library/core/src/result.rs:520:1:538:1 | enum Result |
356359
| my.rs:23:5:23:5 | T | my.rs:21:5:21:5 | T |
360+
| my.rs:24:5:24:10 | String | file:///RUSTUP_HOME/toolchain/lib/rustlib/src/rust/library/alloc/src/string.rs:70:1:364:1 | struct String |
357361
| my.rs:28:8:28:10 | i32 | file:///BUILTINS/types.rs:12:1:12:15 | struct i32 |
358362
| my.rs:29:8:29:10 | i32 | file:///BUILTINS/types.rs:12:1:12:15 | struct i32 |
359363
| my.rs:30:6:30:16 | Result::<...> | my.rs:18:34:25:1 | type Result<...> |

rust/ql/test/library-tests/variables/CONSISTENCY/PathResolutionConsistency.expected

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,16 @@ multipleMethodCallTargets
77
| main.rs:459:9:459:23 | z.add_assign(...) | file://:0:0:0:0 | fn add_assign |
88
| main.rs:459:9:459:23 | z.add_assign(...) | file://:0:0:0:0 | fn add_assign |
99
| main.rs:459:9:459:23 | z.add_assign(...) | file://:0:0:0:0 | fn add_assign |
10+
multiplePathResolutions
11+
| main.rs:85:19:85:30 | ...::from | file://:0:0:0:0 | fn from |
12+
| main.rs:85:19:85:30 | ...::from | file://:0:0:0:0 | fn from |
13+
| main.rs:85:19:85:30 | ...::from | file://:0:0:0:0 | fn from |
14+
| main.rs:85:19:85:30 | ...::from | file://:0:0:0:0 | fn from |
15+
| main.rs:85:19:85:30 | ...::from | file://:0:0:0:0 | fn from |
16+
| main.rs:85:19:85:30 | ...::from | file://:0:0:0:0 | fn from |
17+
| main.rs:102:19:102:30 | ...::from | file://:0:0:0:0 | fn from |
18+
| main.rs:102:19:102:30 | ...::from | file://:0:0:0:0 | fn from |
19+
| main.rs:102:19:102:30 | ...::from | file://:0:0:0:0 | fn from |
20+
| main.rs:102:19:102:30 | ...::from | file://:0:0:0:0 | fn from |
21+
| main.rs:102:19:102:30 | ...::from | file://:0:0:0:0 | fn from |
22+
| main.rs:102:19:102:30 | ...::from | file://:0:0:0:0 | fn from |

rust/ql/test/query-tests/diagnostics/SummaryStatsReduced.expected

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
| Files extracted - without errors % | 57 |
77
| Inconsistencies - AST | 0 |
88
| Inconsistencies - CFG | 0 |
9-
| Inconsistencies - Path resolution | 0 |
9+
| Inconsistencies - Path resolution | 1 |
1010
| Inconsistencies - SSA | 0 |
1111
| Inconsistencies - data flow | 0 |
1212
| Lines of code extracted | 60 |

0 commit comments

Comments
 (0)