diff options
author | Lars Knoll <lars.knoll@qt.io> | 2018-08-10 18:01:54 +0200 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2018-08-23 08:13:11 +0000 |
commit | 653d5aa353f70e86d0b9a575435121c4a23184a4 (patch) | |
tree | dd9d550c6a860e30d6be8256341ba7222824b460 /src/qml/jsruntime/qv4dataview.cpp | |
parent | b8009a27242920f40ce9361c0aec619cca864c64 (diff) |
Fix DataView constructor to be spec compliant
Change-Id: I312f8e086b733e184b353d77452f5d4a1262469a
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/qml/jsruntime/qv4dataview.cpp')
-rw-r--r-- | src/qml/jsruntime/qv4dataview.cpp | 62 |
1 files changed, 35 insertions, 27 deletions
diff --git a/src/qml/jsruntime/qv4dataview.cpp b/src/qml/jsruntime/qv4dataview.cpp index 1a0503dded..3f0e2fd1a7 100644 --- a/src/qml/jsruntime/qv4dataview.cpp +++ b/src/qml/jsruntime/qv4dataview.cpp @@ -55,31 +55,56 @@ void Heap::DataViewCtor::init(QV4::ExecutionContext *scope) Heap::FunctionObject::init(scope, QStringLiteral("DataView")); } -ReturnedValue DataViewCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *) +static uint toIndex(ExecutionEngine *e, const Value &v) +{ + if (v.isUndefined()) + return 0; + double index = v.toInteger(); + if (index < 0) { + e->throwRangeError(QStringLiteral("index out of range")); + return 0; + } + uint idx = static_cast<uint>(index); + if (idx != index) { + e->throwRangeError(QStringLiteral("index out of range")); + return 0; + } + return idx; +} + +ReturnedValue DataViewCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *newTarget) { Scope scope(f->engine()); Scoped<ArrayBuffer> buffer(scope, argc ? argv[0] : Primitive::undefinedValue()); - if (!buffer || buffer->isDetachedBuffer()) + if (!newTarget || !buffer) + return scope.engine->throwTypeError(); + + uint offset = ::toIndex(scope.engine, argc > 1 ? argv[1]: Primitive::undefinedValue()); + if (scope.hasException()) + return Encode::undefined(); + if (buffer->isDetachedBuffer()) return scope.engine->throwTypeError(); - double bo = argc > 1 ? argv[1].toNumber() : 0; - uint byteOffset = (uint)bo; uint bufferLength = buffer->d()->data->size; - double bl = argc < 3 || argv[2].isUndefined() ? (bufferLength - bo) : argv[2].toNumber(); - uint byteLength = (uint)bl; - if (bo != byteOffset || bl != byteLength || byteOffset + byteLength > bufferLength) + if (offset > bufferLength) + return scope.engine->throwRangeError(QStringLiteral("DataView: constructor arguments out of range")); + + uint byteLength = (argc < 3 || argv[2].isUndefined()) ? (bufferLength - offset) : ::toIndex(scope.engine, argv[2]); + if (scope.hasException()) + return Encode::undefined(); + if (offset + byteLength > bufferLength) return scope.engine->throwRangeError(QStringLiteral("DataView: constructor arguments out of range")); Scoped<DataView> a(scope, scope.engine->memoryManager->allocate<DataView>()); a->d()->buffer.set(scope.engine, buffer->d()); a->d()->byteLength = byteLength; - a->d()->byteOffset = byteOffset; + a->d()->byteOffset = offset; return a.asReturnedValue(); } -ReturnedValue DataViewCtor::virtualCall(const FunctionObject *f, const Value *, const Value *argv, int argc) +ReturnedValue DataViewCtor::virtualCall(const FunctionObject *f, const Value *, const Value *, int) { - return virtualCallAsConstructor(f, argv, argc, f); + return f->engine()->throwTypeError(); } void DataViewPrototype::init(ExecutionEngine *engine, Object *ctor) @@ -123,23 +148,6 @@ void DataViewPrototype::init(ExecutionEngine *engine, Object *ctor) defineDefaultProperty(QStringLiteral("setUInt32"), method_set<unsigned int>, 1); } -static uint toIndex(ExecutionEngine *e, const Value &v) -{ - if (v.isUndefined()) - return 0; - double index = v.toInteger(); - if (index < 0) { - e->throwRangeError(QStringLiteral("index out of range")); - return 0; - } - uint idx = static_cast<uint>(index); - if (idx != index) { - e->throwRangeError(QStringLiteral("index out of range")); - return 0; - } - return idx; -} - ReturnedValue DataViewPrototype::method_get_buffer(const FunctionObject *b, const Value *thisObject, const Value *, int) { const DataView *v = thisObject->as<DataView>(); |