Skip to content

Commit 8b44182

Browse files
committed
Rust: Fallback crate resolution
1 parent 4684ac1 commit 8b44182

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
@@ -208,6 +208,7 @@ abstract class ItemNode extends Locatable {
208208
crateDefEdge(this, name, result, kind)
209209
or
210210
crateDependencyEdge(this, name, result) and
211+
not declaresDirectly(this, TTypeNamespace(), name) and
211212
kind.isInternal()
212213
or
213214
externCrateEdge(this, name, result) and
@@ -311,6 +312,7 @@ abstract class ItemNode extends Locatable {
311312
}
312313

313314
/** Gets an _external_ successor named `name`, if any. */
315+
pragma[nomagic]
314316
ItemNode getASuccessor(string name) {
315317
exists(SuccessorKind kind |
316318
result = this.getASuccessor(name, kind) and
@@ -629,17 +631,17 @@ abstract class ImplOrTraitItemNode extends ItemNode {
629631

630632
pragma[nomagic]
631633
private TypeParamItemNode resolveTypeParamPathTypeRepr(PathTypeRepr ptr) {
632-
result = resolvePath(ptr.getPath())
634+
result = resolvePathImpl(ptr.getPath())
633635
}
634636

635637
class ImplItemNode extends ImplOrTraitItemNode instanceof Impl {
636638
Path getSelfPath() { result = super.getSelfTy().(PathTypeRepr).getPath() }
637639

638640
Path getTraitPath() { result = super.getTrait().(PathTypeRepr).getPath() }
639641

640-
TypeItemNode resolveSelfTy() { result = resolvePath(this.getSelfPath()) }
642+
TypeItemNode resolveSelfTy() { result = resolvePathImpl(this.getSelfPath()) }
641643

642-
TraitItemNode resolveTraitTy() { result = resolvePath(this.getTraitPath()) }
644+
TraitItemNode resolveTraitTy() { result = resolvePathImpl(this.getTraitPath()) }
643645

644646
override AssocItemNode getAnAssocItem() { result = this.getADescendant() }
645647

@@ -733,7 +735,7 @@ private class ImplTraitTypeReprItemNode extends TypeItemNode instanceof ImplTrai
733735
}
734736

735737
pragma[nomagic]
736-
ItemNode resolveABound() { result = resolvePath(this.getABoundPath()) }
738+
ItemNode resolveABound() { result = resolvePathImpl(this.getABoundPath()) }
737739

738740
override string getName() { result = "(impl trait)" }
739741

@@ -830,7 +832,7 @@ class TraitItemNode extends ImplOrTraitItemNode, TypeItemNode instanceof Trait {
830832
Path getABoundPath() { result = super.getATypeBound().getTypeRepr().(PathTypeRepr).getPath() }
831833

832834
pragma[nomagic]
833-
ItemNode resolveABound() { result = resolvePath(this.getABoundPath()) }
835+
ItemNode resolveABound() { result = resolvePathImpl(this.getABoundPath()) }
834836

835837
override AssocItemNode getAnAssocItem() { result = this.getADescendant() }
836838

@@ -882,7 +884,7 @@ class TraitItemNode extends ImplOrTraitItemNode, TypeItemNode instanceof Trait {
882884

883885
class TypeAliasItemNode extends TypeItemNode, AssocItemNode instanceof TypeAlias {
884886
pragma[nomagic]
885-
ItemNode resolveAlias() { result = resolvePath(super.getTypeRepr().(PathTypeRepr).getPath()) }
887+
ItemNode resolveAlias() { result = resolvePathImpl(super.getTypeRepr().(PathTypeRepr).getPath()) }
886888

887889
override string getName() { result = TypeAlias.super.getName().getText() }
888890

@@ -971,7 +973,7 @@ class TypeParamItemNode extends TypeItemNode instanceof TypeParam {
971973
Path getABoundPath() { result = super.getATypeBound().getTypeRepr().(PathTypeRepr).getPath() }
972974

973975
pragma[nomagic]
974-
ItemNode resolveABound() { result = resolvePath(this.getABoundPath()) }
976+
ItemNode resolveABound() { result = resolvePathImpl(this.getABoundPath()) }
975977

976978
/**
977979
* Holds if this type parameter has a trait bound. Examples:
@@ -1173,6 +1175,11 @@ private class BuiltinSourceFile extends SourceFileItemNode {
11731175
pragma[nomagic]
11741176
private predicate crateDependencyEdge(SourceFileItemNode file, string name, CrateItemNode dep) {
11751177
exists(CrateItemNode c | dep = c.(Crate).getDependency(name) | file = c.getASourceFile())
1178+
or
1179+
// All files _should_ belong to a crate, but for those where we cannot identify the crate,
1180+
// we give access to all crates as a fallback.
1181+
not file = any(Crate c).getASourceFile() and
1182+
name = dep.getName()
11761183
}
11771184

11781185
private predicate useTreeDeclares(UseTree tree, string name) {
@@ -1194,15 +1201,24 @@ private predicate useTreeDeclares(UseTree tree, string name) {
11941201

11951202
/**
11961203
* Holds if `item` explicitly declares a sub item named `name` in the
1197-
* namespace `ns`. This includes items declared by `use` statements,
1198-
* except for glob imports.
1204+
* namespace `ns`. This excludes items declared by `use` statements.
11991205
*/
12001206
pragma[nomagic]
1201-
private predicate declares(ItemNode item, Namespace ns, string name) {
1207+
private predicate declaresDirectly(ItemNode item, Namespace ns, string name) {
12021208
exists(ItemNode child, SuccessorKind kind | child = getAChildSuccessor(item, name, kind) |
12031209
child.getNamespace() = ns and
12041210
kind.isInternalOrBoth()
12051211
)
1212+
}
1213+
1214+
/**
1215+
* Holds if `item` explicitly declares a sub item named `name` in the
1216+
* namespace `ns`. This includes items declared by `use` statements,
1217+
* except for glob imports.
1218+
*/
1219+
pragma[nomagic]
1220+
private predicate declares(ItemNode item, Namespace ns, string name) {
1221+
declaresDirectly(item, ns, name)
12061222
or
12071223
exists(ItemNode child |
12081224
child.getImmediateParent() = item and
@@ -1326,9 +1342,9 @@ pragma[nomagic]
13261342
private predicate isUnqualifiedSelfPath(RelevantPath path) { path.isUnqualified("Self") }
13271343

13281344
pragma[nomagic]
1329-
private ItemNode resolvePath0(RelevantPath path, Namespace ns, SuccessorKind kind) {
1345+
private ItemNode resolvePathImpl0(RelevantPath path, Namespace ns) {
13301346
exists(ItemNode res |
1331-
res = unqualifiedPathLookup(path, ns, kind) and
1347+
res = unqualifiedPathLookup(path, ns, _) and
13321348
if
13331349
not any(RelevantPath parent).getQualifier() = path and
13341350
isUnqualifiedSelfPath(path) and
@@ -1337,13 +1353,13 @@ private ItemNode resolvePath0(RelevantPath path, Namespace ns, SuccessorKind kin
13371353
else result = res
13381354
)
13391355
or
1340-
exists(ItemNode q, string name |
1341-
q = resolvePathQualifier(path, name) and
1356+
exists(ItemNode q, string name, SuccessorKind kind |
1357+
q = resolvePathImplQualifier(path, name) and
13421358
result = getASuccessor(q, name, ns, kind) and
13431359
kind.isExternalOrBoth()
13441360
)
13451361
or
1346-
result = resolveUseTreeListItem(_, _, path, kind) and
1362+
result = resolveUseTreeListItem(_, _, path, _) and
13471363
ns = result.getNamespace()
13481364
}
13491365

@@ -1377,19 +1393,21 @@ private predicate pathUsesNamespace(Path p, Namespace n) {
13771393
)
13781394
}
13791395

1380-
/** Gets the item that `path` resolves to, if any. */
1381-
cached
1382-
ItemNode resolvePath(RelevantPath path) {
1396+
pragma[nomagic]
1397+
private ItemNode resolvePathImpl(RelevantPath path) {
13831398
exists(Namespace ns |
1384-
result = resolvePath0(path, ns, _) and
1399+
result = resolvePathImpl0(path, ns) and
13851400
if path = any(ImplItemNode i).getSelfPath()
13861401
then
13871402
result instanceof TypeItemNode and
13881403
not result instanceof TraitItemNode
13891404
else
13901405
if path = any(ImplItemNode i).getTraitPath()
13911406
then result instanceof TraitItemNode
1392-
else any()
1407+
else
1408+
if path = any(PathTypeRepr p).getPath()
1409+
then result instanceof TypeItemNode
1410+
else any()
13931411
|
13941412
pathUsesNamespace(path, ns)
13951413
or
@@ -1399,11 +1417,36 @@ ItemNode resolvePath(RelevantPath path) {
13991417
}
14001418

14011419
pragma[nomagic]
1402-
private ItemNode resolvePathQualifier(RelevantPath path, string name) {
1403-
result = resolvePath(path.getQualifier()) and
1420+
private ItemNode resolvePathImplQualifier(RelevantPath path, string name) {
1421+
result = resolvePathImpl(path.getQualifier()) and
14041422
name = path.getText()
14051423
}
14061424

1425+
/** Gets the item that `path` resolves to, if any. */
1426+
cached
1427+
ItemNode resolvePath(RelevantPath path) {
1428+
result = resolvePathImpl(path) and
1429+
// if `path` is the qualifier of a resolvable parent, then we should
1430+
// resolve `path` to something consistent with what the parent resolves to
1431+
(
1432+
not path = any(Path parent | exists(resolvePathImpl(parent))).getQualifier()
1433+
or
1434+
exists(ItemNode i, string name |
1435+
i = resolvePathParent(path, name) and
1436+
result.getASuccessor(name) = i
1437+
)
1438+
)
1439+
}
1440+
1441+
pragma[nomagic]
1442+
private ItemNode resolvePathParent(RelevantPath path, string name) {
1443+
exists(RelevantPath parent |
1444+
result = resolvePath(parent) and
1445+
path = parent.getQualifier() and
1446+
name = parent.getText()
1447+
)
1448+
}
1449+
14071450
private predicate isUseTreeSubPath(UseTree tree, RelevantPath path) {
14081451
path = tree.getPath()
14091452
or
@@ -1449,7 +1492,7 @@ private ItemNode resolveUseTreeListItemQualifier(
14491492
pragma[nomagic]
14501493
private ItemNode resolveUseTreeListItem(Use use, UseTree tree) {
14511494
tree = use.getUseTree() and
1452-
result = resolvePath(tree.getPath())
1495+
result = resolvePathImpl(tree.getPath())
14531496
or
14541497
result = resolveUseTreeListItem(use, tree, tree.getPath(), _)
14551498
}
@@ -1502,21 +1545,13 @@ private predicate externCrateEdge(ExternCrateItemNode ec, string name, CrateItem
15021545

15031546
pragma[nomagic]
15041547
private predicate preludeItem(string name, ItemNode i) {
1505-
exists(
1506-
Crate stdOrCore, string stdOrCoreName, ModuleLikeNode mod, ModuleItemNode prelude,
1507-
ModuleItemNode rust
1508-
|
1509-
stdOrCore.getName() = stdOrCoreName and
1510-
stdOrCoreName = ["std", "core"] and
1548+
exists(Crate stdOrCore, ModuleLikeNode mod, ModuleItemNode prelude, ModuleItemNode rust |
1549+
stdOrCore.getName() = ["std", "core"] and
15111550
mod = stdOrCore.getSourceFile() and
15121551
prelude = mod.getASuccessor("prelude") and
1513-
rust = prelude.getASuccessor(["rust_2015", "rust_2018", "rust_2021", "rust_2024"])
1514-
|
1552+
rust = prelude.getASuccessor(["rust_2015", "rust_2018", "rust_2021", "rust_2024"]) and
15151553
i = rust.getASuccessor(name) and
15161554
not name = ["super", "self"]
1517-
or
1518-
name = stdOrCoreName and
1519-
i = stdOrCore
15201555
)
15211556
}
15221557

@@ -1533,7 +1568,7 @@ private predicate preludeItem(string name, ItemNode i) {
15331568
pragma[nomagic]
15341569
private predicate preludeEdge(SourceFile f, string name, ItemNode i) {
15351570
preludeItem(name, i) and
1536-
not declares(f, _, name)
1571+
not declares(f, i.getNamespace(), name)
15371572
}
15381573

15391574
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)