diff options
author | Simon Hausmann <simon.hausmann@qt.io> | 2018-04-18 10:18:48 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@qt.io> | 2018-05-02 15:46:26 +0000 |
commit | d258c904a6027007d00526ab38b8cc5ba2aed3bf (patch) | |
tree | 5adcfee69c31dc6ab1c8bbe5950415b7d7370e23 /src/qml/jsruntime/qv4sequenceobject.cpp | |
parent | 02fec0dbd7b9774d17690e378b814ff075ac6299 (diff) |
Throw type errors when attempting to mutate read-only sequence properties
Calling for example Qt.application.arguments.push("...") should throw an
exception.
Task-number: QTBUG-67774
Change-Id: Ifd5cd3357dde510cca77b9b32c9f55f8f72837ff
Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
Diffstat (limited to 'src/qml/jsruntime/qv4sequenceobject.cpp')
-rw-r--r-- | src/qml/jsruntime/qv4sequenceobject.cpp | 33 |
1 files changed, 25 insertions, 8 deletions
diff --git a/src/qml/jsruntime/qv4sequenceobject.cpp b/src/qml/jsruntime/qv4sequenceobject.cpp index c0dce2df0d..f0aa39b786 100644 --- a/src/qml/jsruntime/qv4sequenceobject.cpp +++ b/src/qml/jsruntime/qv4sequenceobject.cpp @@ -227,7 +227,7 @@ namespace Heap { template <typename Container> struct QQmlSequence : Object { void init(const Container &container); - void init(QObject *object, int propertyIndex); + void init(QObject *object, int propertyIndex, bool readOnly); void destroy() { delete container; object.destroy(); @@ -237,7 +237,8 @@ struct QQmlSequence : Object { mutable Container *container; QQmlQPointer<QObject> object; int propertyIndex; - bool isReference; + bool isReference : 1; + bool isReadOnly : 1; }; } @@ -294,6 +295,9 @@ public: return false; } + if (d()->isReadOnly) + return false; + if (d()->isReference) { if (!d()->object) return false; @@ -366,6 +370,8 @@ public: /* Qt containers have int (rather than uint) allowable indexes. */ if (index > INT_MAX) return false; + if (d()->isReadOnly) + return false; if (d()->isReference) { if (!d()->object) return false; @@ -432,11 +438,13 @@ public: const QV4::Value *m_compareFn; }; - void sort(const FunctionObject *f, const Value *, const Value *argv, int argc) + bool sort(const FunctionObject *f, const Value *, const Value *argv, int argc) { + if (d()->isReadOnly) + return false; if (d()->isReference) { if (!d()->object) - return; + return false; loadReference(); } @@ -450,6 +458,8 @@ public: if (d()->isReference) storeReference(); + + return true; } static QV4::ReturnedValue method_get_length(const FunctionObject *b, const Value *thisObject, const Value *, int) @@ -480,6 +490,10 @@ public: generateWarning(scope.engine, QLatin1String("Index out of range during length set")); RETURN_UNDEFINED(); } + + if (This->d()->isReadOnly) + THROW_TYPE_ERROR(); + /* Read the sequence from the QObject property if we're a reference */ if (This->d()->isReference) { if (!This->d()->object) @@ -572,6 +586,7 @@ void Heap::QQmlSequence<Container>::init(const Container &container) this->container = new Container(container); propertyIndex = -1; isReference = false; + isReadOnly = false; object.init(); QV4::Scope scope(internalClass->engine); @@ -581,12 +596,13 @@ void Heap::QQmlSequence<Container>::init(const Container &container) } template <typename Container> -void Heap::QQmlSequence<Container>::init(QObject *object, int propertyIndex) +void Heap::QQmlSequence<Container>::init(QObject *object, int propertyIndex, bool readOnly) { Object::init(); this->container = new Container; this->propertyIndex = propertyIndex; isReference = true; + this->isReadOnly = readOnly; this->object.init(object); QV4::Scope scope(internalClass->engine); QV4::Scoped<QV4::QQmlSequence<Container> > o(scope, this); @@ -668,7 +684,8 @@ ReturnedValue SequencePrototype::method_sort(const FunctionObject *b, const Valu #define CALL_SORT(SequenceElementType, SequenceElementTypeName, SequenceType, DefaultValue) \ if (QQml##SequenceElementTypeName##List *s = o->as<QQml##SequenceElementTypeName##List>()) { \ - s->sort(b, thisObject, argv, argc); \ + if (!s->sort(b, thisObject, argv, argc)) \ + THROW_TYPE_ERROR(); \ } else FOREACH_QML_SEQUENCE_TYPE(CALL_SORT) @@ -691,11 +708,11 @@ bool SequencePrototype::isSequenceType(int sequenceTypeId) #define NEW_REFERENCE_SEQUENCE(ElementType, ElementTypeName, SequenceType, unused) \ if (sequenceType == qMetaTypeId<SequenceType>()) { \ - QV4::ScopedObject obj(scope, engine->memoryManager->allocate<QQml##ElementTypeName##List>(object, propertyIndex)); \ + QV4::ScopedObject obj(scope, engine->memoryManager->allocate<QQml##ElementTypeName##List>(object, propertyIndex, readOnly)); \ return obj.asReturnedValue(); \ } else -ReturnedValue SequencePrototype::newSequence(QV4::ExecutionEngine *engine, int sequenceType, QObject *object, int propertyIndex, bool *succeeded) +ReturnedValue SequencePrototype::newSequence(QV4::ExecutionEngine *engine, int sequenceType, QObject *object, int propertyIndex, bool readOnly, bool *succeeded) { QV4::Scope scope(engine); // This function is called when the property is a QObject Q_PROPERTY of |