Warning, /graphics/krita/3rdparty/ext_qt/0122-Don-t-use-UINT_MAX-as-invalid-array-index-in-PropertyKey.patch is written in an unsupported language. File is not indexed.

0001 From 68b7a66a6e4d673d11aab44cb87b3f005cdff8ea Mon Sep 17 00:00:00 2001
0002 From: Ulf Hermann <ulf.hermann@qt.io>
0003 Date: Fri, 29 Mar 2019 09:24:27 +0100
0004 Subject: [PATCH] Don't use UINT_MAX as invalid array index in PropertyKey
0005 
0006 Technically UINT_MAX is actually a valid array index, although that is
0007 an academic problem right now. However, we do have a method
0008 isArrayIndex() and should just use that to determine if a PropertyKey is
0009 an array index.
0010 
0011 Fixes: QTBUG-73893
0012 Change-Id: I302e7894331ed2ab4717f7d8d6cc7d8974dabb4e
0013 Reviewed-by: Erik Verbruggen <erik.verbruggen@qt.io>
0014 ---
0015  src/qml/jsruntime/qv4argumentsobject.cpp | 58 ++++++++++++++----------
0016  src/qml/jsruntime/qv4engine.cpp          |  5 +-
0017  src/qml/jsruntime/qv4identifiertable.cpp |  5 +-
0018  src/qml/jsruntime/qv4object.cpp          | 18 +++-----
0019  src/qml/jsruntime/qv4propertykey_p.h     |  4 +-
0020  src/qml/jsruntime/qv4stringobject.cpp    | 15 +++---
0021  src/qml/jsruntime/qv4typedarray.cpp      | 40 ++++++++--------
0022  7 files changed, 75 insertions(+), 70 deletions(-)
0023 
0024 diff --git a/src/qml/jsruntime/qv4argumentsobject.cpp b/src/qml/jsruntime/qv4argumentsobject.cpp
0025 index 4a21f62cf2..98e0ef9e70 100644
0026 --- a/src/qml/jsruntime/qv4argumentsobject.cpp
0027 +++ b/src/qml/jsruntime/qv4argumentsobject.cpp
0028 @@ -116,6 +116,9 @@ bool ArgumentsObject::virtualDefineOwnProperty(Managed *m, PropertyKey id, const
0029  {
0030      ArgumentsObject *args = static_cast<ArgumentsObject *>(m);
0031      args->fullyCreate();
0032 +    if (!id.isArrayIndex())
0033 +        return Object::virtualDefineOwnProperty(m, id, desc, attrs);
0034 +
0035      uint index = id.asArrayIndex();
0036  
0037      if (!args->isMapped(index))
0038 @@ -148,36 +151,42 @@ bool ArgumentsObject::virtualDefineOwnProperty(Managed *m, PropertyKey id, const
0039  
0040  ReturnedValue ArgumentsObject::virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty)
0041  {
0042 -    const ArgumentsObject *args = static_cast<const ArgumentsObject *>(m);
0043 -    uint index = id.asArrayIndex();
0044 -    if (index < args->d()->argCount && !args->d()->fullyCreated) {
0045 -        if (hasProperty)
0046 -            *hasProperty = true;
0047 -        return args->context()->args()[index].asReturnedValue();
0048 +    if (id.isArrayIndex()) {
0049 +        const ArgumentsObject *args = static_cast<const ArgumentsObject *>(m);
0050 +        uint index = id.asArrayIndex();
0051 +        if (index < args->d()->argCount && !args->d()->fullyCreated) {
0052 +            if (hasProperty)
0053 +                *hasProperty = true;
0054 +            return args->context()->args()[index].asReturnedValue();
0055 +        }
0056 +
0057 +        if (args->isMapped(index)) {
0058 +            Q_ASSERT(index < static_cast<uint>(args->context()->function->formalParameterCount()));
0059 +            if (hasProperty)
0060 +                *hasProperty = true;
0061 +            return args->context()->args()[index].asReturnedValue();
0062 +        }
0063      }
0064  
0065 -    if (!args->isMapped(index))
0066 -        return Object::virtualGet(m, id, receiver, hasProperty);
0067 -    Q_ASSERT(index < static_cast<uint>(args->context()->function->formalParameterCount()));
0068 -    if (hasProperty)
0069 -        *hasProperty = true;
0070 -    return args->context()->args()[index].asReturnedValue();
0071 +    return Object::virtualGet(m, id, receiver, hasProperty);
0072  }
0073  
0074  bool ArgumentsObject::virtualPut(Managed *m, PropertyKey id, const Value &value, Value *receiver)
0075  {
0076 -    ArgumentsObject *args = static_cast<ArgumentsObject *>(m);
0077 -    uint index = id.asArrayIndex();
0078 -
0079 -    if (args == receiver && index < args->d()->argCount && !args->d()->fullyCreated) {
0080 -        args->context()->setArg(index, value);
0081 -        return true;
0082 +    if (id.isArrayIndex()) {
0083 +        ArgumentsObject *args = static_cast<ArgumentsObject *>(m);
0084 +        uint index = id.asArrayIndex();
0085 +
0086 +        if (args == receiver && index < args->d()->argCount && !args->d()->fullyCreated) {
0087 +            args->context()->setArg(index, value);
0088 +            return true;
0089 +        }
0090 +
0091 +        bool isMapped = (args == receiver && args->isMapped(index));
0092 +        if (isMapped)
0093 +            args->context()->setArg(index, value);
0094      }
0095  
0096 -    bool isMapped = (args == receiver && args->isMapped(index));
0097 -    if (isMapped)
0098 -        args->context()->setArg(index, value);
0099 -
0100      return Object::virtualPut(m, id, value, receiver);
0101  }
0102  
0103 @@ -186,13 +195,16 @@ bool ArgumentsObject::virtualDeleteProperty(Managed *m, PropertyKey id)
0104      ArgumentsObject *args = static_cast<ArgumentsObject *>(m);
0105      args->fullyCreate();
0106      bool result = Object::virtualDeleteProperty(m, id);
0107 -    if (result)
0108 +    if (result && id.isArrayIndex())
0109          args->removeMapping(id.asArrayIndex());
0110      return result;
0111  }
0112  
0113  PropertyAttributes ArgumentsObject::virtualGetOwnProperty(const Managed *m, PropertyKey id, Property *p)
0114  {
0115 +    if (!id.isArrayIndex())
0116 +        return Object::virtualGetOwnProperty(m, id, p);
0117 +
0118      const ArgumentsObject *args = static_cast<const ArgumentsObject *>(m);
0119      uint index = id.asArrayIndex();
0120      if (index < args->d()->argCount && !args->d()->fullyCreated) {
0121 diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
0122 index ab980e99df..5bc81de472 100644
0123 --- a/src/qml/jsruntime/qv4engine.cpp
0124 +++ b/src/qml/jsruntime/qv4engine.cpp
0125 @@ -1659,9 +1659,8 @@ static QV4::ReturnedValue variantMapToJS(QV4::ExecutionEngine *v4, const QVarian
0126          s = v4->newIdentifier(it.key());
0127          key = s->propertyKey();
0128          v = variantToJS(v4, it.value());
0129 -        uint idx = key->asArrayIndex();
0130 -        if (idx < UINT_MAX)
0131 -            o->arraySet(idx, v);
0132 +        if (key->isArrayIndex())
0133 +            o->arraySet(key->asArrayIndex(), v);
0134          else
0135              o->insertMember(s, v);
0136      }
0137 diff --git a/src/qml/jsruntime/qv4identifiertable.cpp b/src/qml/jsruntime/qv4identifiertable.cpp
0138 index e476baa886..102c06d9b0 100644
0139 --- a/src/qml/jsruntime/qv4identifiertable.cpp
0140 +++ b/src/qml/jsruntime/qv4identifiertable.cpp
0141 @@ -216,9 +216,8 @@ PropertyKey IdentifierTable::asPropertyKeyImpl(const Heap::String *str)
0142  
0143  Heap::StringOrSymbol *IdentifierTable::resolveId(PropertyKey i) const
0144  {
0145 -    uint arrayIdx = i.asArrayIndex();
0146 -    if (arrayIdx < UINT_MAX)
0147 -        return engine->newString(QString::number(arrayIdx));
0148 +    if (i.isArrayIndex())
0149 +        return engine->newString(QString::number(i.asArrayIndex()));
0150      if (!i.isValid())
0151          return nullptr;
0152  
0153 diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp
0154 index efab9a6454..206b410cf4 100644
0155 --- a/src/qml/jsruntime/qv4object.cpp
0156 +++ b/src/qml/jsruntime/qv4object.cpp
0157 @@ -406,8 +406,8 @@ ReturnedValue Object::internalGet(PropertyKey id, const Value *receiver, bool *h
0158  {
0159      Heap::Object *o = d();
0160  
0161 -    uint index = id.asArrayIndex();
0162 -    if (index != UINT_MAX) {
0163 +    if (id.isArrayIndex()) {
0164 +        const uint index = id.asArrayIndex();
0165          Scope scope(this);
0166          PropertyAttributes attrs;
0167          ScopedProperty pd(scope);
0168 @@ -431,8 +431,6 @@ ReturnedValue Object::internalGet(PropertyKey id, const Value *receiver, bool *h
0169                  break;
0170          }
0171      } else {
0172 -        Q_ASSERT(!id.isArrayIndex());
0173 -
0174          while (1) {
0175              auto idx = o->internalClass->findValueOrGetter(id);
0176              if (idx.isValid()) {
0177 @@ -470,14 +468,13 @@ bool Object::internalPut(PropertyKey id, const Value &value, Value *receiver)
0178          if (d()->internalClass->vtable->getOwnProperty == Object::virtualGetOwnProperty) {
0179              // This object standard methods in the vtable, so we can take a shortcut
0180              // and avoid the calls to getOwnProperty and defineOwnProperty
0181 -            uint index = id.asArrayIndex();
0182  
0183              PropertyAttributes attrs;
0184              PropertyIndex propertyIndex{nullptr, nullptr};
0185  
0186 -            if (index != UINT_MAX) {
0187 +            if (id.isArrayIndex()) {
0188                  if (arrayData())
0189 -                    propertyIndex = arrayData()->getValueOrSetter(index, &attrs);
0190 +                    propertyIndex = arrayData()->getValueOrSetter(id.asArrayIndex(), &attrs);
0191              } else {
0192                  auto member = internalClass()->findValueOrSetter(id);
0193                  if (member.isValid()) {
0194 @@ -546,12 +543,11 @@ bool Object::internalPut(PropertyKey id, const Value &value, Value *receiver)
0195  
0196      if (r->internalClass()->vtable->defineOwnProperty == virtualDefineOwnProperty) {
0197          // standard object, we can avoid some more checks
0198 -        uint index = id.asArrayIndex();
0199 -        if (index == UINT_MAX) {
0200 +        if (id.isArrayIndex()) {
0201 +            r->arraySet(id.asArrayIndex(), value);
0202 +        } else {
0203              ScopedStringOrSymbol s(scope, id.asStringOrSymbol());
0204              r->insertMember(s, value);
0205 -        } else {
0206 -            r->arraySet(index, value);
0207          }
0208          return true;
0209      }
0210 diff --git a/src/qml/jsruntime/qv4propertykey_p.h b/src/qml/jsruntime/qv4propertykey_p.h
0211 index 47867765db..523afd4ccf 100644
0212 --- a/src/qml/jsruntime/qv4propertykey_p.h
0213 +++ b/src/qml/jsruntime/qv4propertykey_p.h
0214 @@ -113,8 +113,8 @@ public:
0215      static PropertyKey invalid() { PropertyKey key; key.val = 0; return key; }
0216      static PropertyKey fromArrayIndex(uint idx) { PropertyKey key; key.val = ArrayIndexMask | static_cast<quint64>(idx); return key; }
0217      bool isStringOrSymbol() const { return isManaged() && val != 0; }
0218 -    uint asArrayIndex() const { return (isManaged() || val == 0) ? std::numeric_limits<uint>::max() : static_cast<uint>(val & 0xffffffff); }
0219 -    uint isArrayIndex() const { return !isManaged() && val != 0 && static_cast<uint>(val & 0xffffffff) != std::numeric_limits<uint>::max(); }
0220 +    uint asArrayIndex() const { Q_ASSERT(isArrayIndex()); return static_cast<uint>(val & 0xffffffff); }
0221 +    uint isArrayIndex() const { return !isManaged() && val != 0; }
0222      bool isValid() const { return val != 0; }
0223      static PropertyKey fromStringOrSymbol(Heap::StringOrSymbol *b)
0224      { PropertyKey key; key.setM(b); return key; }
0225 diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp
0226 index dee6a67792..1c6dfe0fdb 100644
0227 --- a/src/qml/jsruntime/qv4stringobject.cpp
0228 +++ b/src/qml/jsruntime/qv4stringobject.cpp
0229 @@ -152,13 +152,14 @@ PropertyAttributes StringObject::virtualGetOwnProperty(const Managed *m, Propert
0230      if (attributes != Attr_Invalid)
0231          return attributes;
0232  
0233 -    const StringObject *s = static_cast<const StringObject *>(m);
0234 -    uint slen = s->d()->string->toQString().length();
0235 -    uint index = id.asArrayIndex();
0236 -    if (index < slen) {
0237 -        if (p)
0238 -            p->value = s->getIndex(index);
0239 -        return Attr_NotConfigurable|Attr_NotWritable;
0240 +    if (id.isArrayIndex()) {
0241 +        const uint index = id.asArrayIndex();
0242 +        const auto s = static_cast<const StringObject *>(m);
0243 +        if (index < uint(s->d()->string->toQString().length())) {
0244 +            if (p)
0245 +                p->value = s->getIndex(index);
0246 +            return Attr_NotConfigurable|Attr_NotWritable;
0247 +        }
0248      }
0249      return Object::virtualGetOwnProperty(m, id, p);
0250  }
0251 diff --git a/src/qml/jsruntime/qv4typedarray.cpp b/src/qml/jsruntime/qv4typedarray.cpp
0252 index d83f021450..43e1dabb6d 100644
0253 --- a/src/qml/jsruntime/qv4typedarray.cpp
0254 +++ b/src/qml/jsruntime/qv4typedarray.cpp
0255 @@ -459,24 +459,23 @@ Heap::TypedArray *TypedArray::create(ExecutionEngine *e, Heap::TypedArray::Type
0256  
0257  ReturnedValue TypedArray::virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty)
0258  {
0259 -    uint index = id.asArrayIndex();
0260 -    if (index == UINT_MAX && !id.isCanonicalNumericIndexString())
0261 +    const bool isArrayIndex = id.isArrayIndex();
0262 +    if (!isArrayIndex && !id.isCanonicalNumericIndexString())
0263          return Object::virtualGet(m, id, receiver, hasProperty);
0264 -    // fall through, with index == UINT_MAX it'll do the right thing.
0265  
0266      Scope scope(static_cast<const Object *>(m)->engine());
0267      Scoped<TypedArray> a(scope, static_cast<const TypedArray *>(m));
0268      if (a->d()->buffer->isDetachedBuffer())
0269          return scope.engine->throwTypeError();
0270  
0271 -    if (index >= a->length()) {
0272 +    if (!isArrayIndex || id.asArrayIndex() >= a->length()) {
0273          if (hasProperty)
0274              *hasProperty = false;
0275          return Encode::undefined();
0276      }
0277  
0278      uint bytesPerElement = a->d()->type->bytesPerElement;
0279 -    uint byteOffset = a->d()->byteOffset + index * bytesPerElement;
0280 +    uint byteOffset = a->d()->byteOffset + id.asArrayIndex() * bytesPerElement;
0281      Q_ASSERT(byteOffset + bytesPerElement <= (uint)a->d()->buffer->byteLength());
0282  
0283      if (hasProperty)
0284 @@ -486,27 +485,22 @@ ReturnedValue TypedArray::virtualGet(const Managed *m, PropertyKey id, const Val
0285  
0286  bool TypedArray::virtualHasProperty(const Managed *m, PropertyKey id)
0287  {
0288 -    uint index = id.asArrayIndex();
0289 -    if (index == UINT_MAX && !id.isCanonicalNumericIndexString())
0290 +    const bool isArrayIndex = id.isArrayIndex();
0291 +    if (!isArrayIndex && !id.isCanonicalNumericIndexString())
0292          return Object::virtualHasProperty(m, id);
0293 -    // fall through, with index == UINT_MAX it'll do the right thing.
0294  
0295      const TypedArray *a = static_cast<const TypedArray *>(m);
0296      if (a->d()->buffer->isDetachedBuffer()) {
0297          a->engine()->throwTypeError();
0298          return false;
0299      }
0300 -    if (index >= a->length())
0301 -        return false;
0302 -    return true;
0303 +    return isArrayIndex && id.asArrayIndex() < a->length();
0304  }
0305  
0306  PropertyAttributes TypedArray::virtualGetOwnProperty(const Managed *m, PropertyKey id, Property *p)
0307  {
0308 -    uint index = id.asArrayIndex();
0309 -    if (index == UINT_MAX && !id.isCanonicalNumericIndexString())
0310 +    if (!id.isArrayIndex() && !id.isCanonicalNumericIndexString())
0311          return Object::virtualGetOwnProperty(m, id, p);
0312 -    // fall through, with index == UINT_MAX it'll do the right thing.
0313  
0314      bool hasProperty = false;
0315      ReturnedValue v = virtualGet(m, id, m, &hasProperty);
0316 @@ -517,10 +511,9 @@ PropertyAttributes TypedArray::virtualGetOwnProperty(const Managed *m, PropertyK
0317  
0318  bool TypedArray::virtualPut(Managed *m, PropertyKey id, const Value &value, Value *receiver)
0319  {
0320 -    uint index = id.asArrayIndex();
0321 -    if (index == UINT_MAX && !id.isCanonicalNumericIndexString())
0322 +    const bool isArrayIndex = id.isArrayIndex();
0323 +    if (!isArrayIndex && !id.isCanonicalNumericIndexString())
0324          return Object::virtualPut(m, id, value, receiver);
0325 -    // fall through, with index == UINT_MAX it'll do the right thing.
0326  
0327      ExecutionEngine *v4 = static_cast<Object *>(m)->engine();
0328      if (v4->hasException)
0329 @@ -531,6 +524,10 @@ bool TypedArray::virtualPut(Managed *m, PropertyKey id, const Value &value, Valu
0330      if (a->d()->buffer->isDetachedBuffer())
0331          return scope.engine->throwTypeError();
0332  
0333 +    if (!isArrayIndex)
0334 +        return false;
0335 +
0336 +    const uint index = id.asArrayIndex();
0337      if (index >= a->length())
0338          return false;
0339  
0340 @@ -547,11 +544,12 @@ bool TypedArray::virtualPut(Managed *m, PropertyKey id, const Value &value, Valu
0341  
0342  bool TypedArray::virtualDefineOwnProperty(Managed *m, PropertyKey id, const Property *p, PropertyAttributes attrs)
0343  {
0344 -    uint index = id.asArrayIndex();
0345 -    if (index == UINT_MAX && !id.isCanonicalNumericIndexString())
0346 -        return Object::virtualDefineOwnProperty(m, id, p, attrs);
0347 -    // fall through, with index == UINT_MAX it'll do the right thing.
0348 +    if (!id.isArrayIndex()) {
0349 +        return !id.isCanonicalNumericIndexString()
0350 +                && Object::virtualDefineOwnProperty(m, id, p, attrs);
0351 +    }
0352  
0353 +    const uint index = id.asArrayIndex();
0354      TypedArray *a = static_cast<TypedArray *>(m);
0355      if (index >= a->length() || attrs.isAccessor())
0356          return false;
0357 -- 
0358 GitLab
0359