Skip to content

Commit 50195e7

Browse files
committed
libswift: fix a few bugs in StackList
Use MemoryLayout.stride instead pf MemoryLayout.size. This fixes a buffer overflow bug in case of unaligned elements. Plus some other bug fixes for stacklists which get larger than a single slab. Also, add the `append(contentsOf:)` method.
1 parent 17d3335 commit 50195e7

File tree

2 files changed

+23
-19
lines changed

2 files changed

+23
-19
lines changed

lib/SILOptimizer/PassManager/PassManager.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1096,7 +1096,11 @@ FixedSizeSlab *LibswiftPassInvocation::allocSlab(FixedSizeSlab *afterSlab) {
10961096
}
10971097

10981098
FixedSizeSlab *LibswiftPassInvocation::freeSlab(FixedSizeSlab *slab) {
1099-
FixedSizeSlab *prev = std::prev(&*slab->getIterator());
1099+
FixedSizeSlab *prev = nullptr;
1100+
assert(!allocatedSlabs.empty());
1101+
if (&allocatedSlabs.front() != slab)
1102+
prev = &*std::prev(slab->getIterator());
1103+
11001104
allocatedSlabs.remove(*slab);
11011105
passManager->getModule()->freeSlab(slab);
11021106
return prev;

libswift/Sources/SIL/StackList.swift

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,10 @@ public struct StackList<Element> : Sequence, CustomReflectable {
2929
private let context: BridgedPassContext
3030
private var firstSlab = BridgedSlab(data: nil)
3131
private var lastSlab = BridgedSlab(data: nil)
32-
private var endIndex: Int = slabCapacity
32+
private var endIndex: Int = 0
3333

3434
private static var slabCapacity: Int {
35-
BridgedSlabCapacity / MemoryLayout<Element>.size
35+
BridgedSlabCapacity / MemoryLayout<Element>.stride
3636
}
3737

3838
private static func bind(_ slab: BridgedSlab) -> UnsafeMutablePointer<Element> {
@@ -84,16 +84,24 @@ public struct StackList<Element> : Sequence, CustomReflectable {
8484
public mutating func push(_ element: Element) {
8585
if endIndex >= StackList.slabCapacity {
8686
lastSlab = PassContext_allocSlab(context, lastSlab)
87-
if firstSlab.data == nil {
88-
firstSlab = lastSlab
89-
}
9087
endIndex = 0
88+
} else if firstSlab.data == nil {
89+
assert(endIndex == 0)
90+
firstSlab = PassContext_allocSlab(context, lastSlab)
91+
lastSlab = firstSlab
9192
}
9293
(StackList.bind(lastSlab) + endIndex).initialize(to: element)
9394
endIndex += 1
9495
}
95-
96-
public var isEmpty: Bool { return firstSlab.data == nil }
96+
97+
public mutating
98+
func append<S: Sequence>(contentsOf other: S) where S.Element == Element {
99+
for elem in other {
100+
push(elem)
101+
}
102+
}
103+
104+
public var isEmpty: Bool { return endIndex == 0 }
97105

98106
public mutating func pop() -> Element? {
99107
if isEmpty {
@@ -108,26 +116,18 @@ public struct StackList<Element> : Sequence, CustomReflectable {
108116
_ = PassContext_freeSlab(context, lastSlab)
109117
firstSlab.data = nil
110118
lastSlab.data = nil
119+
endIndex = 0
111120
} else {
112121
lastSlab = PassContext_freeSlab(context, lastSlab)
122+
endIndex = StackList.slabCapacity
113123
}
114-
endIndex = StackList.slabCapacity
115124
}
116125

117126
return elem
118127
}
119128

120129
public mutating func removeAll() {
121-
if isEmpty {
122-
return
123-
}
124-
while lastSlab.data != firstSlab.data {
125-
lastSlab = PassContext_freeSlab(context, lastSlab)
126-
}
127-
_ = PassContext_freeSlab(context, lastSlab)
128-
firstSlab.data = nil
129-
lastSlab.data = nil
130-
endIndex = StackList.slabCapacity
130+
while pop() != nil { }
131131
}
132132

133133
public var customMirror: Mirror {

0 commit comments

Comments
 (0)