From 2e1b8b8b0e8ec208831259e7c2ae15b2972a1fed Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Tue, 8 Apr 2025 13:10:52 +0200 Subject: [PATCH 1/2] Rust: Fix bad join in `unqualifiedPathLookup` Before ``` Pipeline standard for PathResolution::unqualifiedPathLookup/2#6b171b76#reorder_2_0_1@822d53wq was evaluated in 61 iterations totaling 118ms (delta sizes total: 131072). 606491 ~0% {4} r1 = SCAN `PathResolution::getASuccessor/3#febac7bd#prev_delta` OUTPUT In.1, In.2, In.0, In.3 106457 ~1% {3} | JOIN WITH `PathResolution::unqualifiedPathLookup/4#e32cdfce_1230#join_rhs` ON FIRST 3 OUTPUT Lhs.3, Rhs.3, Lhs.1 606491 ~2% {4} r2 = SCAN `PathResolution::getASuccessor/3#febac7bd#prev_delta` OUTPUT In.0, In.2, In.3, In.1 19261 ~0% {4} r3 = JOIN r2 WITH `PathResolution::ModuleLikeNode.isRoot/0#dispred#21662e64` ON FIRST 1 OUTPUT Lhs.3, Lhs.0, Lhs.1, Lhs.2 42776643 ~1% {4} r4 = JOIN r2 WITH `doublyBoundedFastTC@PathResolution::hasChild/2#6b318d51#2@PathResolution::isRoot/1#a01ce5c3#1@PathResolution::hasCratePath/1#73ea688d#1` ON FIRST 1 OUTPUT Lhs.3, Rhs.1, Lhs.1, Lhs.2 42795904 ~1% {4} r5 = r3 UNION r4 24921 ~6% {3} | JOIN WITH `PathResolution::RelevantPath.isCratePath/2#e595e892_120#join_rhs` ON FIRST 2 OUTPUT Lhs.3, Rhs.2, Lhs.2 131378 ~2% {3} r6 = r1 UNION r5 131072 ~2% {3} | AND NOT `PathResolution::unqualifiedPathLookup/2#6b171b76#reorder_2_0_1#prev`(FIRST 3) return r6 ``` After ``` Pipeline standard for PathResolution::unqualifiedPathLookup/2#6b171b76#reorder_2_0_1@0553a4wi was evaluated in 66 iterations totaling 10ms (delta sizes total: 131072). 610251 ~0% {4} r1 = SCAN `PathResolution::getASuccessor/3#febac7bd#prev_delta` OUTPUT In.1, In.2, In.0, In.3 131378 ~0% {3} | JOIN WITH `PathResolution::unqualifiedPathLookup1/4#781de0cd_1230#join_rhs` ON FIRST 3 OUTPUT Lhs.3, Rhs.3, Lhs.1 131072 ~0% {3} | AND NOT `PathResolution::unqualifiedPathLookup/2#6b171b76#reorder_2_0_1#prev`(FIRST 3) return r1 ``` --- .../codeql/rust/internal/PathResolution.qll | 29 ++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/rust/ql/lib/codeql/rust/internal/PathResolution.qll b/rust/ql/lib/codeql/rust/internal/PathResolution.qll index 91d7e87704c6..74f03e3f6093 100644 --- a/rust/ql/lib/codeql/rust/internal/PathResolution.qll +++ b/rust/ql/lib/codeql/rust/internal/PathResolution.qll @@ -882,20 +882,24 @@ private predicate hasChild(ItemNode parent, ItemNode child) { child.getImmediate private predicate rootHasCratePathTc(ItemNode i1, ItemNode i2) = doublyBoundedFastTC(hasChild/2, isRoot/1, hasCratePath/1)(i1, i2) +pragma[nomagic] +private predicate unqualifiedPathLookup1(RelevantPath p, string name, Namespace ns, ItemNode encl) { + unqualifiedPathLookup(p, name, ns, encl) + or + // For `($)crate`, jump directly to the root module + exists(ItemNode i | p.isCratePath(name, i) | + encl.(ModuleLikeNode).isRoot() and + encl = i + or + rootHasCratePathTc(encl, i) + ) +} + pragma[nomagic] private ItemNode unqualifiedPathLookup(RelevantPath path, Namespace ns) { exists(ItemNode encl, string name | - result = getASuccessor(encl, pragma[only_bind_into](name), ns) - | - unqualifiedPathLookup(path, name, ns, encl) - or - // For `($)crate`, jump directly to the root module - exists(ItemNode i | path.isCratePath(pragma[only_bind_into](name), i) | - encl.(ModuleLikeNode).isRoot() and - encl = i - or - rootHasCratePathTc(encl, i) - ) + result = getASuccessor(encl, name, ns) and + unqualifiedPathLookup1(path, name, ns, encl) ) } @@ -916,8 +920,7 @@ private ItemNode resolvePath0(RelevantPath path, Namespace ns) { or exists(ItemNode q, string name | q = resolvePathQualifier(path, name) and - result = q.getASuccessor(name) and - ns = result.getNamespace() + result = getASuccessor(q, name, ns) ) or result = resolveUseTreeListItem(_, _, path) and From 95add2f60bc474b69625a1394c12f4b2a4822b0b Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Tue, 8 Apr 2025 13:11:32 +0200 Subject: [PATCH 2/2] Rust: Fix bad join in `getAPrivateVisibleModule` Before ``` Pipeline standard for PathResolution::getAPrivateVisibleModule/1#3829a5ee@822d5hwq was evaluated in 24 iterations totaling 16ms (delta sizes total: 4843). 105047 ~63652% {2} r1 = SCAN `PathResolution::resolvePathPrivate/3#56db2cdf#reorder_1_2_0_3#prev_delta` OUTPUT In.0, In.0 69 ~0% {2} r2 = JOIN `#PathResolution::ItemNode.getImmediateParentModule/0#dispred#57c4c6d5Plus#bf#reorder_1_0#prev_delta` WITH `PathResolution::resolvePathPrivate/3#56db2cdf#reorder_1_2_0_3#prev` ON FIRST 1 OUTPUT Lhs.0, Lhs.1 5766690 ~148309% {2} r3 = JOIN `PathResolution::resolvePathPrivate/3#56db2cdf#reorder_1_2_0_3#prev_delta` WITH `#PathResolution::ItemNode.getImmediateParentModule/0#dispred#57c4c6d5Plus#bf#reorder_1_0#prev` ON FIRST 1 OUTPUT Lhs.0, Rhs.1 5871806 ~143984% {2} r4 = r1 UNION r2 UNION r3 6859 ~148% {2} | AND NOT `PathResolution::getAPrivateVisibleModule/1#3829a5ee#prev`(FIRST 2) return r4 ``` After ``` Pipeline standard for PathResolution::getAPrivateVisibleModule/1#3829a5ee@5edefhwp was evaluated in 12 iterations totaling 0ms (delta sizes total: 3515). 339 ~1% {2} r1 = SCAN `PathResolution::isItemParent/1#d5e587d6#prev_delta` OUTPUT In.0, In.0 3130 ~0% {2} r2 = JOIN `PathResolution::isItemParent/1#d5e587d6#prev_delta` WITH `#PathResolution::ItemNode.getImmediateParentModule/0#dispred#57c4c6d5Plus#bf#reorder_1_0#prev` ON FIRST 1 OUTPUT Lhs.0, Rhs.1 46 ~0% {2} r3 = JOIN `#PathResolution::ItemNode.getImmediateParentModule/0#dispred#57c4c6d5Plus#bf#reorder_1_0#prev_delta` WITH `PathResolution::isItemParent/1#d5e587d6#prev` ON FIRST 1 OUTPUT Lhs.0, Lhs.1 3515 ~2% {2} r4 = r1 UNION r2 UNION r3 3515 ~2% {2} | AND NOT `PathResolution::getAPrivateVisibleModule/1#3829a5ee#prev`(FIRST 2) return r4 ``` --- rust/ql/lib/codeql/rust/internal/PathResolution.qll | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/rust/ql/lib/codeql/rust/internal/PathResolution.qll b/rust/ql/lib/codeql/rust/internal/PathResolution.qll index 74f03e3f6093..fca468359599 100644 --- a/rust/ql/lib/codeql/rust/internal/PathResolution.qll +++ b/rust/ql/lib/codeql/rust/internal/PathResolution.qll @@ -981,6 +981,11 @@ private ItemNode resolvePathPrivate( ) } +pragma[nomagic] +private predicate isItemParent(ModuleLikeNode itemParent) { + exists(resolvePathPrivate(_, itemParent, _)) +} + /** * Gets a module that has access to private items defined inside `itemParent`. * @@ -991,7 +996,7 @@ private ItemNode resolvePathPrivate( */ pragma[nomagic] private ModuleLikeNode getAPrivateVisibleModule(ModuleLikeNode itemParent) { - exists(resolvePathPrivate(_, itemParent, _)) and + isItemParent(itemParent) and result.getImmediateParentModule*() = itemParent }