Mutate value type function result directly, not a CoW copy

I'm investigating doing something like SecureString on .NET and use an API to encrypt and decrypt the in memory representation of sensitive data, but also doing something about in-memory copies made during either end of that process, zeroing them out afterwards.

My general question: if calling a function that returns a Swift value type, will there be any way to mutate that value directly, or will any mutation done to the result invariantly cause a CoW? It seems to me that Swift's data safety would prevent mutating the result.

For example, if I'm using an library's decrypt function that returns Data will this do what I'm intending:

var decrypted: Data = decrypt(blah)
// do something with decrypted data
decrypted.replaceSubrange(...) // wipe bytes in memory

or will the call to replaceSubrange be modifying a CoW copy of the original immutable result of decrypt(), leaving that original behind in memory after all?

Could some extension on Data allow me to break the memory safety and mutate the function result itself, zeroing its contents after I'm done?

Copy-on-write will only actually copy the memory if you are writing via a non-unique reference. If you have a unique reference to the memory, changes are not visible to anybody else, so the mutation can happen in-place.

In your example, if decrypted escapes the function within the "do something" region, that escaped version will not see the result of the replaceSubrange call. replaceSubrange will realise that it doesn't have a unique reference to the memory, allocate and copy to new storage, then operate on that fresh copy.

Swift doesn't have a way to enforce that a value does not escape - i.e. that no additional references to it are formed. AFAIK non-copyable types are part of the ownership manifesto, though, so they are on the radar.

1 Like

Yes this makes sense. Thanks for the refresher!