From: Apple Date: Sun, 4 Mar 2012 06:06:42 +0000 (+0000) Subject: JavaScriptCore-903.5.tar.gz X-Git-Tag: ios-51^0 X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/commitdiff_plain/1df5f87f1309a8daa30dabdee855f48ae40d14ab JavaScriptCore-903.5.tar.gz --- diff --git a/runtime/JSArray.cpp b/runtime/JSArray.cpp index 6bc3163..473ba1d 100644 --- a/runtime/JSArray.cpp +++ b/runtime/JSArray.cpp @@ -101,7 +101,8 @@ static unsigned lastArraySize = 0; static inline size_t storageSize(unsigned vectorLength) { - ASSERT(vectorLength <= MAX_STORAGE_VECTOR_LENGTH); + if (vectorLength > MAX_STORAGE_VECTOR_LENGTH) + CRASH(); // MAX_STORAGE_VECTOR_LENGTH is defined such that provided (vectorLength <= MAX_STORAGE_VECTOR_LENGTH) // - as asserted above - the following calculation cannot overflow. @@ -440,8 +441,9 @@ NEVER_INLINE void JSArray::putSlowCase(ExecState* exec, unsigned i, JSValue valu } void* baseStorage = storage->m_allocBase; - - if (!tryFastRealloc(baseStorage, storageSize(newVectorLength + m_indexBias)).getValue(baseStorage)) { + + if ((unsigned)m_indexBias > (MAX_STORAGE_VECTOR_LENGTH - newVectorLength) + || !tryFastRealloc(baseStorage, storageSize(newVectorLength + m_indexBias)).getValue(baseStorage)) { throwOutOfMemoryError(exec); return; } @@ -594,7 +596,8 @@ bool JSArray::increaseVectorLength(unsigned newLength) unsigned newVectorLength = getNewVectorLength(newLength); void* baseStorage = storage->m_allocBase; - if (!tryFastRealloc(baseStorage, storageSize(newVectorLength + m_indexBias)).getValue(baseStorage)) + if ((unsigned)m_indexBias > (MAX_STORAGE_VECTOR_LENGTH - newVectorLength) + || !tryFastRealloc(baseStorage, storageSize(newVectorLength + m_indexBias)).getValue(baseStorage)) return false; storage = m_storage = reinterpret_cast_ptr(static_cast(baseStorage) + m_indexBias * sizeof(JSValue)); @@ -623,6 +626,8 @@ bool JSArray::increaseVectorPrefixLength(unsigned newLength) ASSERT(newLength <= MAX_STORAGE_VECTOR_INDEX); unsigned newVectorLength = getNewVectorLength(newLength); + if ((unsigned)m_indexBias > (MAX_STORAGE_VECTOR_LENGTH - newVectorLength)) + return false; void* newBaseStorage = fastMalloc(storageSize(newVectorLength + m_indexBias)); if (!newBaseStorage) return false; @@ -850,7 +855,8 @@ void JSArray::unshiftCount(ExecState* exec, int count) memmove(newBaseStorage, storage, storageSize(0)); m_storage = reinterpret_cast_ptr(newBaseStorage); m_vectorLength += count; - } else if (!increaseVectorPrefixLength(m_vectorLength + count)) { + } else if ((unsigned)count > (MAX_STORAGE_VECTOR_LENGTH - m_vectorLength) + || !increaseVectorPrefixLength(m_vectorLength + count)) { throwOutOfMemoryError(exec); return; } diff --git a/runtime/JSObject.cpp b/runtime/JSObject.cpp index 05ec555..dbf9ccf 100644 --- a/runtime/JSObject.cpp +++ b/runtime/JSObject.cpp @@ -313,6 +313,11 @@ const HashEntry* JSObject::findPropertyHashEntry(ExecState* exec, const Identifi void JSObject::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction, unsigned attributes) { + if (propertyName == exec->propertyNames().underscoreProto) { + // Defining a getter for __proto__ is silently ignored. + return; + } + JSValue object = getDirect(exec->globalData(), propertyName); if (object && object.isGetterSetter()) { ASSERT(m_structure->hasGetterSetterProperties()); @@ -339,6 +344,11 @@ void JSObject::defineGetter(ExecState* exec, const Identifier& propertyName, JSO void JSObject::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunction, unsigned attributes) { + if (propertyName == exec->propertyNames().underscoreProto) { + // Defining a setter for __proto__ is silently ignored. + return; + } + JSValue object = getDirect(exec->globalData(), propertyName); if (object && object.isGetterSetter()) { ASSERT(m_structure->hasGetterSetterProperties()); diff --git a/runtime/JSValue.h b/runtime/JSValue.h index de50011..ce3b3d3 100644 --- a/runtime/JSValue.h +++ b/runtime/JSValue.h @@ -400,11 +400,13 @@ namespace JSC { ALWAYS_INLINE JSValue jsDoubleNumber(double d) { + ASSERT(JSValue(JSValue::EncodeAsDouble, d).isNumber()); return JSValue(JSValue::EncodeAsDouble, d); } ALWAYS_INLINE JSValue jsNumber(double d) { + ASSERT(JSValue(d).isNumber()); return JSValue(d); } diff --git a/runtime/ObjectConstructor.cpp b/runtime/ObjectConstructor.cpp index c325fa0..6efcea6 100644 --- a/runtime/ObjectConstructor.cpp +++ b/runtime/ObjectConstructor.cpp @@ -131,7 +131,11 @@ EncodedJSValue JSC_HOST_CALL objectConstructorGetPrototypeOf(ExecState* exec) { if (!exec->argument(0).isObject()) return throwVMError(exec, createTypeError(exec, "Requested prototype of a value that is not an object.")); - return JSValue::encode(asObject(exec->argument(0))->prototype()); + + // This uses JSValue::get() instead of directly accessing the prototype from the object + // (using JSObject::prototype()) in order to allow objects to override the behavior, such + // as returning jsUndefined() for cross-origin access. + return JSValue::encode(exec->argument(0).get(exec, exec->propertyNames().underscoreProto)); } EncodedJSValue JSC_HOST_CALL objectConstructorGetOwnPropertyDescriptor(ExecState* exec) diff --git a/wtf/CheckedArithmetic.h b/wtf/CheckedArithmetic.h new file mode 100644 index 0000000..3de506d --- /dev/null +++ b/wtf/CheckedArithmetic.h @@ -0,0 +1,693 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CheckedArithmetic_h +#define CheckedArithmetic_h + +#include "Assertions.h" +#include "TypeTraits.h" + +#include +#include + +/* Checked + * + * This class provides a mechanism to perform overflow-safe integer arithmetic + * without having to manually ensure that you have all the required bounds checks + * directly in your code. + * + * There are two modes of operation: + * - The default is Checked, and crashes at the point + * and overflow has occurred. + * - The alternative is Checked, which uses an additional + * byte of storage to track whether an overflow has occurred, subsequent + * unchecked operations will crash if an overflow has occured + * + * It is possible to provide a custom overflow handler, in which case you need + * to support these functions: + * - void overflowed(); + * This function is called when an operation has produced an overflow. + * - bool hasOverflowed(); + * This function must return true if overflowed() has been called on an + * instance and false if it has not. + * - void clearOverflow(); + * Used to reset overflow tracking when a value is being overwritten with + * a new value. + * + * Checked works for all integer types, with the following caveats: + * - Mixing signedness of operands is only supported for types narrower than + * 64bits. + * - It does have a performance impact, so tight loops may want to be careful + * when using it. + * + */ + +namespace WTF { + +class CrashOnOverflow { +protected: + void overflowed() + { + CRASH(); + } + + void clearOverflow() { } + +public: + bool hasOverflowed() const { return false; } +}; + +class RecordOverflow { +protected: + RecordOverflow() + : m_overflowed(false) + { + } + + void overflowed() + { + m_overflowed = true; + } + + void clearOverflow() + { + m_overflowed = false; + } + +public: + bool hasOverflowed() const { return m_overflowed; } + +private: + unsigned char m_overflowed; +}; + +template class Checked; +template struct RemoveChecked; +template struct RemoveChecked >; + +template ::is_signed, bool sourceSigned = std::numeric_limits::is_signed> struct BoundsChecker; +template struct BoundsChecker { + static bool inBounds(Source value) + { + // Same signedness so implicit type conversion will always increase precision + // to widest type + return value <= std::numeric_limits::max(); + } +}; + +template struct BoundsChecker { + static bool inBounds(Source value) + { + // Same signedness so implicit type conversion will always increase precision + // to widest type + return std::numeric_limits::min() <= value && value <= std::numeric_limits::max(); + } +}; + +template struct BoundsChecker { + static bool inBounds(Source value) + { + // Target is unsigned so any value less than zero is clearly unsafe + if (value < 0) + return false; + // If our (unsigned) Target is the same or greater width we can + // convert value to type Target without losing precision + if (sizeof(Target) >= sizeof(Source)) + return static_cast(value) <= std::numeric_limits::max(); + // The signed Source type has greater precision than the target so + // max(Target) -> Source will widen. + return value <= static_cast(std::numeric_limits::max()); + } +}; + +template struct BoundsChecker { + static bool inBounds(Source value) + { + // Signed target with an unsigned source + if (sizeof(Target) <= sizeof(Source)) + return value <= static_cast(std::numeric_limits::max()); + // Target is Wider than Source so we're guaranteed to fit any value in + // unsigned Source + return true; + } +}; + +template ::value> struct BoundsCheckElider; +template struct BoundsCheckElider { + static bool inBounds(Source) { return true; } +}; +template struct BoundsCheckElider : public BoundsChecker { +}; + +template static inline bool isInBounds(Source value) +{ + return BoundsCheckElider::inBounds(value); +} + +template struct RemoveChecked { + typedef T CleanType; + static const CleanType DefaultValue = 0; +}; + +template struct RemoveChecked > { + typedef typename RemoveChecked::CleanType CleanType; + static const CleanType DefaultValue = 0; +}; + +template struct RemoveChecked > { + typedef typename RemoveChecked::CleanType CleanType; + static const CleanType DefaultValue = 0; +}; + +// The ResultBase and SignednessSelector are used to workaround typeof not being +// available in MSVC +template sizeof(V)), bool sameSize = (sizeof(U) == sizeof(V))> struct ResultBase; +template struct ResultBase { + typedef U ResultType; +}; + +template struct ResultBase { + typedef V ResultType; +}; + +template struct ResultBase { + typedef U ResultType; +}; + +template ::is_signed, bool vIsSigned = std::numeric_limits::is_signed> struct SignednessSelector; +template struct SignednessSelector { + typedef U ResultType; +}; + +template struct SignednessSelector { + typedef U ResultType; +}; + +template struct SignednessSelector { + typedef V ResultType; +}; + +template struct SignednessSelector { + typedef U ResultType; +}; + +template struct ResultBase { + typedef typename SignednessSelector::ResultType ResultType; +}; + +template struct Result : ResultBase::CleanType, typename RemoveChecked::CleanType> { +}; + +template ::ResultType, + bool lhsSigned = std::numeric_limits::is_signed, bool rhsSigned = std::numeric_limits::is_signed> struct ArithmeticOperations; + +template struct ArithmeticOperations { + // LHS and RHS are signed types + + // Helper function + static inline bool signsMatch(LHS lhs, RHS rhs) + { + return (lhs ^ rhs) >= 0; + } + + static inline bool add(LHS lhs, RHS rhs, ResultType& result) WARN_UNUSED_RETURN + { + if (signsMatch(lhs, rhs)) { + if (lhs >= 0) { + if ((std::numeric_limits::max() - rhs) < lhs) + return false; + } else { + ResultType temp = lhs - std::numeric_limits::min(); + if (rhs < -temp) + return false; + } + } // if the signs do not match this operation can't overflow + result = lhs + rhs; + return true; + } + + static inline bool sub(LHS lhs, RHS rhs, ResultType& result) WARN_UNUSED_RETURN + { + if (!signsMatch(lhs, rhs)) { + if (lhs >= 0) { + if (lhs > std::numeric_limits::max() + rhs) + return false; + } else { + if (rhs > std::numeric_limits::max() + lhs) + return false; + } + } // if the signs match this operation can't overflow + result = lhs - rhs; + return true; + } + + static inline bool multiply(LHS lhs, RHS rhs, ResultType& result) WARN_UNUSED_RETURN + { + if (signsMatch(lhs, rhs)) { + if (lhs >= 0) { + if (lhs && (std::numeric_limits::max() / lhs) < rhs) + return false; + } else { + if (lhs == std::numeric_limits::min() || rhs == std::numeric_limits::min()) + return false; + if ((std::numeric_limits::max() / -lhs) < -rhs) + return false; + } + } else { + if (lhs < 0) { + if (rhs && lhs < (std::numeric_limits::min() / rhs)) + return false; + } else { + if (lhs && rhs < (std::numeric_limits::min() / lhs)) + return false; + } + } + result = lhs * rhs; + return true; + } + + static inline bool equals(LHS lhs, RHS rhs) { return lhs == rhs; } + +}; + +template struct ArithmeticOperations { + // LHS and RHS are unsigned types so bounds checks are nice and easy + static inline bool add(LHS lhs, RHS rhs, ResultType& result) WARN_UNUSED_RETURN + { + ResultType temp = lhs + rhs; + if (temp < lhs) + return false; + result = temp; + return true; + } + + static inline bool sub(LHS lhs, RHS rhs, ResultType& result) WARN_UNUSED_RETURN + { + ResultType temp = lhs - rhs; + if (temp > lhs) + return false; + result = temp; + return true; + } + + static inline bool multiply(LHS lhs, RHS rhs, ResultType& result) WARN_UNUSED_RETURN + { + ResultType temp = lhs * rhs; + if (temp < lhs) + return false; + result = temp; + return true; + } + + static inline bool equals(LHS lhs, RHS rhs) { return lhs == rhs; } + +}; + +template struct ArithmeticOperations { + static inline bool add(int64_t lhs, int64_t rhs, ResultType& result) + { + int64_t temp = lhs + rhs; + if (temp < std::numeric_limits::min()) + return false; + if (temp > std::numeric_limits::max()) + return false; + result = static_cast(temp); + return true; + } + + static inline bool sub(int64_t lhs, int64_t rhs, ResultType& result) + { + int64_t temp = lhs - rhs; + if (temp < std::numeric_limits::min()) + return false; + if (temp > std::numeric_limits::max()) + return false; + result = static_cast(temp); + return true; + } + + static inline bool multiply(int64_t lhs, int64_t rhs, ResultType& result) + { + int64_t temp = lhs * rhs; + if (temp < std::numeric_limits::min()) + return false; + if (temp > std::numeric_limits::max()) + return false; + result = static_cast(temp); + return true; + } + + static inline bool equals(int lhs, unsigned rhs) + { + return static_cast(lhs) == static_cast(rhs); + } +}; + +template struct ArithmeticOperations { + static inline bool add(int64_t lhs, int64_t rhs, ResultType& result) + { + return ArithmeticOperations::add(rhs, lhs, result); + } + + static inline bool sub(int64_t lhs, int64_t rhs, ResultType& result) + { + return ArithmeticOperations::sub(lhs, rhs, result); + } + + static inline bool multiply(int64_t lhs, int64_t rhs, ResultType& result) + { + return ArithmeticOperations::multiply(rhs, lhs, result); + } + + static inline bool equals(unsigned lhs, int rhs) + { + return ArithmeticOperations::equals(rhs, lhs); + } +}; + +template static inline bool safeAdd(U lhs, V rhs, R& result) +{ + return ArithmeticOperations::add(lhs, rhs, result); +} + +template static inline bool safeSub(U lhs, V rhs, R& result) +{ + return ArithmeticOperations::sub(lhs, rhs, result); +} + +template static inline bool safeMultiply(U lhs, V rhs, R& result) +{ + return ArithmeticOperations::multiply(lhs, rhs, result); +} + +template static inline bool safeEquals(U lhs, V rhs) +{ + return ArithmeticOperations::equals(lhs, rhs); +} + +enum ResultOverflowedTag { ResultOverflowed }; + +// FIXME: Needed to workaround http://llvm.org/bugs/show_bug.cgi?id=10801 +static inline bool workAroundClangBug() { return true; } + +template class Checked : public OverflowHandler { +public: + template friend class Checked; + Checked() + : m_value(0) + { + } + + Checked(ResultOverflowedTag) + : m_value(0) + { + // FIXME: Remove this when clang fixes http://llvm.org/bugs/show_bug.cgi?id=10801 + if (workAroundClangBug()) + this->overflowed(); + } + + template Checked(U value) + { + if (!isInBounds(value)) + this->overflowed(); + m_value = static_cast(value); + } + + template Checked(const Checked& rhs) + : m_value(rhs.m_value) + { + if (rhs.hasOverflowed()) + this->overflowed(); + } + + template Checked(const Checked& rhs) + : OverflowHandler(rhs) + { + if (!isInBounds(rhs.m_value)) + this->overflowed(); + m_value = static_cast(rhs.m_value); + } + + template Checked(const Checked& rhs) + { + if (rhs.hasOverflowed()) + this->overflowed(); + if (!isInBounds(rhs.m_value)) + this->overflowed(); + m_value = static_cast(rhs.m_value); + } + + const Checked& operator=(Checked rhs) + { + this->clearOverflow(); + if (rhs.hasOverflowed()) + this->overflowed(); + m_value = static_cast(rhs.m_value); + return *this; + } + + template const Checked& operator=(U value) + { + return *this = Checked(value); + } + + template const Checked& operator=(const Checked& rhs) + { + return *this = Checked(rhs); + } + + // prefix + const Checked& operator++() + { + if (m_value == std::numeric_limits::max()) + this->overflowed(); + m_value++; + return *this; + } + + const Checked& operator--() + { + if (m_value == std::numeric_limits::min()) + this->overflowed(); + m_value--; + return *this; + } + + // postfix operators + const Checked operator++(int) + { + if (m_value == std::numeric_limits::max()) + this->overflowed(); + return Checked(m_value++); + } + + const Checked operator--(int) + { + if (m_value == std::numeric_limits::min()) + this->overflowed(); + return Checked(m_value--); + } + + // Boolean operators + bool operator!() const + { + if (this->hasOverflowed()) + CRASH(); + return !m_value; + } + + typedef void* (Checked::*UnspecifiedBoolType); + operator UnspecifiedBoolType*() const + { + if (this->hasOverflowed()) + CRASH(); + return (m_value) ? reinterpret_cast(1) : 0; + } + + // Value accessors. unsafeGet() will crash if there's been an overflow. + T unsafeGet() const + { + if (this->hasOverflowed()) + CRASH(); + return m_value; + } + + bool safeGet(T& value) const WARN_UNUSED_RETURN + { + value = m_value; + return this->hasOverflowed(); + } + + // Mutating assignment + template const Checked operator+=(U rhs) + { + if (!safeAdd(m_value, rhs, m_value)) + this->overflowed(); + return *this; + } + + template const Checked operator-=(U rhs) + { + if (!safeSub(m_value, rhs, m_value)) + this->overflowed(); + return *this; + } + + template const Checked operator*=(U rhs) + { + if (!safeMultiply(m_value, rhs, m_value)) + this->overflowed(); + return *this; + } + + template const Checked operator+=(Checked rhs) + { + if (rhs.hasOverflowed()) + this->overflowed(); + return *this += rhs.m_value; + } + + template const Checked operator-=(Checked rhs) + { + if (rhs.hasOverflowed()) + this->overflowed(); + return *this -= rhs.m_value; + } + + template const Checked operator*=(Checked rhs) + { + if (rhs.hasOverflowed()) + this->overflowed(); + return *this *= rhs.m_value; + } + + // Equality comparisons + template bool operator==(Checked rhs) + { + return unsafeGet() == rhs.unsafeGet(); + } + + template bool operator==(U rhs) + { + if (this->hasOverflowed()) + this->overflowed(); + return safeEquals(m_value, rhs); + } + + template const Checked operator==(Checked rhs) + { + return unsafeGet() == Checked(rhs.unsafeGet()); + } + + template bool operator!=(U rhs) + { + return !(*this == rhs); + } + +private: + // Disallow implicit conversion of floating point to integer types + Checked(float); + Checked(double); + void operator=(float); + void operator=(double); + void operator+=(float); + void operator+=(double); + void operator-=(float); + void operator-=(double); + T m_value; +}; + +template static inline Checked::ResultType, OverflowHandler> operator+(Checked lhs, Checked rhs) +{ + U x = 0; + V y = 0; + bool overflowed = lhs.safeGet(x) || rhs.safeGet(y); + typename Result::ResultType result = 0; + overflowed |= !safeAdd(x, y, result); + if (overflowed) + return ResultOverflowed; + return result; +} + +template static inline Checked::ResultType, OverflowHandler> operator-(Checked lhs, Checked rhs) +{ + U x = 0; + V y = 0; + bool overflowed = lhs.safeGet(x) || rhs.safeGet(y); + typename Result::ResultType result = 0; + overflowed |= !safeSub(x, y, result); + if (overflowed) + return ResultOverflowed; + return result; +} + +template static inline Checked::ResultType, OverflowHandler> operator*(Checked lhs, Checked rhs) +{ + U x = 0; + V y = 0; + bool overflowed = lhs.safeGet(x) || rhs.safeGet(y); + typename Result::ResultType result = 0; + overflowed |= !safeMultiply(x, y, result); + if (overflowed) + return ResultOverflowed; + return result; +} + +template static inline Checked::ResultType, OverflowHandler> operator+(Checked lhs, V rhs) +{ + return lhs + Checked(rhs); +} + +template static inline Checked::ResultType, OverflowHandler> operator-(Checked lhs, V rhs) +{ + return lhs - Checked(rhs); +} + +template static inline Checked::ResultType, OverflowHandler> operator*(Checked lhs, V rhs) +{ + return lhs * Checked(rhs); +} + +template static inline Checked::ResultType, OverflowHandler> operator+(U lhs, Checked rhs) +{ + return Checked(lhs) + rhs; +} + +template static inline Checked::ResultType, OverflowHandler> operator-(U lhs, Checked rhs) +{ + return Checked(lhs) - rhs; +} + +template static inline Checked::ResultType, OverflowHandler> operator*(U lhs, Checked rhs) +{ + return Checked(lhs) * rhs; +} + +} + +using WTF::Checked; +using WTF::RecordOverflow; + +#endif diff --git a/wtf/MathExtras.h b/wtf/MathExtras.h index 5498316..6da125a 100644 --- a/wtf/MathExtras.h +++ b/wtf/MathExtras.h @@ -274,6 +274,11 @@ inline int clampToInteger(unsigned x) return static_cast(x); } +inline bool isWithinIntRange(float x) +{ + return x > static_cast(std::numeric_limits::min()) && x < static_cast(std::numeric_limits::max()); +} + #if !COMPILER(MSVC) && !(COMPILER(RVCT) && PLATFORM(BREWMP)) && !OS(SOLARIS) && !OS(SYMBIAN) using std::isfinite; using std::isinf; diff --git a/yarr/YarrInterpreter.cpp b/yarr/YarrInterpreter.cpp index 903c692..c8312aa 100644 --- a/yarr/YarrInterpreter.cpp +++ b/yarr/YarrInterpreter.cpp @@ -1491,7 +1491,7 @@ public: m_bodyDisjunction->terms.append(ByteTerm::WordBoundary(invert, inputPosition)); } - void atomPatternCharacter(UChar ch, int inputPosition, unsigned frameLocation, unsigned quantityCount, QuantifierType quantityType) + void atomPatternCharacter(UChar ch, int inputPosition, unsigned frameLocation, Checked quantityCount, QuantifierType quantityType) { if (m_pattern.m_ignoreCase) { UChar lo = Unicode::toLower(ch); @@ -1506,22 +1506,22 @@ public: m_bodyDisjunction->terms.append(ByteTerm(ch, inputPosition, frameLocation, quantityCount, quantityType)); } - void atomCharacterClass(CharacterClass* characterClass, bool invert, int inputPosition, unsigned frameLocation, unsigned quantityCount, QuantifierType quantityType) + void atomCharacterClass(CharacterClass* characterClass, bool invert, int inputPosition, unsigned frameLocation, Checked quantityCount, QuantifierType quantityType) { m_bodyDisjunction->terms.append(ByteTerm(characterClass, invert, inputPosition)); - m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].atom.quantityCount = quantityCount; + m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].atom.quantityCount = quantityCount.unsafeGet(); m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].atom.quantityType = quantityType; m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].frameLocation = frameLocation; } - void atomBackReference(unsigned subpatternId, int inputPosition, unsigned frameLocation, unsigned quantityCount, QuantifierType quantityType) + void atomBackReference(unsigned subpatternId, int inputPosition, unsigned frameLocation, Checked quantityCount, QuantifierType quantityType) { ASSERT(subpatternId); m_bodyDisjunction->terms.append(ByteTerm::BackReference(subpatternId, inputPosition)); - m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].atom.quantityCount = quantityCount; + m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].atom.quantityCount = quantityCount.unsafeGet(); m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].atom.quantityType = quantityType; m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].frameLocation = frameLocation; } @@ -1582,7 +1582,7 @@ public: m_currentAlternativeIndex = beginTerm + 1; } - void atomParentheticalAssertionEnd(int inputPosition, unsigned frameLocation, unsigned quantityCount, QuantifierType quantityType) + void atomParentheticalAssertionEnd(int inputPosition, unsigned frameLocation, Checked quantityCount, QuantifierType quantityType) { unsigned beginTerm = popParenthesesStack(); closeAlternative(beginTerm + 1); @@ -1598,9 +1598,9 @@ public: m_bodyDisjunction->terms[endTerm].atom.parenthesesWidth = endTerm - beginTerm; m_bodyDisjunction->terms[endTerm].frameLocation = frameLocation; - m_bodyDisjunction->terms[beginTerm].atom.quantityCount = quantityCount; + m_bodyDisjunction->terms[beginTerm].atom.quantityCount = quantityCount.unsafeGet(); m_bodyDisjunction->terms[beginTerm].atom.quantityType = quantityType; - m_bodyDisjunction->terms[endTerm].atom.quantityCount = quantityCount; + m_bodyDisjunction->terms[endTerm].atom.quantityCount = quantityCount.unsafeGet(); m_bodyDisjunction->terms[endTerm].atom.quantityType = quantityType; } @@ -1680,7 +1680,7 @@ public: m_bodyDisjunction->terms[endIndex].frameLocation = frameLocation; } - void atomParenthesesSubpatternEnd(unsigned lastSubpatternId, int inputPosition, unsigned frameLocation, unsigned quantityCount, QuantifierType quantityType, unsigned callFrameSize = 0) + void atomParenthesesSubpatternEnd(unsigned lastSubpatternId, int inputPosition, unsigned frameLocation, Checked quantityCount, QuantifierType quantityType, unsigned callFrameSize = 0) { unsigned beginTerm = popParenthesesStack(); closeAlternative(beginTerm + 1); @@ -1706,12 +1706,12 @@ public: m_allParenthesesInfo.append(parenthesesDisjunction); m_bodyDisjunction->terms.append(ByteTerm(ByteTerm::TypeParenthesesSubpattern, subpatternId, parenthesesDisjunction, capture, inputPosition)); - m_bodyDisjunction->terms[beginTerm].atom.quantityCount = quantityCount; + m_bodyDisjunction->terms[beginTerm].atom.quantityCount = quantityCount.unsafeGet(); m_bodyDisjunction->terms[beginTerm].atom.quantityType = quantityType; m_bodyDisjunction->terms[beginTerm].frameLocation = frameLocation; } - void atomParenthesesOnceEnd(int inputPosition, unsigned frameLocation, unsigned quantityCount, QuantifierType quantityType) + void atomParenthesesOnceEnd(int inputPosition, unsigned frameLocation, Checked quantityCount, QuantifierType quantityType) { unsigned beginTerm = popParenthesesStack(); closeAlternative(beginTerm + 1); @@ -1727,13 +1727,13 @@ public: m_bodyDisjunction->terms[endTerm].atom.parenthesesWidth = endTerm - beginTerm; m_bodyDisjunction->terms[endTerm].frameLocation = frameLocation; - m_bodyDisjunction->terms[beginTerm].atom.quantityCount = quantityCount; + m_bodyDisjunction->terms[beginTerm].atom.quantityCount = quantityCount.unsafeGet(); m_bodyDisjunction->terms[beginTerm].atom.quantityType = quantityType; - m_bodyDisjunction->terms[endTerm].atom.quantityCount = quantityCount; + m_bodyDisjunction->terms[endTerm].atom.quantityCount = quantityCount.unsafeGet(); m_bodyDisjunction->terms[endTerm].atom.quantityType = quantityType; } - void atomParenthesesTerminalEnd(int inputPosition, unsigned frameLocation, unsigned quantityCount, QuantifierType quantityType) + void atomParenthesesTerminalEnd(int inputPosition, unsigned frameLocation, Checked quantityCount, QuantifierType quantityType) { unsigned beginTerm = popParenthesesStack(); closeAlternative(beginTerm + 1); @@ -1749,9 +1749,9 @@ public: m_bodyDisjunction->terms[endTerm].atom.parenthesesWidth = endTerm - beginTerm; m_bodyDisjunction->terms[endTerm].frameLocation = frameLocation; - m_bodyDisjunction->terms[beginTerm].atom.quantityCount = quantityCount; + m_bodyDisjunction->terms[beginTerm].atom.quantityCount = quantityCount.unsafeGet(); m_bodyDisjunction->terms[beginTerm].atom.quantityType = quantityType; - m_bodyDisjunction->terms[endTerm].atom.quantityCount = quantityCount; + m_bodyDisjunction->terms[endTerm].atom.quantityCount = quantityCount.unsafeGet(); m_bodyDisjunction->terms[endTerm].atom.quantityType = quantityType; } diff --git a/yarr/YarrInterpreter.h b/yarr/YarrInterpreter.h index 78a8f34..eb5fdc6 100644 --- a/yarr/YarrInterpreter.h +++ b/yarr/YarrInterpreter.h @@ -107,7 +107,7 @@ struct ByteTerm { bool m_invert : 1; int inputPosition; - ByteTerm(UChar ch, int inputPos, unsigned frameLocation, unsigned quantityCount, QuantifierType quantityType) + ByteTerm(UChar ch, int inputPos, unsigned frameLocation, Checked quantityCount, QuantifierType quantityType) : frameLocation(frameLocation) , m_capture(false) , m_invert(false) @@ -126,11 +126,11 @@ struct ByteTerm { atom.patternCharacter = ch; atom.quantityType = quantityType; - atom.quantityCount = quantityCount; + atom.quantityCount = quantityCount.unsafeGet(); inputPosition = inputPos; } - ByteTerm(UChar lo, UChar hi, int inputPos, unsigned frameLocation, unsigned quantityCount, QuantifierType quantityType) + ByteTerm(UChar lo, UChar hi, int inputPos, unsigned frameLocation, Checked quantityCount, QuantifierType quantityType) : frameLocation(frameLocation) , m_capture(false) , m_invert(false) @@ -150,7 +150,7 @@ struct ByteTerm { atom.casedCharacter.lo = lo; atom.casedCharacter.hi = hi; atom.quantityType = quantityType; - atom.quantityCount = quantityCount; + atom.quantityCount = quantityCount.unsafeGet(); inputPosition = inputPos; } @@ -204,17 +204,17 @@ struct ByteTerm { return term; } - static ByteTerm CheckInput(unsigned count) + static ByteTerm CheckInput(Checked count) { ByteTerm term(TypeCheckInput); - term.checkInputCount = count; + term.checkInputCount = count.unsafeGet(); return term; } - static ByteTerm UncheckInput(unsigned count) + static ByteTerm UncheckInput(Checked count) { ByteTerm term(TypeUncheckInput); - term.checkInputCount = count; + term.checkInputCount = count.unsafeGet(); return term; } diff --git a/yarr/YarrJIT.cpp b/yarr/YarrJIT.cpp index 8d5344f..0649661 100644 --- a/yarr/YarrJIT.cpp +++ b/yarr/YarrJIT.cpp @@ -560,7 +560,7 @@ class YarrGenerator : private MacroAssembler { if (term->inputPosition == m_checked) matchDest.append(atEndOfInput()); - readCharacter((term->inputPosition - m_checked), character); + readCharacter(term->inputPosition - m_checked, character); matchCharacterClass(character, matchDest, m_pattern.newlineCharacterClass()); op.m_jumps.append(jump()); @@ -716,10 +716,10 @@ class YarrGenerator : private MacroAssembler { const RegisterID countRegister = regT1; move(index, countRegister); - sub32(Imm32(term->quantityCount), countRegister); + sub32(Imm32(term->quantityCount.unsafeGet()), countRegister); Label loop(this); - BaseIndex address(input, countRegister, TimesTwo, (term->inputPosition - m_checked + term->quantityCount) * sizeof(UChar)); + BaseIndex address(input, countRegister, TimesTwo, ((term->inputPosition - m_checked + Checked(term->quantityCount)) * static_cast(sizeof(UChar))).unsafeGet()); if (m_pattern.m_ignoreCase && isASCIIAlpha(ch)) { load16(address, character); @@ -765,7 +765,7 @@ class YarrGenerator : private MacroAssembler { if (term->quantityCount == quantifyInfinite) jump(loop); else - branch32(NotEqual, countRegister, Imm32(term->quantityCount)).linkTo(loop, this); + branch32(NotEqual, countRegister, Imm32(term->quantityCount.unsafeGet())).linkTo(loop, this); failures.link(this); op.m_reentry = label(); @@ -817,7 +817,7 @@ class YarrGenerator : private MacroAssembler { nonGreedyFailures.append(atEndOfInput()); if (term->quantityCount != quantifyInfinite) - nonGreedyFailures.append(branch32(Equal, countRegister, Imm32(term->quantityCount))); + nonGreedyFailures.append(branch32(Equal, countRegister, Imm32(term->quantityCount.unsafeGet()))); if (m_pattern.m_ignoreCase && isASCIIAlpha(ch)) { readCharacter(term->inputPosition - m_checked, character); or32(TrustedImm32(32), character); @@ -845,7 +845,7 @@ class YarrGenerator : private MacroAssembler { const RegisterID character = regT0; JumpList matchDest; - readCharacter((term->inputPosition - m_checked), character); + readCharacter(term->inputPosition - m_checked, character); matchCharacterClass(character, matchDest, term->characterClass); if (term->invert()) @@ -869,11 +869,11 @@ class YarrGenerator : private MacroAssembler { const RegisterID countRegister = regT1; move(index, countRegister); - sub32(Imm32(term->quantityCount), countRegister); + sub32(Imm32(term->quantityCount.unsafeGet()), countRegister); Label loop(this); JumpList matchDest; - load16(BaseIndex(input, countRegister, TimesTwo, (term->inputPosition - m_checked + term->quantityCount) * sizeof(UChar)), character); + load16(BaseIndex(input, countRegister, TimesTwo, ((term->inputPosition - m_checked + Checked(term->quantityCount)) * static_cast(sizeof(UChar))).unsafeGet()), character); matchCharacterClass(character, matchDest, term->characterClass); if (term->invert()) @@ -919,7 +919,7 @@ class YarrGenerator : private MacroAssembler { add32(TrustedImm32(1), countRegister); add32(TrustedImm32(1), index); if (term->quantityCount != quantifyInfinite) { - branch32(NotEqual, countRegister, Imm32(term->quantityCount)).linkTo(loop, this); + branch32(NotEqual, countRegister, Imm32(term->quantityCount.unsafeGet())).linkTo(loop, this); failures.append(jump()); } else jump(loop); @@ -972,7 +972,7 @@ class YarrGenerator : private MacroAssembler { loadFromFrame(term->frameLocation, countRegister); nonGreedyFailures.append(atEndOfInput()); - nonGreedyFailures.append(branch32(Equal, countRegister, Imm32(term->quantityCount))); + nonGreedyFailures.append(branch32(Equal, countRegister, Imm32(term->quantityCount.unsafeGet()))); JumpList matchDest; readCharacter(term->inputPosition - m_checked, character); diff --git a/yarr/YarrPattern.cpp b/yarr/YarrPattern.cpp index fc8e8ee..bf150c1 100644 --- a/yarr/YarrPattern.cpp +++ b/yarr/YarrPattern.cpp @@ -511,7 +511,7 @@ public: unsigned setupAlternativeOffsets(PatternAlternative* alternative, unsigned currentCallFrameSize, unsigned initialInputPosition) { alternative->m_hasFixedSize = true; - unsigned currentInputPosition = initialInputPosition; + Checked currentInputPosition = initialInputPosition; for (unsigned i = 0; i < alternative->m_terms.size(); ++i) { PatternTerm& term = alternative->m_terms[i]; @@ -520,11 +520,11 @@ public: case PatternTerm::TypeAssertionBOL: case PatternTerm::TypeAssertionEOL: case PatternTerm::TypeAssertionWordBoundary: - term.inputPosition = currentInputPosition; + term.inputPosition = currentInputPosition.unsafeGet(); break; case PatternTerm::TypeBackReference: - term.inputPosition = currentInputPosition; + term.inputPosition = currentInputPosition.unsafeGet(); term.frameLocation = currentCallFrameSize; currentCallFrameSize += YarrStackSpaceForBackTrackInfoBackReference; alternative->m_hasFixedSize = false; @@ -534,7 +534,7 @@ public: break; case PatternTerm::TypePatternCharacter: - term.inputPosition = currentInputPosition; + term.inputPosition = currentInputPosition.unsafeGet(); if (term.quantityType != QuantifierFixedCount) { term.frameLocation = currentCallFrameSize; currentCallFrameSize += YarrStackSpaceForBackTrackInfoPatternCharacter; @@ -544,7 +544,7 @@ public: break; case PatternTerm::TypeCharacterClass: - term.inputPosition = currentInputPosition; + term.inputPosition = currentInputPosition.unsafeGet(); if (term.quantityType != QuantifierFixedCount) { term.frameLocation = currentCallFrameSize; currentCallFrameSize += YarrStackSpaceForBackTrackInfoCharacterClass; @@ -559,18 +559,18 @@ public: if (term.quantityCount == 1 && !term.parentheses.isCopy) { if (term.quantityType != QuantifierFixedCount) currentCallFrameSize += YarrStackSpaceForBackTrackInfoParenthesesOnce; - currentCallFrameSize = setupDisjunctionOffsets(term.parentheses.disjunction, currentCallFrameSize, currentInputPosition); + currentCallFrameSize = setupDisjunctionOffsets(term.parentheses.disjunction, currentCallFrameSize, currentInputPosition.unsafeGet()); // If quantity is fixed, then pre-check its minimum size. if (term.quantityType == QuantifierFixedCount) currentInputPosition += term.parentheses.disjunction->m_minimumSize; - term.inputPosition = currentInputPosition; + term.inputPosition = currentInputPosition.unsafeGet(); } else if (term.parentheses.isTerminal) { currentCallFrameSize += YarrStackSpaceForBackTrackInfoParenthesesTerminal; - currentCallFrameSize = setupDisjunctionOffsets(term.parentheses.disjunction, currentCallFrameSize, currentInputPosition); - term.inputPosition = currentInputPosition; + currentCallFrameSize = setupDisjunctionOffsets(term.parentheses.disjunction, currentCallFrameSize, currentInputPosition.unsafeGet()); + term.inputPosition = currentInputPosition.unsafeGet(); } else { - term.inputPosition = currentInputPosition; - setupDisjunctionOffsets(term.parentheses.disjunction, 0, currentInputPosition); + term.inputPosition = currentInputPosition.unsafeGet(); + setupDisjunctionOffsets(term.parentheses.disjunction, 0, currentInputPosition.unsafeGet()); currentCallFrameSize += YarrStackSpaceForBackTrackInfoParentheses; } // Fixed count of 1 could be accepted, if they have a fixed size *AND* if all alternatives are of the same length. @@ -578,9 +578,9 @@ public: break; case PatternTerm::TypeParentheticalAssertion: - term.inputPosition = currentInputPosition; + term.inputPosition = currentInputPosition.unsafeGet(); term.frameLocation = currentCallFrameSize; - currentCallFrameSize = setupDisjunctionOffsets(term.parentheses.disjunction, currentCallFrameSize + YarrStackSpaceForBackTrackInfoParentheticalAssertion, currentInputPosition); + currentCallFrameSize = setupDisjunctionOffsets(term.parentheses.disjunction, currentCallFrameSize + YarrStackSpaceForBackTrackInfoParentheticalAssertion, currentInputPosition.unsafeGet()); break; case PatternTerm::TypeDotStarEnclosure: @@ -590,7 +590,7 @@ public: } } - alternative->m_minimumSize = currentInputPosition - initialInputPosition; + alternative->m_minimumSize = (currentInputPosition - initialInputPosition).unsafeGet(); return currentCallFrameSize; } diff --git a/yarr/YarrPattern.h b/yarr/YarrPattern.h index 97c3870..e46479e 100644 --- a/yarr/YarrPattern.h +++ b/yarr/YarrPattern.h @@ -28,6 +28,7 @@ #define YarrPattern_h #include +#include #include #include @@ -117,7 +118,7 @@ struct PatternTerm { } anchors; }; QuantifierType quantityType; - unsigned quantityCount; + Checked quantityCount; int inputPosition; unsigned frameLocation;