Skip to content

Commit f1e4bb9

Browse files
committed
Rust: Fallback crate resolution
1 parent a07e357 commit f1e4bb9

File tree

3 files changed

+70
-42
lines changed

3 files changed

+70
-42
lines changed

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

Lines changed: 70 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ abstract class ItemNode extends Locatable {
188188
crateDefEdge(this, name, result, kind)
189189
or
190190
crateDependencyEdge(this, name, result) and
191+
not declaresDirectly(this, TTypeNamespace(), name) and
191192
kind.isInternal()
192193
or
193194
externCrateEdge(this, name, result) and
@@ -291,6 +292,7 @@ abstract class ItemNode extends Locatable {
291292
}
292293

293294
/** Gets an _external_ successor named `name`, if any. */
295+
pragma[nomagic]
294296
ItemNode getASuccessor(string name) {
295297
exists(SuccessorKind kind |
296298
result = this.getASuccessor(name, kind) and
@@ -609,17 +611,17 @@ abstract class ImplOrTraitItemNode extends ItemNode {
609611

610612
pragma[nomagic]
611613
private TypeParamItemNode resolveTypeParamPathTypeRepr(PathTypeRepr ptr) {
612-
result = resolvePath(ptr.getPath())
614+
result = resolvePathImpl(ptr.getPath())
613615
}
614616

615617
class ImplItemNode extends ImplOrTraitItemNode instanceof Impl {
616618
Path getSelfPath() { result = super.getSelfTy().(PathTypeRepr).getPath() }
617619

618620
Path getTraitPath() { result = super.getTrait().(PathTypeRepr).getPath() }
619621

620-
TypeItemNode resolveSelfTy() { result = resolvePath(this.getSelfPath()) }
622+
TypeItemNode resolveSelfTy() { result = resolvePathImpl(this.getSelfPath()) }
621623

622-
TraitItemNode resolveTraitTy() { result = resolvePath(this.getTraitPath()) }
624+
TraitItemNode resolveTraitTy() { result = resolvePathImpl(this.getTraitPath()) }
623625

624626
override AssocItemNode getAnAssocItem() { result = this.getADescendant() }
625627

@@ -713,7 +715,7 @@ private class ImplTraitTypeReprItemNode extends TypeItemNode instanceof ImplTrai
713715
}
714716

715717
pragma[nomagic]
716-
ItemNode resolveABound() { result = resolvePath(this.getABoundPath()) }
718+
ItemNode resolveABound() { result = resolvePathImpl(this.getABoundPath()) }
717719

718720
override string getName() { result = "(impl trait)" }
719721

@@ -810,7 +812,7 @@ class TraitItemNode extends ImplOrTraitItemNode, TypeItemNode instanceof Trait {
810812
Path getABoundPath() { result = super.getATypeBound().getTypeRepr().(PathTypeRepr).getPath() }
811813

812814
pragma[nomagic]
813-
ItemNode resolveABound() { result = resolvePath(this.getABoundPath()) }
815+
ItemNode resolveABound() { result = resolvePathImpl(this.getABoundPath()) }
814816

815817
override AssocItemNode getAnAssocItem() { result = this.getADescendant() }
816818

@@ -862,7 +864,7 @@ class TraitItemNode extends ImplOrTraitItemNode, TypeItemNode instanceof Trait {
862864

863865
class TypeAliasItemNode extends TypeItemNode, AssocItemNode instanceof TypeAlias {
864866
pragma[nomagic]
865-
ItemNode resolveAlias() { result = resolvePath(super.getTypeRepr().(PathTypeRepr).getPath()) }
867+
ItemNode resolveAlias() { result = resolvePathImpl(super.getTypeRepr().(PathTypeRepr).getPath()) }
866868

867869
override string getName() { result = TypeAlias.super.getName().getText() }
868870

@@ -951,7 +953,7 @@ class TypeParamItemNode extends TypeItemNode instanceof TypeParam {
951953
Path getABoundPath() { result = super.getATypeBound().getTypeRepr().(PathTypeRepr).getPath() }
952954

953955
pragma[nomagic]
954-
ItemNode resolveABound() { result = resolvePath(this.getABoundPath()) }
956+
ItemNode resolveABound() { result = resolvePathImpl(this.getABoundPath()) }
955957

956958
/**
957959
* Holds if this type parameter has a trait bound. Examples:
@@ -1153,6 +1155,11 @@ private class BuiltinSourceFile extends SourceFileItemNode {
11531155
pragma[nomagic]
11541156
private predicate crateDependencyEdge(SourceFileItemNode file, string name, CrateItemNode dep) {
11551157
exists(CrateItemNode c | dep = c.(Crate).getDependency(name) | file = c.getASourceFile())
1158+
or
1159+
// All files _should_ belong to a crate, but for those where we cannot identify the crate,
1160+
// we give access to all crates as a fallback.
1161+
not file = any(Crate c).getASourceFile() and
1162+
name = dep.getName()
11561163
}
11571164

11581165
private predicate useTreeDeclares(UseTree tree, string name) {
@@ -1174,15 +1181,24 @@ private predicate useTreeDeclares(UseTree tree, string name) {
11741181

11751182
/**
11761183
* Holds if `item` explicitly declares a sub item named `name` in the
1177-
* namespace `ns`. This includes items declared by `use` statements,
1178-
* except for glob imports.
1184+
* namespace `ns`. This excludes items declared by `use` statements.
11791185
*/
11801186
pragma[nomagic]
1181-
private predicate declares(ItemNode item, Namespace ns, string name) {
1187+
private predicate declaresDirectly(ItemNode item, Namespace ns, string name) {
11821188
exists(ItemNode child, SuccessorKind kind | child = getAChildSuccessor(item, name, kind) |
11831189
child.getNamespace() = ns and
11841190
kind.isInternalOrBoth()
11851191
)
1192+
}
1193+
1194+
/**
1195+
* Holds if `item` explicitly declares a sub item named `name` in the
1196+
* namespace `ns`. This includes items declared by `use` statements,
1197+
* except for glob imports.
1198+
*/
1199+
pragma[nomagic]
1200+
private predicate declares(ItemNode item, Namespace ns, string name) {
1201+
declaresDirectly(item, ns, name)
11861202
or
11871203
exists(ItemNode child |
11881204
child.getImmediateParent() = item and
@@ -1306,9 +1322,9 @@ pragma[nomagic]
13061322
private predicate isUnqualifiedSelfPath(RelevantPath path) { path.isUnqualified("Self") }
13071323

13081324
pragma[nomagic]
1309-
private ItemNode resolvePath0(RelevantPath path, Namespace ns, SuccessorKind kind) {
1325+
private ItemNode resolvePathImpl0(RelevantPath path, Namespace ns) {
13101326
exists(ItemNode res |
1311-
res = unqualifiedPathLookup(path, ns, kind) and
1327+
res = unqualifiedPathLookup(path, ns, _) and
13121328
if
13131329
not any(RelevantPath parent).getQualifier() = path and
13141330
isUnqualifiedSelfPath(path) and
@@ -1317,13 +1333,13 @@ private ItemNode resolvePath0(RelevantPath path, Namespace ns, SuccessorKind kin
13171333
else result = res
13181334
)
13191335
or
1320-
exists(ItemNode q, string name |
1321-
q = resolvePathQualifier(path, name) and
1336+
exists(ItemNode q, string name, SuccessorKind kind |
1337+
q = resolvePathImplQualifier(path, name) and
13221338
result = getASuccessor(q, name, ns, kind) and
13231339
kind.isExternalOrBoth()
13241340
)
13251341
or
1326-
result = resolveUseTreeListItem(_, _, path, kind) and
1342+
result = resolveUseTreeListItem(_, _, path, _) and
13271343
ns = result.getNamespace()
13281344
}
13291345

@@ -1357,19 +1373,21 @@ private predicate pathUsesNamespace(Path p, Namespace n) {
13571373
)
13581374
}
13591375

1360-
/** Gets the item that `path` resolves to, if any. */
1361-
cached
1362-
ItemNode resolvePath(RelevantPath path) {
1376+
pragma[nomagic]
1377+
private ItemNode resolvePathImpl(RelevantPath path) {
13631378
exists(Namespace ns |
1364-
result = resolvePath0(path, ns, _) and
1379+
result = resolvePathImpl0(path, ns) and
13651380
if path = any(ImplItemNode i).getSelfPath()
13661381
then
13671382
result instanceof TypeItemNode and
13681383
not result instanceof TraitItemNode
13691384
else
13701385
if path = any(ImplItemNode i).getTraitPath()
13711386
then result instanceof TraitItemNode
1372-
else any()
1387+
else
1388+
if path = any(PathTypeRepr p).getPath()
1389+
then result instanceof TypeItemNode
1390+
else any()
13731391
|
13741392
pathUsesNamespace(path, ns)
13751393
or
@@ -1379,11 +1397,36 @@ ItemNode resolvePath(RelevantPath path) {
13791397
}
13801398

13811399
pragma[nomagic]
1382-
private ItemNode resolvePathQualifier(RelevantPath path, string name) {
1383-
result = resolvePath(path.getQualifier()) and
1400+
private ItemNode resolvePathImplQualifier(RelevantPath path, string name) {
1401+
result = resolvePathImpl(path.getQualifier()) and
13841402
name = path.getText()
13851403
}
13861404

1405+
/** Gets the item that `path` resolves to, if any. */
1406+
cached
1407+
ItemNode resolvePath(RelevantPath path) {
1408+
result = resolvePathImpl(path) and
1409+
// if `path` is the qualifier of a resolvable parent, then we should
1410+
// resolve `path` to something consistent with what the parent resolves to
1411+
(
1412+
not path = any(Path parent | exists(resolvePathImpl(parent))).getQualifier()
1413+
or
1414+
exists(ItemNode i, string name |
1415+
i = resolvePathParent(path, name) and
1416+
result.getASuccessor(name) = i
1417+
)
1418+
)
1419+
}
1420+
1421+
pragma[nomagic]
1422+
private ItemNode resolvePathParent(RelevantPath path, string name) {
1423+
exists(RelevantPath parent |
1424+
result = resolvePath(parent) and
1425+
path = parent.getQualifier() and
1426+
name = parent.getText()
1427+
)
1428+
}
1429+
13871430
private predicate isUseTreeSubPath(UseTree tree, RelevantPath path) {
13881431
path = tree.getPath()
13891432
or
@@ -1429,7 +1472,7 @@ private ItemNode resolveUseTreeListItemQualifier(
14291472
pragma[nomagic]
14301473
private ItemNode resolveUseTreeListItem(Use use, UseTree tree) {
14311474
tree = use.getUseTree() and
1432-
result = resolvePath(tree.getPath())
1475+
result = resolvePathImpl(tree.getPath())
14331476
or
14341477
result = resolveUseTreeListItem(use, tree, tree.getPath(), _)
14351478
}
@@ -1482,21 +1525,13 @@ private predicate externCrateEdge(ExternCrateItemNode ec, string name, CrateItem
14821525

14831526
pragma[nomagic]
14841527
private predicate preludeItem(string name, ItemNode i) {
1485-
exists(
1486-
Crate stdOrCore, string stdOrCoreName, ModuleLikeNode mod, ModuleItemNode prelude,
1487-
ModuleItemNode rust
1488-
|
1489-
stdOrCore.getName() = stdOrCoreName and
1490-
stdOrCoreName = ["std", "core"] and
1528+
exists(Crate stdOrCore, ModuleLikeNode mod, ModuleItemNode prelude, ModuleItemNode rust |
1529+
stdOrCore.getName() = ["std", "core"] and
14911530
mod = stdOrCore.getSourceFile() and
14921531
prelude = mod.getASuccessor("prelude") and
1493-
rust = prelude.getASuccessor(["rust_2015", "rust_2018", "rust_2021", "rust_2024"])
1494-
|
1532+
rust = prelude.getASuccessor(["rust_2015", "rust_2018", "rust_2021", "rust_2024"]) and
14951533
i = rust.getASuccessor(name) and
14961534
not name = ["super", "self"]
1497-
or
1498-
name = stdOrCoreName and
1499-
i = stdOrCore
15001535
)
15011536
}
15021537

@@ -1513,7 +1548,7 @@ private predicate preludeItem(string name, ItemNode i) {
15131548
pragma[nomagic]
15141549
private predicate preludeEdge(SourceFile f, string name, ItemNode i) {
15151550
preludeItem(name, i) and
1516-
not declares(f, _, name)
1551+
not declares(f, i.getNamespace(), name)
15171552
}
15181553

15191554
pragma[nomagic]
Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
11
multipleCallTargets
22
| main.rs:118:9:118:11 | f(...) |
33
| proc_macro.rs:9:5:11:5 | ...::new(...) |
4-
multiplePathResolutions
5-
| main.rs:641:3:641:12 | proc_macro |
6-
| main.rs:647:7:647:16 | proc_macro |
7-
| main.rs:650:7:650:16 | proc_macro |

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

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -276,14 +276,11 @@ resolvePath
276276
| main.rs:635:9:635:36 | GenericStruct::<...> | main.rs:578:5:581:5 | struct GenericStruct |
277277
| main.rs:635:9:635:47 | ...::call_both | main.rs:601:9:604:9 | fn call_both |
278278
| main.rs:635:25:635:35 | Implementor | main.rs:607:5:607:23 | struct Implementor |
279-
| main.rs:641:3:641:12 | proc_macro | {EXTERNAL LOCATION} | Crate([email protected]) |
280279
| main.rs:641:3:641:12 | proc_macro | proc_macro.rs:0:0:0:0 | Crate([email protected]) |
281280
| main.rs:641:3:641:24 | ...::add_suffix | proc_macro.rs:4:1:12:1 | fn add_suffix |
282281
| main.rs:645:6:645:12 | AStruct | main.rs:644:1:644:17 | struct AStruct |
283-
| main.rs:647:7:647:16 | proc_macro | {EXTERNAL LOCATION} | Crate([email protected]) |
284282
| main.rs:647:7:647:16 | proc_macro | proc_macro.rs:0:0:0:0 | Crate([email protected]) |
285283
| main.rs:647:7:647:28 | ...::add_suffix | proc_macro.rs:4:1:12:1 | fn add_suffix |
286-
| main.rs:650:7:650:16 | proc_macro | {EXTERNAL LOCATION} | Crate([email protected]) |
287284
| main.rs:650:7:650:16 | proc_macro | proc_macro.rs:0:0:0:0 | Crate([email protected]) |
288285
| main.rs:650:7:650:28 | ...::add_suffix | proc_macro.rs:4:1:12:1 | fn add_suffix |
289286
| main.rs:655:9:655:11 | std | {EXTERNAL LOCATION} | Crate([email protected]) |

0 commit comments

Comments
 (0)