From 1e18f2c4a647923fc66a3e3204fcccd88a2960a6 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Tue, 26 Mar 2019 09:40:03 +0100 Subject: Check for numeric limits when growing SharedInternalClassDataPrivate We can effectively only deal with values of < 2GB for m_alloc * sizeof(Data). This is not much more than the values seen in the wild. Change-Id: Ia6972df33d34a320b5b087d38db81aae24ce5bbe Reviewed-by: Lars Knoll --- src/qml/jsruntime/qv4memberdata.cpp | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) (limited to 'src/qml/jsruntime/qv4memberdata.cpp') diff --git a/src/qml/jsruntime/qv4memberdata.cpp b/src/qml/jsruntime/qv4memberdata.cpp index 246f857643..f327c85001 100644 --- a/src/qml/jsruntime/qv4memberdata.cpp +++ b/src/qml/jsruntime/qv4memberdata.cpp @@ -69,12 +69,25 @@ Heap::MemberData *MemberData::allocate(ExecutionEngine *e, uint n, Heap::MemberD size_t alloc = MemoryManager::align(sizeof(Heap::MemberData) + (n - 1)*sizeof(Value)); // round up to next power of two to avoid quadratic behaviour for very large objects alloc = nextPowerOfTwo(alloc); - Heap::MemberData *m = e->memoryManager->allocManaged(alloc); - if (old) + + // The above code can overflow in a number of interesting ways. All of those are unsigned, + // and therefore defined behavior. Still, apply some sane bounds. + if (alloc > std::numeric_limits::max()) + alloc = std::numeric_limits::max(); + + Heap::MemberData *m; + if (old) { + const size_t oldSize = sizeof(Heap::MemberData) + (old->values.size - 1) * sizeof(Value); + if (oldSize > alloc) + alloc = oldSize; + m = e->memoryManager->allocManaged(alloc); // no write barrier required here - memcpy(m, old, sizeof(Heap::MemberData) + (old->values.size - 1) * sizeof(Value)); - else + memcpy(m, old, oldSize); + } else { + m = e->memoryManager->allocManaged(alloc); m->init(); + } + m->values.alloc = static_cast((alloc - sizeof(Heap::MemberData) + sizeof(Value))/sizeof(Value)); m->values.size = m->values.alloc; return m; -- cgit v1.2.3