Diff
Modified: trunk/JSTests/ChangeLog (236803 => 236804)
--- trunk/JSTests/ChangeLog 2018-10-03 18:26:29 UTC (rev 236803)
+++ trunk/JSTests/ChangeLog 2018-10-03 18:28:55 UTC (rev 236804)
@@ -1,3 +1,13 @@
+2018-10-03 Mark Lam <mark....@apple.com>
+
+ Make string MaxLength for all WTF and JS strings consistently equal to INT_MAX.
+ https://bugs.webkit.org/show_bug.cgi?id=190187
+ <rdar://problem/42512909>
+
+ Reviewed by Michael Saboff.
+
+ * stress/regress-190187.js: Added.
+
2018-10-02 Caio Lima <ticaiol...@gmail.com>
[BigInt] BigInt.proptotype.toString is broken when radix is power of 2
Added: trunk/JSTests/stress/regress-190187.js (0 => 236804)
--- trunk/JSTests/stress/regress-190187.js (rev 0)
+++ trunk/JSTests/stress/regress-190187.js 2018-10-03 18:28:55 UTC (rev 236804)
@@ -0,0 +1,18 @@
+//@ runDefault
+//@ skip if $memoryLimited or $buildType == "debug"
+//@ slow!
+
+try {
+ var v1 = "AAAAAAAAAAA";
+ for(var i = 0; i < 27; i++)
+ v1 = v1 + v1;
+ var v2;
+ var v3 = RegExp.prototype.toString.call({source:v1,flags:v1});
+ v3 += v1;
+ v2 += v3.localeCompare(v1);
+} catch (e) {
+ exception = e;
+}
+
+if (exception != "Error: Out of memory")
+ throw "FAILED";
Modified: trunk/Source/_javascript_Core/ChangeLog (236803 => 236804)
--- trunk/Source/_javascript_Core/ChangeLog 2018-10-03 18:26:29 UTC (rev 236803)
+++ trunk/Source/_javascript_Core/ChangeLog 2018-10-03 18:28:55 UTC (rev 236804)
@@ -1,3 +1,34 @@
+2018-10-03 Mark Lam <mark....@apple.com>
+
+ Make string MaxLength for all WTF and JS strings consistently equal to INT_MAX.
+ https://bugs.webkit.org/show_bug.cgi?id=190187
+ <rdar://problem/42512909>
+
+ Reviewed by Michael Saboff.
+
+ Allowing different max string lengths at each level opens up opportunities for
+ bugs to creep in. With 2 different max length values, it is more difficult to
+ keep the story straight on how we do overflow / bounds checks at each place in
+ the code. It's also difficult to tell if a seemingly valid check at the WTF level
+ will have bad ramifications at the JSC level. Also, it's also not meaningful to
+ support a max length > INT_MAX. To eliminate this class of bugs, we'll
+ standardize on a MaxLength of INT_MAX at all levels.
+
+ We'll also standardize the way we do length overflow checks on using
+ CheckedArithmetic, and add some asserts to document the assumptions of the code.
+
+ * runtime/FunctionConstructor.cpp:
+ (JSC::constructFunctionSkippingEvalEnabledCheck):
+ - Fix OOM error handling which crashed a test after the new MaxLength was applied.
+ * runtime/JSString.h:
+ (JSC::JSString::finishCreation):
+ (JSC::JSString::createHasOtherOwner):
+ (JSC::JSString::setLength):
+ * runtime/JSStringInlines.h:
+ (JSC::jsMakeNontrivialString):
+ * runtime/Operations.h:
+ (JSC::jsString):
+
2018-10-03 Koby Boyango <kob...@mce-sys.com>
[JSC] Add a C++ callable overload of objectConstructorSeal
Modified: trunk/Source/_javascript_Core/runtime/FunctionConstructor.cpp (236803 => 236804)
--- trunk/Source/_javascript_Core/runtime/FunctionConstructor.cpp 2018-10-03 18:26:29 UTC (rev 236803)
+++ trunk/Source/_javascript_Core/runtime/FunctionConstructor.cpp 2018-10-03 18:28:55 UTC (rev 236804)
@@ -144,7 +144,11 @@
{
// The spec mandates that the parameters parse as a valid parameter list
// independent of the function body.
- String program = makeString("(", prefix, "(", parameterBuilder.toString(), "){\n\n})");
+ String program = tryMakeString("(", prefix, "(", parameterBuilder.toString(), "){\n\n})");
+ if (UNLIKELY(!program)) {
+ throwOutOfMemoryError(exec, scope);
+ return nullptr;
+ }
SourceCode source = makeSource(program, sourceOrigin, sourceURL, position);
JSValue exception;
checkSyntax(exec, source, &exception);
Modified: trunk/Source/_javascript_Core/runtime/JSString.h (236803 => 236804)
--- trunk/Source/_javascript_Core/runtime/JSString.h 2018-10-03 18:26:29 UTC (rev 236803)
+++ trunk/Source/_javascript_Core/runtime/JSString.h 2018-10-03 18:28:55 UTC (rev 236804)
@@ -95,8 +95,12 @@
return &vm.stringSpace;
}
- static const unsigned MaxLength = std::numeric_limits<int32_t>::max();
-
+ // We employ overflow checks in many places with the assumption that MaxLength
+ // is INT_MAX. Hence, it cannot be changed into another length value without
+ // breaking all the bounds and overflow checks that assume this.
+ static constexpr unsigned MaxLength = std::numeric_limits<int32_t>::max();
+ static_assert(MaxLength == String::MaxLength, "");
+
private:
JSString(VM& vm, Ref<StringImpl>&& value)
: JSCell(vm, vm.stringStructure.get())
@@ -109,7 +113,7 @@
{
}
- void finishCreation(VM& vm, size_t length)
+ void finishCreation(VM& vm, unsigned length)
{
ASSERT(!m_value.isNull());
Base::finishCreation(vm);
@@ -117,7 +121,7 @@
setIs8Bit(m_value.impl()->is8Bit());
}
- void finishCreation(VM& vm, size_t length, size_t cost)
+ void finishCreation(VM& vm, unsigned length, size_t cost)
{
ASSERT(!m_value.isNull());
Base::finishCreation(vm);
@@ -145,7 +149,7 @@
}
static JSString* createHasOtherOwner(VM& vm, Ref<StringImpl>&& value)
{
- size_t length = value->length();
+ unsigned length = value->length();
JSString* newString = new (NotNull, allocateCell<JSString>(vm.heap)) JSString(vm, WTFMove(value));
newString->finishCreation(vm, length);
return newString;
@@ -209,6 +213,7 @@
ALWAYS_INLINE void setLength(unsigned length)
{
+ ASSERT(length <= MaxLength);
m_length = length;
}
@@ -255,10 +260,14 @@
return false;
if (m_index == JSRopeString::s_maxInternalRopeLength)
expand();
- if (static_cast<int32_t>(m_jsString->length() + jsString->length()) < 0) {
+
+ static_assert(JSString::MaxLength == std::numeric_limits<int32_t>::max(), "");
+ auto sum = checkedSum<int32_t>(m_jsString->length(), jsString->length());
+ if (sum.hasOverflowed()) {
this->overflowed();
return false;
}
+ ASSERT(static_cast<unsigned>(sum.unsafeGet()) <= MaxLength);
m_jsString->append(m_vm, m_index++, jsString);
return true;
}
Modified: trunk/Source/_javascript_Core/runtime/JSStringInlines.h (236803 => 236804)
--- trunk/Source/_javascript_Core/runtime/JSStringInlines.h 2018-10-03 18:26:29 UTC (rev 236803)
+++ trunk/Source/_javascript_Core/runtime/JSStringInlines.h 2018-10-03 18:28:55 UTC (rev 236804)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2016-2018 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -50,6 +50,7 @@
String result = tryMakeString(std::forward<StringType>(string), std::forward<StringTypes>(strings)...);
if (UNLIKELY(!result))
return throwOutOfMemoryError(exec, scope);
+ ASSERT(result.length() <= JSString::MaxLength);
return jsNontrivialString(exec, WTFMove(result));
}
Modified: trunk/Source/_javascript_Core/runtime/Operations.h (236803 => 236804)
--- trunk/Source/_javascript_Core/runtime/Operations.h 2018-10-03 18:26:29 UTC (rev 236803)
+++ trunk/Source/_javascript_Core/runtime/Operations.h 2018-10-03 18:28:55 UTC (rev 236804)
@@ -1,6 +1,6 @@
/*
* Copyright (C) 1999-2000 Harri Porten (por...@kde.org)
- * Copyright (C) 2002-2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2002-2018 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -42,12 +42,13 @@
VM& vm = exec->vm();
auto scope = DECLARE_THROW_SCOPE(vm);
- int32_t length1 = s1->length();
+ unsigned length1 = s1->length();
if (!length1)
return s2;
- int32_t length2 = s2->length();
+ unsigned length2 = s2->length();
if (!length2)
return s1;
+ static_assert(JSString::MaxLength == std::numeric_limits<int32_t>::max(), "");
if (sumOverflows<int32_t>(length1, length2)) {
throwOutOfMemoryError(exec, scope);
return nullptr;
@@ -61,19 +62,19 @@
VM& vm = exec->vm();
auto scope = DECLARE_THROW_SCOPE(vm);
- int32_t length1 = s1->length();
+ unsigned length1 = s1->length();
if (!length1)
RELEASE_AND_RETURN(scope, jsString(exec, s2, s3));
- int32_t length2 = s2->length();
+ unsigned length2 = s2->length();
if (!length2)
RELEASE_AND_RETURN(scope, jsString(exec, s1, s3));
- int32_t length3 = s3->length();
+ unsigned length3 = s3->length();
if (!length3)
RELEASE_AND_RETURN(scope, jsString(exec, s1, s2));
-
+ static_assert(JSString::MaxLength == std::numeric_limits<int32_t>::max(), "");
if (sumOverflows<int32_t>(length1, length2, length3)) {
throwOutOfMemoryError(exec, scope);
return nullptr;
@@ -86,15 +87,13 @@
VM* vm = &exec->vm();
auto scope = DECLARE_THROW_SCOPE(*vm);
- int32_t length1 = u1.length();
- int32_t length2 = u2.length();
- int32_t length3 = u3.length();
-
- if (length1 < 0 || length2 < 0 || length3 < 0) {
- throwOutOfMemoryError(exec, scope);
- return nullptr;
- }
-
+ unsigned length1 = u1.length();
+ unsigned length2 = u2.length();
+ unsigned length3 = u3.length();
+ ASSERT(length1 <= JSString::MaxLength);
+ ASSERT(length2 <= JSString::MaxLength);
+ ASSERT(length3 <= JSString::MaxLength);
+
if (!length1)
RELEASE_AND_RETURN(scope, jsString(exec, jsString(vm, u2), jsString(vm, u3)));
@@ -104,6 +103,7 @@
if (!length3)
RELEASE_AND_RETURN(scope, jsString(exec, jsString(vm, u1), jsString(vm, u2)));
+ static_assert(JSString::MaxLength == std::numeric_limits<int32_t>::max(), "");
if (sumOverflows<int32_t>(length1, length2, length3)) {
throwOutOfMemoryError(exec, scope);
return nullptr;
Modified: trunk/Source/WTF/ChangeLog (236803 => 236804)
--- trunk/Source/WTF/ChangeLog 2018-10-03 18:26:29 UTC (rev 236803)
+++ trunk/Source/WTF/ChangeLog 2018-10-03 18:28:55 UTC (rev 236804)
@@ -1,3 +1,17 @@
+2018-10-03 Mark Lam <mark....@apple.com>
+
+ Make string MaxLength for all WTF and JS strings consistently equal to INT_MAX.
+ https://bugs.webkit.org/show_bug.cgi?id=190187
+ <rdar://problem/42512909>
+
+ Reviewed by Michael Saboff.
+
+ * wtf/text/StringConcatenate.h:
+ (WTF::tryMakeStringFromAdapters):
+ (WTF::sumWithOverflow): Deleted.
+ * wtf/text/StringImpl.h:
+ * wtf/text/WTFString.h:
+
2018-10-03 Michael Catanzaro <mcatanz...@igalia.com>
-Wunused-variable in RenderLayer::updateScrollableAreaSet
Modified: trunk/Source/WTF/wtf/text/StringConcatenate.h (236803 => 236804)
--- trunk/Source/WTF/wtf/text/StringConcatenate.h 2018-10-03 18:26:29 UTC (rev 236803)
+++ trunk/Source/WTF/wtf/text/StringConcatenate.h 2018-10-03 18:28:55 UTC (rev 236804)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2010-2018 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -27,6 +27,7 @@
#define StringConcatenate_h
#include <string.h>
+#include <wtf/CheckedArithmetic.h>
#ifndef AtomicString_h
#include <wtf/text/AtomicString.h>
@@ -141,9 +142,7 @@
while (m_characters[length])
++length;
- if (length > std::numeric_limits<unsigned>::max()) // FIXME this is silly https://bugs.webkit.org/show_bug.cgi?id=165790
- CRASH();
-
+ RELEASE_ASSERT(length <= String::MaxLength);
m_length = length;
}
@@ -259,24 +258,6 @@
}
};
-inline void sumWithOverflow(bool& overflow, unsigned& total, unsigned addend)
-{
- unsigned oldTotal = total;
- total = oldTotal + addend;
- if (total < oldTotal)
- overflow = true;
-}
-
-template<typename... Unsigned>
-inline void sumWithOverflow(bool& overflow, unsigned& total, unsigned addend, Unsigned ...addends)
-{
- unsigned oldTotal = total;
- total = oldTotal + addend;
- if (total < oldTotal)
- overflow = true;
- sumWithOverflow(overflow, total, addends...);
-}
-
template<typename Adapter>
inline bool are8Bit(Adapter adapter)
{
@@ -305,12 +286,13 @@
template<typename StringTypeAdapter, typename... StringTypeAdapters>
String tryMakeStringFromAdapters(StringTypeAdapter adapter, StringTypeAdapters ...adapters)
{
- bool overflow = false;
- unsigned length = adapter.length();
- sumWithOverflow(overflow, length, adapters.length()...);
- if (overflow)
+ static_assert(String::MaxLength == std::numeric_limits<int32_t>::max(), "");
+ auto sum = checkedSum<int32_t>(adapter.length(), adapters.length()...);
+ if (sum.hasOverflowed())
return String();
+ unsigned length = sum.unsafeGet();
+ ASSERT(length <= String::MaxLength);
if (are8Bit(adapter, adapters...)) {
LChar* buffer;
RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer);
Modified: trunk/Source/WTF/wtf/text/StringImpl.h (236803 => 236804)
--- trunk/Source/WTF/wtf/text/StringImpl.h 2018-10-03 18:26:29 UTC (rev 236803)
+++ trunk/Source/WTF/wtf/text/StringImpl.h 2018-10-03 18:28:55 UTC (rev 236804)
@@ -1,6 +1,6 @@
/*
* Copyright (C) 1999 Lars Knoll (kn...@kde.org)
- * Copyright (C) 2005-2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2005-2018 Apple Inc. All rights reserved.
* Copyright (C) 2009 Google Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
@@ -130,6 +130,9 @@
class StringImplShape {
WTF_MAKE_NONCOPYABLE(StringImplShape);
+public:
+ static constexpr unsigned MaxLength = std::numeric_limits<int32_t>::max();
+
protected:
StringImplShape(unsigned refCount, unsigned length, const LChar*, unsigned hashAndFlags);
StringImplShape(unsigned refCount, unsigned length, const UChar*, unsigned hashAndFlags);
@@ -180,6 +183,8 @@
public:
enum BufferOwnership { BufferInternal, BufferOwned, BufferSubstring, BufferExternal };
+ static constexpr unsigned MaxLength = StringImplShape::MaxLength;
+
// The bottom 6 bits in the hash are flags.
static constexpr const unsigned s_flagCount = 6;
private:
Modified: trunk/Source/WTF/wtf/text/WTFString.h (236803 => 236804)
--- trunk/Source/WTF/wtf/text/WTFString.h 2018-10-03 18:26:29 UTC (rev 236803)
+++ trunk/Source/WTF/wtf/text/WTFString.h 2018-10-03 18:28:55 UTC (rev 236804)
@@ -365,6 +365,8 @@
// This is useful for clearing String-based caches.
void clearImplIfNotShared();
+ static constexpr unsigned MaxLength = StringImpl::MaxLength;
+
private:
template<typename CharacterType> void removeInternal(const CharacterType*, unsigned, unsigned);