Skip to content

Commit 9d03d90

Browse files
authored
#120 Ensure concurrent access to AsyncBufferedByteIterator does not crash from dangling pointers (#121)
1 parent c174e46 commit 9d03d90

File tree

1 file changed

+18
-0
lines changed

1 file changed

+18
-0
lines changed

Sources/AsyncAlgorithms/AsyncBufferedByteIterator.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,24 @@ internal struct _AsyncBytesBuffer: @unchecked Sendable {
110110
}
111111
try Task.checkCancellation()
112112
do {
113+
// If two tasks have access to this iterator then the references on
114+
// the storage will be non uniquely owned. This means that any reload
115+
// must happen into it's own fresh buffer. The consumption of those
116+
// bytes between two tasks are inherently defined as potential
117+
// duplication by the nature of sending that buffer across the two
118+
// tasks - this means that the brief period in which they may be
119+
// sharing non reloaded bytes is to be expected; basically in that
120+
// edge case of making the iterator and sending that across to two
121+
// places to iterate is asking for something bizzare and the answer
122+
// should not be crash, but it definitely cannot be consistent.
123+
//
124+
// The unique ref check is here to prevent the potentials of a crashing
125+
// secnario.
126+
if !isKnownUniquelyReferenced(&storage) {
127+
// The count is not mutated across invocations so the access is safe.
128+
let capacity = storage.buffer.count
129+
storage = Storage(capacity: capacity)
130+
}
113131
let readSize: Int = try await readFunction(storage.buffer)
114132
if readSize == 0 {
115133
finished = true

0 commit comments

Comments
 (0)