Don't check the this pointer for 0 in member functions
authorLars Knoll <lars.knoll@digia.com>
Mon, 27 Oct 2014 07:54:26 +0000 (08:54 +0100)
committerSimon Hausmann <simon.hausmann@digia.com>
Mon, 27 Oct 2014 14:19:12 +0000 (15:19 +0100)
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 <simon.hausmann@digia.com>
src/qml/jsruntime/qv4argumentsobject.cpp
src/qml/jsruntime/qv4arraydata.cpp
src/qml/jsruntime/qv4arraydata_p.h
src/qml/jsruntime/qv4arrayobject.cpp
src/qml/jsruntime/qv4functionobject.cpp
src/qml/jsruntime/qv4lookup.cpp
src/qml/jsruntime/qv4object.cpp
src/qml/jsruntime/qv4objectproto.cpp
src/qml/jsruntime/qv4runtime.cpp

index d79521c..4af8927 100644 (file)
@@ -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;
index c40f501..3235a11 100644 (file)
@@ -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())) {
index 70c581d..c2deb3e 100644 (file)
@@ -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<SimpleArrayData *>(this);
         return that->getProperty(index);
index eaf4742..011279a 100644 (file)
@@ -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();
 
index 67f2a0c..f3ad8ef 100644 (file)
@@ -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<SimpleArrayData *>(arr->arrayData())->data(i);
             for (quint32 i = alen; i < len; ++i)
index 4f2ec83..254666e 100644 (file)
@@ -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();
index d53ca01..0c61d66 100644 (file)
@@ -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<const StringObject *>(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<const Object *>(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<StringObject *>(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);
             }
index a1c6130..9cbf4b2 100644 (file)
@@ -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);
index 5086113..048ff93 100644 (file)
@@ -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();