5 ms·
"The type whose thread safety is in question here is not actually String, but char[]" Not quite, it is String constructor that has the race condition, char arr
by sorokod 3y ago
"The type whose thread safety is in question here is not actually String, but char[]"
Not quite, it is String constructor that has the race condition, char array is incidental there.
- sk5t 3y agoI wouldn’t point the finger at the ctor; making a defensive deep copy of mutable parameters is not in the contract.
- bonzini 3y agoThe thread-safety guarantees can only be obeyed if the arguments are thread-safe as well. For example, take a java.util.concurrent.ConcurrentHashMap, which is thread-safe. If your value object is mutated concurrently, and is not thread-safe, you can't expect anything sensible to happen if you call containsValue(). Likewise, String's char[] constructor can only be thread safe if there are no concurrent changes to the argument.
- masklinn 3y ago> The thread-safety guarantees can only be obeyed if the arguments are thread-safe as well. While that’s generally true it’s not the case here, char[] does not invalidate anything upon mutation it just changes. The issue is that the ctor checks for a property (all chars are under 256) then assumes that holds indefinitely.
- friendzis 3y ago> The issue is that the ctor checks for a property (all chars are under 256) then assumes that holds indefinitely. You could say that this is a classical TOCTOU bug as the ctor assumes that a mutable argument does not mutate. The core question[s] here are whether this assumption is and should be in the contract. Protection against these kinds of bugs is only possible with deep copies of mutable arguments or COW semantics. So you either implement callee defensively and slow down general case (remember, this is stdlib), or you leave concurrency control to the caller. Probably every sane general purpose language does the latter.
- masklinn 3y ago> You could say that this is a classical TOCTOU bug as the ctor assumes that a mutable argument does not mutate. Indeed. > Protection against these kinds of bugs is only possible with deep copies of mutable arguments or COW semantics. In the general case yes, but in this case no, you can solve the issue and improve performances by implementing the thing correctly, in a single pass over the input. This way you don’t get a split-brain situation.