Skip to content

Commit 93e3bac

Browse files
authored
(144909030) FSR writes bytes to end of buffer even on success cases (#1199)
1 parent 601e847 commit 93e3bac

File tree

1 file changed

+14
-6
lines changed

1 file changed

+14
-6
lines changed

Sources/FoundationEssentials/String/String+Internals.swift

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,16 @@ extension UnsafeBufferPointer {
233233
if nullTerminated {
234234
// Ensure buffer is always null-terminated even on failure to prevent buffer over-reads
235235
// At this point, the buffer is known to be non-empty, so it must have space for at least a null terminating byte (even if it overwrites the final output byte in the buffer)
236-
buffer[buffer.count - 1] = 0
236+
if bufferIdx < bufferLength {
237+
// We still have space left in the buffer - if we haven't already null-terminated then add a null byte to the buffer
238+
// Since we have space, we only want to write the null byte when/where we have to since some clients provide buffer sizes that don't match the true buffer length
239+
if bufferIdx == buffer.startIndex || buffer[bufferIdx - 1] != 0 {
240+
buffer[bufferIdx] = 0
241+
}
242+
} else {
243+
// The buffer is non-empty but we've completely filled it, overwrite the last written byte with a null byte to ensure null termination
244+
buffer[buffer.count - 1] = 0
245+
}
237246
}
238247
}
239248

@@ -347,21 +356,20 @@ extension NSString {
347356
} else if self.fastestEncoding == NSASCIIStringEncoding, let fastUTF8 = self._fastCStringContents(false) {
348357
// If we have quick access to ASCII contents, no need to decompose
349358
let utf8Buffer = UnsafeBufferPointer(start: fastUTF8, count: self.length)
350-
defer {
351-
// Ensure buffer is always null-terminated even on failure to prevent buffer over-reads
352-
// At this point, the buffer is known to be non-empty, so it must have space for at least a null terminating byte (even if it overwrites the final output byte in the buffer)
353-
buffer[buffer.count - 1] = 0
354-
}
355359

356360
// We only allow embedded nulls if there are no non-null characters following the first null character
357361
if let embeddedNullIdx = utf8Buffer.firstIndex(of: 0) {
358362
if !utf8Buffer[embeddedNullIdx...].allSatisfy({ $0 == 0 }) {
363+
// Ensure the buffer is always null-terminated even on failure to prevent buffer over-reads - at this point we know the buffer is non-empty
364+
buffer[0] = 0
359365
return false
360366
}
361367
}
362368

363369
var (leftoverIterator, next) = buffer.initialize(from: utf8Buffer)
364370
guard leftoverIterator.next() == nil && next < buffer.endIndex else {
371+
// Ensure the buffer is always null-terminated even on failure to prevent buffer over-reads
372+
buffer[buffer.endIndex - 1] = 0
365373
return false
366374
}
367375
buffer[next] = 0

0 commit comments

Comments
 (0)