From 57e5407178ce05f577bd032a7bab2508434a4b02 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Mon, 27 Oct 2014 08:54:26 +0100 Subject: [PATCH] Don't check the this pointer for 0 in member functions This actually violates the C++ standard that defines that you aren't allowed to call member functions on an invalid object. Instead insert the 0 pointer checks on the caller side where required. Change-Id: I8be3c3831594bb6482e9ef6de6e590ec437ac0f8 Reviewed-by: Simon Hausmann --- src/qml/jsruntime/qv4argumentsobject.cpp | 4 +++- src/qml/jsruntime/qv4arraydata.cpp | 2 +- src/qml/jsruntime/qv4arraydata_p.h | 8 -------- src/qml/jsruntime/qv4arrayobject.cpp | 3 +++ src/qml/jsruntime/qv4functionobject.cpp | 4 +++- src/qml/jsruntime/qv4lookup.cpp | 2 +- src/qml/jsruntime/qv4object.cpp | 19 ++++++++++--------- src/qml/jsruntime/qv4objectproto.cpp | 10 +++++----- src/qml/jsruntime/qv4runtime.cpp | 2 +- 9 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/qml/jsruntime/qv4argumentsobject.cpp b/src/qml/jsruntime/qv4argumentsobject.cpp index d79521c..4af8927 100644 --- a/src/qml/jsruntime/qv4argumentsobject.cpp +++ b/src/qml/jsruntime/qv4argumentsobject.cpp @@ -97,7 +97,7 @@ bool ArgumentsObject::defineOwnProperty(ExecutionContext *ctx, uint index, const fullyCreate(); Scope scope(ctx); - Property *pd = arrayData()->getProperty(index); + Property *pd = arrayData() ? arrayData()->getProperty(index) : 0; Property map; PropertyAttributes mapAttrs; bool isMapped = false; @@ -106,6 +106,7 @@ bool ArgumentsObject::defineOwnProperty(ExecutionContext *ctx, uint index, const isMapped = arrayData()->attributes(index).isAccessor() && pd->getter() == context()->d()->engine->argumentsAccessors[index].getter(); if (isMapped) { + Q_ASSERT(arrayData()); mapAttrs = arrayData()->attributes(index); map.copy(*pd, mapAttrs); setArrayAttributes(index, Attr_Data); @@ -119,6 +120,7 @@ bool ArgumentsObject::defineOwnProperty(ExecutionContext *ctx, uint index, const ctx->d()->strictMode = strict; if (isMapped && attrs.isData()) { + Q_ASSERT(arrayData()); ScopedCallData callData(scope, 1); callData->thisObject = this->asReturnedValue(); callData->args[0] = desc.value; diff --git a/src/qml/jsruntime/qv4arraydata.cpp b/src/qml/jsruntime/qv4arraydata.cpp index c40f501..3235a11 100644 --- a/src/qml/jsruntime/qv4arraydata.cpp +++ b/src/qml/jsruntime/qv4arraydata.cpp @@ -740,7 +740,7 @@ void ArrayData::sort(ExecutionContext *context, Object *thisObject, const ValueR if (!len) return; - if (!thisObject->arrayData()->length()) + if (!thisObject->arrayData() || !thisObject->arrayData()->length()) return; if (!(comparefn->isUndefined() || comparefn->asObject())) { diff --git a/src/qml/jsruntime/qv4arraydata_p.h b/src/qml/jsruntime/qv4arraydata_p.h index 70c581d..c2deb3e 100644 --- a/src/qml/jsruntime/qv4arraydata_p.h +++ b/src/qml/jsruntime/qv4arraydata_p.h @@ -116,8 +116,6 @@ struct Q_QML_EXPORT ArrayData : public Managed bool isSparse() const { return this && type() == Sparse; } uint length() const { - if (!this) - return 0; return vtable()->length(this); } @@ -130,14 +128,10 @@ struct Q_QML_EXPORT ArrayData : public Managed } bool isEmpty(uint i) const { - if (!this) - return true; return (vtable()->get(this, i) == Primitive::emptyValue().asReturnedValue()); } ReturnedValue get(uint i) const { - if (!this) - return Primitive::emptyValue().asReturnedValue(); return vtable()->get(this, i); } inline Property *getProperty(uint index); @@ -242,8 +236,6 @@ struct Q_QML_EXPORT SparseArrayData : public ArrayData inline Property *ArrayData::getProperty(uint index) { - if (!this) - return 0; if (type() != Sparse) { SimpleArrayData *that = static_cast(this); return that->getProperty(index); diff --git a/src/qml/jsruntime/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp index eaf4742..011279a 100644 --- a/src/qml/jsruntime/qv4arrayobject.cpp +++ b/src/qml/jsruntime/qv4arrayobject.cpp @@ -268,6 +268,7 @@ ReturnedValue ArrayPrototype::method_push(CallContext *ctx) return Encode::undefined(); instance->arrayCreate(); + Q_ASSERT(instance->arrayData()); uint len = instance->getLength(); @@ -347,6 +348,7 @@ ReturnedValue ArrayPrototype::method_shift(CallContext *ctx) return Encode::undefined(); instance->arrayCreate(); + Q_ASSERT(instance->arrayData()); uint len = instance->getLength(); @@ -534,6 +536,7 @@ ReturnedValue ArrayPrototype::method_unshift(CallContext *ctx) return Encode::undefined(); instance->arrayCreate(); + Q_ASSERT(instance->arrayData()); uint len = instance->getLength(); diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index 67f2a0c..f3ad8ef 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -298,7 +298,9 @@ ReturnedValue FunctionPrototype::method_apply(CallContext *ctx) for (quint32 i = 0; i < len; ++i) callData->args[i] = arr->getIndexed(i); } else { - uint alen = qMin(len, arr->arrayData()->length()); + uint alen = arr->arrayData() ? arr->arrayData()->length() : 0; + if (alen > len) + alen = len; for (uint i = 0; i < alen; ++i) callData->args[i] = static_cast(arr->arrayData())->data(i); for (quint32 i = alen; i < len; ++i) diff --git a/src/qml/jsruntime/qv4lookup.cpp b/src/qml/jsruntime/qv4lookup.cpp index 4f2ec83..254666e 100644 --- a/src/qml/jsruntime/qv4lookup.cpp +++ b/src/qml/jsruntime/qv4lookup.cpp @@ -139,7 +139,7 @@ ReturnedValue Lookup::indexedGetterFallback(Lookup *l, const ValueRef object, co } if (idx < UINT_MAX) { - if (!o->arrayData()->hasAttributes()) { + if (o->arrayData() && !o->arrayData()->hasAttributes()) { ScopedValue v(scope, o->arrayData()->get(idx)); if (!v->isEmpty()) return v->asReturnedValue(); diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp index d53ca01..0c61d66 100644 --- a/src/qml/jsruntime/qv4object.cpp +++ b/src/qml/jsruntime/qv4object.cpp @@ -244,7 +244,7 @@ Property *Object::__getOwnProperty__(String *name, PropertyAttributes *attrs) Property *Object::__getOwnProperty__(uint index, PropertyAttributes *attrs) { - Property *p = arrayData()->getProperty(index); + Property *p = arrayData() ? arrayData()->getProperty(index) : 0; if (p) { if (attrs) *attrs = arrayData()->attributes(index); @@ -289,7 +289,7 @@ Property *Object::__getPropertyDescriptor__(uint index, PropertyAttributes *attr { const Object *o = this; while (o) { - Property *p = o->arrayData()->getProperty(index); + Property *p = o->arrayData() ? o->arrayData()->getProperty(index) : 0; if (p) { if (attrs) *attrs = o->arrayData()->attributes(index); @@ -355,7 +355,7 @@ bool Object::hasOwnProperty(String *name) const bool Object::hasOwnProperty(uint index) const { - if (!arrayData()->isEmpty(index)) + if (arrayData() && !arrayData()->isEmpty(index)) return true; if (isStringObject()) { String *s = static_cast(this)->d()->value.asString(); @@ -414,7 +414,7 @@ PropertyAttributes Object::query(const Managed *m, String *name) PropertyAttributes Object::queryIndexed(const Managed *m, uint index) { const Object *o = static_cast(m); - if (o->arrayData()->get(index) != Primitive::emptyValue().asReturnedValue()) + if (o->arrayData() && o->arrayData()->get(index) != Primitive::emptyValue().asReturnedValue()) return o->arrayData()->attributes(index); if (o->isStringObject()) { @@ -618,7 +618,7 @@ ReturnedValue Object::internalGetIndexed(uint index, bool *hasProperty) PropertyAttributes attrs; Object *o = this; while (o) { - Property *p = o->arrayData()->getProperty(index); + Property *p = o->arrayData() ? o->arrayData()->getProperty(index) : 0; if (p) { pd = p; attrs = o->arrayData()->attributes(index); @@ -738,7 +738,7 @@ void Object::internalPutIndexed(uint index, const ValueRef value) PropertyAttributes attrs; - Property *pd = arrayData()->getProperty(index); + Property *pd = arrayData() ? arrayData()->getProperty(index) : 0; if (pd) attrs = arrayData()->attributes(index); @@ -925,7 +925,7 @@ bool Object::defineOwnProperty2(ExecutionContext *ctx, uint index, const Propert Property *current = 0; // Clause 1 - { + if (arrayData()) { current = arrayData()->getProperty(index); if (!current && isStringObject()) current = static_cast(this)->getIndex(index); @@ -962,12 +962,12 @@ bool Object::__defineOwnProperty__(ExecutionContext *ctx, uint index, String *me if (attrs.isEmpty()) return true; - Property *current; + Property *current = 0; PropertyAttributes cattrs; if (member) { current = propertyAt(index); cattrs = internalClass()->propertyData[index]; - } else { + } else if (arrayData()) { current = arrayData()->getProperty(index); cattrs = arrayData()->attributes(index); } @@ -1000,6 +1000,7 @@ bool Object::__defineOwnProperty__(ExecutionContext *ctx, uint index, String *me if (!member) { // need to convert the array and the slot initSparseArray(); + Q_ASSERT(arrayData()); setArrayAttributes(index, cattrs); current = arrayData()->getProperty(index); } diff --git a/src/qml/jsruntime/qv4objectproto.cpp b/src/qml/jsruntime/qv4objectproto.cpp index a1c6130..9cbf4b2 100644 --- a/src/qml/jsruntime/qv4objectproto.cpp +++ b/src/qml/jsruntime/qv4objectproto.cpp @@ -329,11 +329,11 @@ ReturnedValue ObjectPrototype::method_isSealed(CallContext *ctx) if (!o->arrayData() || !o->arrayData()->length()) return Encode(true); - if (o->arrayData()->length() && !o->arrayData()->attrs()) + Q_ASSERT(o->arrayData() && o->arrayData()->length()); + if (!o->arrayData()->attrs()) return Encode(false); for (uint i = 0; i < o->arrayData()->alloc(); ++i) { - // ### Fix for sparse arrays if (!o->arrayData()->isEmpty(i)) if (o->arrayData()->attributes(i).isConfigurable()) return Encode(false); @@ -355,14 +355,14 @@ ReturnedValue ObjectPrototype::method_isFrozen(CallContext *ctx) if (o->internalClass() != o->internalClass()->frozen()) return Encode(false); - if (!o->arrayData()->length()) + if (!o->arrayData() || !o->arrayData()->length()) return Encode(true); - if (o->arrayData()->length() && !o->arrayData()->attrs()) + Q_ASSERT(o->arrayData() && o->arrayData()->length()); + if (!o->arrayData()->attrs()) return Encode(false); for (uint i = 0; i < o->arrayData()->alloc(); ++i) { - // ### Fix for sparse arrays if (!o->arrayData()->isEmpty(i)) if (o->arrayData()->attributes(i).isConfigurable() || o->arrayData()->attributes(i).isWritable()) return Encode(false); diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index 5086113..048ff93 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -580,7 +580,7 @@ ReturnedValue Runtime::getElement(ExecutionContext *ctx, const ValueRef object, } if (idx < UINT_MAX) { - if (!o->arrayData()->hasAttributes()) { + if (o->arrayData() && !o->arrayData()->hasAttributes()) { ScopedValue v(scope, o->arrayData()->get(idx)); if (!v->isEmpty()) return v->asReturnedValue(); -- 2.7.4