diff options
author | Erik Verbruggen <erik.verbruggen@theqtcompany.com> | 2016-05-26 17:46:24 +0200 |
---|---|---|
committer | Erik Verbruggen <erik.verbruggen@qt.io> | 2016-06-08 08:04:53 +0000 |
commit | ce0800060246e68fffc226b366cb4b0ea2e41ded (patch) | |
tree | 1a79104c19a84611d3207456438b4054703f2f56 | |
parent | fc83d811812d2e16f4139f6db7e357b5d2eb945b (diff) |
V4: tighten up various casts to check also check type.
All those type conversions assumed that the content of a Value was
either the requested type, or 0 (zero, a null pointer). Now, attempting
to convert e.g. undefined to a string will fail, instead of returning a
weird address.
Change-Id: I0f567cdcc9cc9728d019f17693f4a6007394a9c6
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
-rw-r--r-- | src/qml/jsruntime/qv4persistent_p.h | 4 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4value_p.h | 13 | ||||
-rw-r--r-- | src/qml/memory/qv4mm.cpp | 5 |
3 files changed, 16 insertions, 6 deletions
diff --git a/src/qml/jsruntime/qv4persistent_p.h b/src/qml/jsruntime/qv4persistent_p.h index 5b1926468a..a0ade2068f 100644 --- a/src/qml/jsruntime/qv4persistent_p.h +++ b/src/qml/jsruntime/qv4persistent_p.h @@ -118,7 +118,7 @@ public: Managed *asManaged() const { if (!val) return 0; - return val->as<Managed>(); + return val->managed(); } template<typename T> T *as() const { @@ -167,7 +167,7 @@ public: Managed *asManaged() const { if (!val) return 0; - return val->as<Managed>(); + return val->managed(); } template <typename T> T *as() const { diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h index a8d9b0fa71..f99e24c6e9 100644 --- a/src/qml/jsruntime/qv4value_p.h +++ b/src/qml/jsruntime/qv4value_p.h @@ -286,16 +286,22 @@ struct Q_QML_PRIVATE_EXPORT Value } Q_ALWAYS_INLINE String *stringValue() const { + if (!isString()) + return nullptr; return m() ? reinterpret_cast<String*>(const_cast<Value *>(this)) : 0; } Q_ALWAYS_INLINE Object *objectValue() const { + if (!isObject()) + return nullptr; return m() ? reinterpret_cast<Object*>(const_cast<Value *>(this)) : 0; } Q_ALWAYS_INLINE Managed *managed() const { + if (!isManaged()) + return nullptr; return m() ? reinterpret_cast<Managed*>(const_cast<Value *>(this)) : 0; } Q_ALWAYS_INLINE Heap::Base *heapObject() const { - return m(); + return isManaged() ? m() : nullptr; } Q_ALWAYS_INLINE quint64 &rawValueRef() { @@ -357,7 +363,10 @@ struct Q_QML_PRIVATE_EXPORT Value } template <typename T> T *as() { - return const_cast<T *>(const_cast<const Value *>(this)->as<T>()); + if (isManaged()) + return const_cast<T *>(const_cast<const Value *>(this)->as<T>()); + else + return nullptr; } template<typename T> inline T *cast() { diff --git a/src/qml/memory/qv4mm.cpp b/src/qml/memory/qv4mm.cpp index 4fb2acebc5..226358074b 100644 --- a/src/qml/memory/qv4mm.cpp +++ b/src/qml/memory/qv4mm.cpp @@ -382,6 +382,7 @@ static void drainMarkStack(QV4::ExecutionEngine *engine, Value *markBase) { while (engine->jsStackTop > markBase) { Heap::Base *h = engine->popForGC(); + Q_ASSERT(h); // at this point we should only have Heap::Base objects in this area on the stack. If not, weird things might happen. Q_ASSERT (h->vtable()->markObjects); h->vtable()->markObjects(h, engine); } @@ -438,7 +439,7 @@ void MemoryManager::sweep(bool lastSweep) for (PersistentValueStorage::Iterator it = m_weakValues->begin(); it != m_weakValues->end(); ++it) { if (!(*it).isManaged()) continue; - Managed *m = (*it).as<Managed>(); + Managed *m = (*it).managed(); if (m->markBit()) continue; // we need to call detroyObject on qobjectwrappers now, so that they can emit the destroyed @@ -676,7 +677,7 @@ void MemoryManager::collectFromJSStack() const Value *v = engine->jsStackBase; Value *top = engine->jsStackTop; while (v < top) { - Managed *m = v->as<Managed>(); + Managed *m = v->managed(); if (m && m->inUse()) // Skip pointers to already freed objects, they are bogus as well m->mark(engine); |