aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2018-04-18 09:48:58 +0200
committerLars Knoll <lars.knoll@qt.io>2018-04-25 14:19:10 +0000
commit0dd479fc8d856b94f3be961364ee1bcacea2c961 (patch)
treeb627e4f7b725687c5e4cc45165ca378d7b624d55
parent4615ffda64f567774264b4b510d9125d2d711718 (diff)
Fix removal of members from the InternalClass
Removing identifiers from the propertyhash could cause subtle issues if there was an identifier that hashed to the same value as the identifier being removed stored in the hash afterwards. This identifier could end up in a state where it could not be found anymore. Amends ea164ca4a8ec1e5c568ab82c0c4256a841f77bf0 Change-Id: I2881865ee83833b6364d9be55579b8fc7d7c5016 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
-rw-r--r--src/qml/jsruntime/qv4internalclass.cpp33
1 files changed, 22 insertions, 11 deletions
diff --git a/src/qml/jsruntime/qv4internalclass.cpp b/src/qml/jsruntime/qv4internalclass.cpp
index a01e42e817..4c7eb7b185 100644
--- a/src/qml/jsruntime/qv4internalclass.cpp
+++ b/src/qml/jsruntime/qv4internalclass.cpp
@@ -88,19 +88,30 @@ void PropertyHash::addEntry(const PropertyHash::Entry &entry, int classSize)
int PropertyHash::removeIdentifier(Identifier *identifier, int classSize)
{
- detach(false, classSize);
- uint idx = identifier->hashValue % d->alloc;
- while (1) {
- if (d->entries[idx].identifier == identifier) {
- int val = d->entries[idx].index;
- d->entries[idx] = { nullptr, 0 };
- return val;
+ int val = -1;
+ PropertyHashData *dd = new PropertyHashData(d->numBits);
+ for (int i = 0; i < d->alloc; ++i) {
+ const Entry &e = d->entries[i];
+ if (!e.identifier || e.index >= static_cast<unsigned>(classSize))
+ continue;
+ if (e.identifier == identifier) {
+ val = e.index;
+ continue;
}
-
- ++idx;
- idx %= d->alloc;
+ uint idx = e.identifier->hashValue % dd->alloc;
+ while (dd->entries[idx].identifier) {
+ ++idx;
+ idx %= dd->alloc;
+ }
+ dd->entries[idx] = e;
}
- Q_UNREACHABLE();
+ dd->size = classSize;
+ if (!--d->refCount)
+ delete d;
+ d = dd;
+
+ Q_ASSERT(val != -1);
+ return val;
}
void PropertyHash::detach(bool grow, int classSize)