From 28438d66b1a5e31f25b085cf6bda2fc6fbeefe93 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 9 Jul 2014 10:27:23 -0700 Subject: [PATCH] Fixed exceptions/endian issues with DataViews --- libraries/script-engine/src/DataViewClass.cpp | 23 ++++++- libraries/script-engine/src/DataViewClass.h | 2 +- .../script-engine/src/DataViewPrototype.cpp | 64 ++++++++++++++----- 3 files changed, 68 insertions(+), 21 deletions(-) diff --git a/libraries/script-engine/src/DataViewClass.cpp b/libraries/script-engine/src/DataViewClass.cpp index 7afd43e71c..38a85e55a8 100644 --- a/libraries/script-engine/src/DataViewClass.cpp +++ b/libraries/script-engine/src/DataViewClass.cpp @@ -54,15 +54,32 @@ QScriptValue DataViewClass::construct(QScriptContext *context, QScriptEngine *en } QScriptValue bufferArg = context->argument(0); - QScriptValue byteOffsetArg = (context->argumentCount() >= 2) ? context->argument(1) : QScriptValue(-1); - QScriptValue byteLengthArg = (context->argumentCount() >= 3) ? context->argument(2) : QScriptValue(-1); + QScriptValue byteOffsetArg = (context->argumentCount() >= 2) ? context->argument(1) : QScriptValue(); + QScriptValue byteLengthArg = (context->argumentCount() >= 3) ? context->argument(2) : QScriptValue(); QByteArray* arrayBuffer = (bufferArg.isValid()) ? qscriptvalue_cast(bufferArg.data()) :NULL; if (!arrayBuffer) { + engine->evaluate("throw \"TypeError: 1st argument not a ArrayBuffer\""); return QScriptValue(); } + if (byteOffsetArg.isNumber() && + (byteOffsetArg.toInt32() < 0 || + byteOffsetArg.toInt32() >= arrayBuffer->size())) { + engine->evaluate("throw \"RangeError: byteOffset out of range\""); + return QScriptValue(); + } + if (byteLengthArg.isNumber() && + (byteLengthArg.toInt32() < 0 || + byteOffsetArg.toInt32() + byteLengthArg.toInt32() > arrayBuffer->size())) { + engine->evaluate("throw \"RangeError: byteLength out of range\""); + return QScriptValue(); + } - QScriptValue newObject = cls->newInstance(bufferArg, byteOffsetArg.toInt32(), byteLengthArg.toInt32()); + QScriptValue newObject = cls->newInstance(bufferArg, + (byteOffsetArg.isNumber()) ? byteOffsetArg.toInt32() + : 0, + (byteLengthArg.isNumber()) ? byteLengthArg.toInt32() + : arrayBuffer->size()); if (context->isCalledAsConstructor()) { context->setThisObject(newObject); diff --git a/libraries/script-engine/src/DataViewClass.h b/libraries/script-engine/src/DataViewClass.h index 7e4d427f09..6b6d6d25e7 100644 --- a/libraries/script-engine/src/DataViewClass.h +++ b/libraries/script-engine/src/DataViewClass.h @@ -18,7 +18,7 @@ class DataViewClass : public ArrayBufferViewClass { Q_OBJECT public: DataViewClass(QScriptEngine* engine); - QScriptValue newInstance(QScriptValue buffer, quint32 byteOffset = -1, quint32 byteLength = -1); + QScriptValue newInstance(QScriptValue buffer, quint32 byteOffset, quint32 byteLength); QString name() const; QScriptValue prototype() const; diff --git a/libraries/script-engine/src/DataViewPrototype.cpp b/libraries/script-engine/src/DataViewPrototype.cpp index 2965f98809..17734e109c 100644 --- a/libraries/script-engine/src/DataViewPrototype.cpp +++ b/libraries/script-engine/src/DataViewPrototype.cpp @@ -29,10 +29,10 @@ QByteArray* DataViewPrototype::thisArrayBuffer() const { bool DataViewPrototype::realOffset(quint32& offset, size_t size) const { quint32 viewOffset = thisObject().data().property(BYTE_OFFSET_PROPERTY_NAME).toInt32(); quint32 viewLength = thisObject().data().property(BYTE_LENGTH_PROPERTY_NAME).toInt32(); - qDebug() << "View Offset: " << viewOffset << ", View Lenght: " << viewLength; - qDebug() << "Offset: " << offset << ", Size: " << size; + //qDebug() << "View Offset: " << viewOffset << ", View Lenght: " << viewLength; + //qDebug() << "Offset: " << offset << ", Size: " << size; offset += viewOffset; - qDebug() << "New offset: " << offset << ", bool: " << ((offset + size) <= viewOffset + viewLength); + //qDebug() << "New offset: " << offset << ", bool: " << ((offset + size) <= viewOffset + viewLength); return (offset + size) <= viewOffset + viewLength; } @@ -47,7 +47,8 @@ qint32 DataViewPrototype::getInt8(quint32 byteOffset) { stream >> result; return result; } - return 42; + thisObject().engine()->evaluate("throw \"RangeError: byteOffset out of range\""); + return 0; } quint32 DataViewPrototype::getUint8(quint32 byteOffset) { @@ -59,85 +60,92 @@ quint32 DataViewPrototype::getUint8(quint32 byteOffset) { stream >> result; return result; } - return 42; + thisObject().engine()->evaluate("throw \"RangeError: byteOffset out of range\""); + return 0; } qint32 DataViewPrototype::getInt16(quint32 byteOffset, bool littleEndian) { if (realOffset(byteOffset, sizeof(qint16))) { QDataStream stream(*thisArrayBuffer()); - stream.setByteOrder((littleEndian) ? QDataStream::LittleEndian : QDataStream::BigEndian); stream.skipRawData(byteOffset); + stream.setByteOrder((littleEndian) ? QDataStream::LittleEndian : QDataStream::BigEndian); qint16 result; stream >> result; return result; } - return 42; + thisObject().engine()->evaluate("throw \"RangeError: byteOffset out of range\""); + return 0; } quint32 DataViewPrototype::getUint16(quint32 byteOffset, bool littleEndian) { if (realOffset(byteOffset, sizeof(quint16))) { QDataStream stream(*thisArrayBuffer()); - stream.setByteOrder((littleEndian) ? QDataStream::LittleEndian : QDataStream::BigEndian); stream.skipRawData(byteOffset); + stream.setByteOrder((littleEndian) ? QDataStream::LittleEndian : QDataStream::BigEndian); quint16 result; stream >> result; return result; } - return 42; + thisObject().engine()->evaluate("throw \"RangeError: byteOffset out of range\""); + return 0; } qint32 DataViewPrototype::getInt32(quint32 byteOffset, bool littleEndian) { if (realOffset(byteOffset, sizeof(qint32))) { QDataStream stream(*thisArrayBuffer()); - stream.setByteOrder((littleEndian) ? QDataStream::LittleEndian : QDataStream::BigEndian); stream.skipRawData(byteOffset); + stream.setByteOrder((littleEndian) ? QDataStream::LittleEndian : QDataStream::BigEndian); qint32 result; stream >> result; return result; } - return 42; + thisObject().engine()->evaluate("throw \"RangeError: byteOffset out of range\""); + return 0; } quint32 DataViewPrototype::getUint32(quint32 byteOffset, bool littleEndian) { if (realOffset(byteOffset, sizeof(quint32))) { QDataStream stream(*thisArrayBuffer()); - stream.setByteOrder((littleEndian) ? QDataStream::LittleEndian : QDataStream::BigEndian); stream.skipRawData(byteOffset); + stream.setByteOrder((littleEndian) ? QDataStream::LittleEndian : QDataStream::BigEndian); quint32 result; stream >> result; return result; } - return 42; + thisObject().engine()->evaluate("throw \"RangeError: byteOffset out of range\""); + return 0; } float DataViewPrototype::getFloat32(quint32 byteOffset, bool littleEndian) { if (realOffset(byteOffset, sizeof(float))) { QDataStream stream(*thisArrayBuffer()); - stream.setByteOrder((littleEndian) ? QDataStream::LittleEndian : QDataStream::BigEndian); stream.skipRawData(byteOffset); + stream.setByteOrder((littleEndian) ? QDataStream::LittleEndian : QDataStream::BigEndian); float result; stream >> result; return result; } - return 42; + thisObject().engine()->evaluate("throw \"RangeError: byteOffset out of range\""); + return 0; } double DataViewPrototype::getFloat64(quint32 byteOffset, bool littleEndian) { if (realOffset(byteOffset, sizeof(double))) { QDataStream stream(*thisArrayBuffer()); - stream.setByteOrder((littleEndian) ? QDataStream::LittleEndian : QDataStream::BigEndian); stream.skipRawData(byteOffset); + stream.setByteOrder((littleEndian) ? QDataStream::LittleEndian : QDataStream::BigEndian); double result; stream >> result; return result; } - return 42; + thisObject().engine()->evaluate("throw \"RangeError: byteOffset out of range\""); + return 0; } ///////////////// SETTERS //////////////////////////// @@ -148,6 +156,8 @@ void DataViewPrototype::setInt8(quint32 byteOffset, qint32 value) { stream.skipRawData(byteOffset); stream << (qint8)value; + } else { + thisObject().engine()->evaluate("throw \"1RangeError: byteOffset out of range\""); } } @@ -157,6 +167,8 @@ void DataViewPrototype::setUint8(quint32 byteOffset, quint32 value) { stream.skipRawData(byteOffset); stream << (quint8)value; + } else { + thisObject().engine()->evaluate("throw \"1RangeError: byteOffset out of range\""); } } @@ -164,8 +176,11 @@ void DataViewPrototype::setInt16(quint32 byteOffset, qint32 value, bool littleEn if (realOffset(byteOffset, sizeof(qint16))) { QDataStream stream(thisArrayBuffer(), QIODevice::ReadWrite); stream.skipRawData(byteOffset); + stream.setByteOrder((littleEndian) ? QDataStream::LittleEndian : QDataStream::BigEndian); stream << (qint16)value; + } else { + thisObject().engine()->evaluate("throw \"1RangeError: byteOffset out of range\""); } } @@ -173,8 +188,11 @@ void DataViewPrototype::setUint16(quint32 byteOffset, quint32 value, bool little if (realOffset(byteOffset, sizeof(quint16))) { QDataStream stream(thisArrayBuffer(), QIODevice::ReadWrite); stream.skipRawData(byteOffset); + stream.setByteOrder((littleEndian) ? QDataStream::LittleEndian : QDataStream::BigEndian); stream << (quint16)value; + } else { + thisObject().engine()->evaluate("throw \"1RangeError: byteOffset out of range\""); } } @@ -182,8 +200,11 @@ void DataViewPrototype::setInt32(quint32 byteOffset, qint32 value, bool littleEn if (realOffset(byteOffset, sizeof(qint32))) { QDataStream stream(thisArrayBuffer(), QIODevice::ReadWrite); stream.skipRawData(byteOffset); + stream.setByteOrder((littleEndian) ? QDataStream::LittleEndian : QDataStream::BigEndian); stream << (qint32)value; + } else { + thisObject().engine()->evaluate("throw \"1RangeError: byteOffset out of range\""); } } @@ -191,8 +212,11 @@ void DataViewPrototype::setUint32(quint32 byteOffset, quint32 value, bool little if (realOffset(byteOffset, sizeof(quint32))) { QDataStream stream(thisArrayBuffer(), QIODevice::ReadWrite); stream.skipRawData(byteOffset); + stream.setByteOrder((littleEndian) ? QDataStream::LittleEndian : QDataStream::BigEndian); stream << (quint32)value; + } else { + thisObject().engine()->evaluate("throw \"1RangeError: byteOffset out of range\""); } } @@ -200,8 +224,11 @@ void DataViewPrototype::setFloat32(quint32 byteOffset, float value, bool littleE if (realOffset(byteOffset, sizeof(float))) { QDataStream stream(thisArrayBuffer(), QIODevice::ReadWrite); stream.skipRawData(byteOffset); + stream.setByteOrder((littleEndian) ? QDataStream::LittleEndian : QDataStream::BigEndian); stream << value; + } else { + thisObject().engine()->evaluate("throw \"1RangeError: byteOffset out of range\""); } } @@ -209,8 +236,11 @@ void DataViewPrototype::setFloat64(quint32 byteOffset, double value, bool little if (realOffset(byteOffset, sizeof(double))) { QDataStream stream(thisArrayBuffer(), QIODevice::ReadWrite); stream.skipRawData(byteOffset); + stream.setByteOrder((littleEndian) ? QDataStream::LittleEndian : QDataStream::BigEndian); stream << value; + } else { + thisObject().engine()->evaluate("throw \"1RangeError: byteOffset out of range\""); } }