aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime
diff options
context:
space:
mode:
authorFabian Kosmale <fabian.kosmale@qt.io>2022-10-12 15:54:50 +0200
committerFabian Kosmale <fabian.kosmale@qt.io>2022-10-13 17:27:28 +0000
commit67bb71a051a562da1c778efa6c99cf64922adb80 (patch)
tree38f217f2cdc6dd69c3ae6ab191199ce9f0538959 /src/qml/jsruntime
parent0e963a53c04b0dbe172cfb495b4d62dc8e2f31a3 (diff)
QV4::Scope: Forbid calling alloc with qint64
Calling alloc with a qint64 parameter is a good indicator that we got that value from Object::getLength. In that case, the value needs to be sanitized with safeForAllocLength. As a consequence, we notice that method_stringify did indeed use alloc in an usasafe way; this is now fixed. In a few other places, variables had to be changed from unsigned to signed int (as the conversion is now ambiguous). An even stricter check would be to only accepd a value of (not yet existing) "sanitized_size_t" type. However, that requires more effort, at it would each and every call-site, and is thus left as an exercise for later. Pick-to: 6.4 6.2 5.15 Fixes: QTBUG-107619 Change-Id: I3bba9be1e0aea72e11ccb6c168219b4591eb8f5b Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Diffstat (limited to 'src/qml/jsruntime')
-rw-r--r--src/qml/jsruntime/qv4engine.cpp4
-rw-r--r--src/qml/jsruntime/qv4functionobject.cpp14
-rw-r--r--src/qml/jsruntime/qv4jsonobject.cpp7
-rw-r--r--src/qml/jsruntime/qv4scopedvalue_p.h6
4 files changed, 18 insertions, 13 deletions
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index d54feae1c3..614cd3eef8 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -2003,11 +2003,11 @@ int ExecutionEngine::maxGCStackSize() const
int ExecutionEngine::safeForAllocLength(qint64 len64)
{
if (len64 < 0ll || len64 > qint64(std::numeric_limits<int>::max())) {
- this->throwRangeError(QStringLiteral("Invalid array length."));
+ throwRangeError(QStringLiteral("Invalid array length."));
return 0;
}
if (len64 > qint64(this->jsStackLimit - this->jsStackTop)) {
- this->throwRangeError(QStringLiteral("Array too large for apply()."));
+ throwRangeError(QStringLiteral("Array too large for apply()."));
return 0;
}
return len64;
diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp
index fd0c714060..6cc2ca7ab0 100644
--- a/src/qml/jsruntime/qv4functionobject.cpp
+++ b/src/qml/jsruntime/qv4functionobject.cpp
@@ -348,30 +348,30 @@ ReturnedValue FunctionPrototype::method_apply(const QV4::FunctionObject *b, cons
return v4->throwTypeError();
Scope scope(v4);
- const uint len = v4->safeForAllocLength(arr->getLength());
+ const int len = v4->safeForAllocLength(arr->getLength());
CHECK_EXCEPTION();
Value *arguments = scope.alloc<Scope::Uninitialized>(len);
if (len) {
if (ArgumentsObject::isNonStrictArgumentsObject(arr) && !arr->cast<ArgumentsObject>()->fullyCreated()) {
QV4::ArgumentsObject *a = arr->cast<ArgumentsObject>();
- int l = qMin(len, (uint)a->d()->context->argc());
+ int l = qMin(len, a->d()->context->argc());
memcpy(arguments, a->d()->context->args(), l*sizeof(Value));
- for (quint32 i = l; i < len; ++i)
+ for (int i = l; i < len; ++i)
arguments[i] = Value::undefinedValue();
} else if (arr->arrayType() == Heap::ArrayData::Simple && !arr->protoHasArray()) {
auto sad = static_cast<Heap::SimpleArrayData *>(arr->arrayData());
- uint alen = sad ? sad->values.size : 0;
+ int alen = sad ? sad->values.size : 0;
if (alen > len)
alen = len;
- for (uint i = 0; i < alen; ++i)
+ for (int i = 0; i < alen; ++i)
arguments[i] = sad->data(i);
- for (quint32 i = alen; i < len; ++i)
+ for (int i = alen; i < len; ++i)
arguments[i] = Value::undefinedValue();
} else {
// need to init the arguments array, as the get() calls below can have side effects
memset(arguments, 0, len*sizeof(Value));
- for (quint32 i = 0; i < len; ++i)
+ for (int i = 0; i < len; ++i)
arguments[i] = arr->get(i);
}
}
diff --git a/src/qml/jsruntime/qv4jsonobject.cpp b/src/qml/jsruntime/qv4jsonobject.cpp
index 4643195cfd..6fc854665c 100644
--- a/src/qml/jsruntime/qv4jsonobject.cpp
+++ b/src/qml/jsruntime/qv4jsonobject.cpp
@@ -904,9 +904,10 @@ ReturnedValue JsonObject::method_stringify(const FunctionObject *b, const Value
if (o) {
stringify.replacerFunction = o->as<FunctionObject>();
if (o->isArrayObject()) {
- uint arrayLen = o->getLength();
+ int arrayLen = scope.engine->safeForAllocLength(o->getLength());
+ CHECK_EXCEPTION();
stringify.propertyList = static_cast<QV4::String *>(scope.alloc(arrayLen));
- for (uint i = 0; i < arrayLen; ++i) {
+ for (int i = 0; i < arrayLen; ++i) {
Value *v = stringify.propertyList + i;
*v = o->get(i);
if (v->as<NumberObject>() || v->as<StringObject>() || v->isNumber())
@@ -914,7 +915,7 @@ ReturnedValue JsonObject::method_stringify(const FunctionObject *b, const Value
if (!v->isString()) {
v->setM(nullptr);
} else {
- for (uint j = 0; j <i; ++j) {
+ for (int j = 0; j <i; ++j) {
if (stringify.propertyList[j].m() == v->m()) {
v->setM(nullptr);
break;
diff --git a/src/qml/jsruntime/qv4scopedvalue_p.h b/src/qml/jsruntime/qv4scopedvalue_p.h
index fd68fcc1b3..ddd312b893 100644
--- a/src/qml/jsruntime/qv4scopedvalue_p.h
+++ b/src/qml/jsruntime/qv4scopedvalue_p.h
@@ -93,6 +93,10 @@ struct Scope {
/* Be careful when using Uninitialized, the stack has to be fully initialized before calling into the memory manager again */
Uninitialized
};
+
+ template <AllocMode mode = Undefined>
+ Value *alloc(qint64 nValues) const = delete; // use safeForAllocLength
+
template <AllocMode mode = Undefined>
QML_NEARLY_ALWAYS_INLINE Value *alloc(int nValues) const
{
@@ -413,7 +417,7 @@ struct ScopedProperty
{
ScopedProperty(Scope &scope)
{
- property = reinterpret_cast<Property*>(scope.alloc(sizeof(Property) / sizeof(Value)));
+ property = reinterpret_cast<Property*>(scope.alloc(int(sizeof(Property) / sizeof(Value))));
}
Property *operator->() { return property; }