Open arik-so opened 1 year ago
As of today, it just so happens that we don't have any primitive wrappers being passed as optionals, so we can punt on that for the time being, but we should fix that in the medium term.
If that changes, it could, and very likely will, become a bug.
Swift is very eager to deallocate objects, even before their last use. For example, take this code block in Listen.swift:
Here,
blockPrimitiveWrapper
gets deinit before thelet nativeCallResult = self.cType!.block_connected
call. Presumably Swift simply store the value ofblockPrimitiveWrapper.cType
behind the scenes, and then just passes that. Because a deinit cleans up the contents, it invalidates the cType, and we have an access of deallocated memory.This is only a concern when we instantiate the wrapper inside the method, i. e. it's a concern for all elided types. However, if we then take a look at this method:
We find that we're trying to do a noOpRetain on
firstHopsVector
, which of course we should be doing, but we can't, because its argument was an optional, and it therefore only exists inside theif let
block. Additionally, it doesn't really make a difference because the object was dangled prior to being passed, so whether or not Swift callsdeinit
, nothing actually happens to the underlying C value, and we're safe.However, for the purposes of future-proofing, or if we should choose not to dangle the object, we should instead be able to do a
noOpRetain
on that object, as well. The same applies to tuples, of course.As of today, it just so happens that we don't have any primitive wrappers being passed as optionals, so we can punt on that for the time being, but we should fix that in the medium term.