summaryrefslogtreecommitdiffstats
path: root/src/corelib/io/qfsfileengine_p.h
diff options
context:
space:
mode:
authorGiuseppe D'Angelo <giuseppe.dangelo@kdab.com>2021-11-08 22:24:51 +0100
committerGiuseppe D'Angelo <giuseppe.dangelo@kdab.com>2021-11-26 02:14:52 +0100
commit8c9875893bbd7b1355e36d9501d8cb1f84cb6b4d (patch)
treec399cd37dbccd0abd9e781b7c410e263f0d8d622 /src/corelib/io/qfsfileengine_p.h
parent7039fb1e425016ed60383e3752695edbc28a4201 (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