QHash: only fetch qt_qhash_seed when detaching from a null QHash

The old code fetched QHashData::seed from qt_qhash_seed on every detach.

That is both unnecessary and wrong.

It is uneccessary, because if the detached-from QHashData isn't shared_null,
the seed has already been populated from qt_qhash_seed. It thus suffices to
fetch the seed from qt_qhash_seed only when we detach from shared_null.

It is wrong, because if qt_qhash_seed was changed between the detach from
shared_null and a following detach, d->seed is now different from this->seed,
but detach_helper simply clones the buckets 1:1 from this to d, leaving d
in a corrupt state.

By doing this change, we make QHash robust against on-the-fly changes
to qt_qhash_seed (e.g. for testing, or added security). It also opens up the
option to have API for changing the seed of a given QHash instance after it
has been created (detach, set new seed, rehash).

Change-Id: Ib251fc9a6204b42036e97a2fc66f644b379ab841
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Marc Mutz 2015-01-08 21:26:08 +01:00 committed by Thiago Macieira
parent 9d46189a64
commit 3d8a10b960

View File

@ -418,7 +418,7 @@ QHashData *QHashData::detach_helper(void (*node_duplicate)(Node *, void *),
Node *e;
};
if (this == &shared_null)
qt_initialize_qhash_seed();
qt_initialize_qhash_seed(); // may throw
d = new QHashData;
d->fakeNext = 0;
d->buckets = 0;
@ -428,7 +428,7 @@ QHashData *QHashData::detach_helper(void (*node_duplicate)(Node *, void *),
d->userNumBits = userNumBits;
d->numBits = numBits;
d->numBuckets = numBuckets;
d->seed = uint(qt_qhash_seed.load());
d->seed = (this == &shared_null) ? uint(qt_qhash_seed.load()) : seed;
d->sharable = true;
d->strictAlignment = nodeAlign > 8;
d->reserved = 0;