diff options
author | Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> | 2021-11-08 22:24:51 +0100 |
---|---|---|
committer | Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> | 2021-11-26 02:14:52 +0100 |
commit | 8c9875893bbd7b1355e36d9501d8cb1f84cb6b4d (patch) | |
tree | c399cd37dbccd0abd9e781b7c410e263f0d8d622 /src/corelib/io/qfsfileengine_p.h | |
parent | 7039fb1e425016ed60383e3752695edbc28a4201 (diff) |
Q(Multi)Map: prevent dangling key/value after detach()
Q(Multi)Map mutating functions that take reference to a key and/or a
value (e.g. insert(), take(), etc.) must make sure that those references
are still valid -- that is, that the referred objects are still alive --
after the detach() call done inside those functions.
In fact, if the key/value are references into *this, one must take extra
steps in order to preserve them across the detach().
Consider the scenario where one has two shallow copies of QMap, each
accessed by a different thread, and each thread calls a mutating
function on its copy, using a reference into the map (e.g.
map.take(map.firstKey())). Let's call the shared payload of this QMap
SP, with its refcount of 2; it's important to note that the argument
(call it A) passed to the mutating function belongs to SP.
Each thread may then find the reference count to be different than 1 and
therefore do a detach() from inside the mutating function. Then this
could happen:
Thread 1: Thread 2:
detach() detach()
SP refcount != 1 => true SP refcount != 1 => true
deep copy from SP deep copy from SP
ref() the new copy ref() the new copy
SP.deref() => 1 => don't dealloc SP
set the new copy as payload
SP.deref() => 0 => dealloc SP
set the new copy as payload
use A to access the new copy use A to access the new copy
The order of ref()/deref() SP and the new copy in each thread doesn't
really matter here. What really matters is that SP has been destroyed
and that means A is a danging reference.
Fix this by keeping SP alive in the mutating functions before doing a
detach(). This can simply be realized by taking a local copy of the map
from within such functions.
remove() doesn't suffer from this because its implementation doesn't do
a bare detach() but something slightly smarter.
Change-Id: Iad974a1ad1bd5ee5d1e9378ae90947bef737b6bb
Pick-to: 6.2
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
Reviewed-by: MÃ¥rten Nordheim <marten.nordheim@qt.io>
Diffstat (limited to 'src/corelib/io/qfsfileengine_p.h')
0 files changed, 0 insertions, 0 deletions