[SR-14424] Small strings don't play well with 'init(unsafeUninitializedCapacity:initializingWith:)' #56780
Labels
bug
A deviation from expected or documented behavior. Also: expected but undesirable behavior.
standard library
Area: Standard library umbrella
Additional Detail from JIRA
md5: 39168a2f7392a285b9cb9a4f674f7768
Issue Description:
The
unsafeUninitializedCapacity
initializer requires users to return the initialized count and to leave the remaining bytes uninitialized. This is what's happening here. To wit:Bytes are written from the end of the buffer towards the start as the string representation is being built up.
Once the final byte sequence for the string has been obtained, it is move-initialized to the start of the buffer (as per discussions on the forums, it is permitted to use
moveInitialize
with overlapping source and destination in this way).This leaves the unused bytes uninitialized, as required by the documentation.
All of this works perfectly when the string isn't small. Digging through the sources, I understand that a
_SmallString
's buffer is backed by a tuple of(UInt64, UInt64)
. Although unused bytes are deinitialized here, they aren't zero immediately prior to deinitialization.It should be the job of
_SmallString
to initialize unused bytes to zero before rebinding the buffer to its original type. (In fact, isn't it undefined behavior to rebind memory and read from it after it's been deinitialized?)The user can't leave the unused capacity zero-initialized themselves after using it because (a) that may not be what a non-small string expects; and (b) the documentation tells the user that they must leave the unused capacity uninitialized.
AFAICT, to fix this bug, it's just a matter of writing
(rawPtr + initializedCount).initialize(repeating: 0, count: unusedCapacity)
before rebinding the memory to the type ofself._storage
.The text was updated successfully, but these errors were encountered: