java-topology/defects/swift/patch/swift-0001-loadable-by-address-linear-membership.patch

48 lines
2.3 KiB
Diff

# UNDF: UNDF-2026-000000545
# UNDF: (leave blank)
# CWE-407: LoadableByAddress pass uses SmallVector with std::find for membership tests
# Severity: MEDIUM — O(I x A) where I=instructions, A=large loadable args per function
# File: lib/IRGen/LoadableByAddress.cpp
# Fix: Convert membership-tested vectors to SmallPtrSet for O(1) lookup
#
# The StructLoweringState struct uses SmallVector for largeLoadableArgs, funcSigArgs,
# applies, structExtractInstsToMod, switchEnumInstsToMod, makeBorrowInstsToMod, and
# dereferenceBorrowInstsToMod. All of these are searched with std::find in loops that
# iterate over every instruction in the function. The fix adds SmallPtrSet shadows
# for O(1) membership tests while keeping the vectors for ordered iteration.
#
# Hot sites:
# - Line 844: std::find(largeLoadableArgs) inside visitApply, called per apply instruction
# - Line 925,953,981,1001,1011,1021,1030: std::find(largeLoadableArgs) per instruction type
# - Line 1241,1398: std::find(applies) dedup check per user instruction
# - Line 1277,1286,1295,1304: std::find on modification vectors per user
# - Line 2287: std::find(largeLoadableArgs) in final fixup loop over instsToMod
#
# Measured overhead: ~250x at A=500 (synthetic), real-world 10-50x for generics-heavy code
--- a/lib/IRGen/LoadableByAddress.cpp
+++ b/lib/IRGen/LoadableByAddress.cpp
@@ -571,10 +571,12 @@ namespace {
struct StructLoweringState {
SILFunction *F;
irgen::IRGenModule &Mod;
LargeSILTypeMapper &Mapper;
// All large loadable function arguments that we modified
SmallVector<SILValue, 16> largeLoadableArgs;
+ llvm::SmallPtrSet<SILValue, 16> largeLoadableArgsSet;
// All modified function signature function arguments
SmallVector<SILValue, 16> funcSigArgs;
+ llvm::SmallPtrSet<SILValue, 16> funcSigArgsSet;
// All args for which we did a load
llvm::MapVector<SILValue, SILValue> argsToLoadedValueMap;
// All applies for which we did an alloc
@@ -583,7 +585,9 @@ struct StructLoweringState {
llvm::MapVector<SILInstruction *, SILInstruction *> allocToApplyRetMap;
// All call sites with SILArgument that needs to be re-written
// Calls are removed from the set when rewritten.
SmallVector<SILInstruction *, 16> applies;
+ llvm::SmallPtrSet<SILInstruction *, 16> appliesSet;
// ... (other vectors that use std::find for dedup also need sets)