Title: [224122] trunk/Source/_javascript_Core
Revision
224122
Author
[email protected]
Date
2017-10-27 11:42:27 -0700 (Fri, 27 Oct 2017)

Log Message

WebAssembly: update arbitrary limits to what browsers use
https://bugs.webkit.org/show_bug.cgi?id=178946
<rdar://problem/34257412>
<rdar://problem/34501154>

Reviewed by Saam Barati.

https://github.com/WebAssembly/design/issues/1138 discusses the
arbitrary function size limit, which it turns out Chrome and
Firefox didn't enforce. We didn't use it because it was
ridiculously low and actual programs ran into that limit (bummer
for Edge which just shipped it...). Now that we agree on a high
arbitrary program limit, let's update it! While I'm doing this
there are a few other spots that I polished to use Checked or
better check limits overall.

* wasm/WasmB3IRGenerator.cpp:
(JSC::Wasm::B3IRGenerator::addLocal):
* wasm/WasmFormat.cpp:
(JSC::Wasm::Segment::create):
* wasm/WasmFunctionParser.h:
(JSC::Wasm::FunctionParser<Context>::parse):
* wasm/WasmInstance.cpp:
* wasm/WasmLimits.h:
* wasm/WasmModuleParser.cpp:
(JSC::Wasm::ModuleParser::parseGlobal):
(JSC::Wasm::ModuleParser::parseCode):
(JSC::Wasm::ModuleParser::parseData):
* wasm/WasmSignature.h:
(JSC::Wasm::Signature::allocatedSize):
* wasm/WasmTable.cpp:
(JSC::Wasm::Table::Table):
* wasm/js/JSWebAssemblyTable.cpp:
(JSC::JSWebAssemblyTable::JSWebAssemblyTable):
(JSC::JSWebAssemblyTable::grow):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (224121 => 224122)


--- trunk/Source/_javascript_Core/ChangeLog	2017-10-27 18:38:43 UTC (rev 224121)
+++ trunk/Source/_javascript_Core/ChangeLog	2017-10-27 18:42:27 UTC (rev 224122)
@@ -1,3 +1,41 @@
+2017-10-27  JF Bastien  <[email protected]>
+
+        WebAssembly: update arbitrary limits to what browsers use
+        https://bugs.webkit.org/show_bug.cgi?id=178946
+        <rdar://problem/34257412>
+        <rdar://problem/34501154>
+
+        Reviewed by Saam Barati.
+
+        https://github.com/WebAssembly/design/issues/1138 discusses the
+        arbitrary function size limit, which it turns out Chrome and
+        Firefox didn't enforce. We didn't use it because it was
+        ridiculously low and actual programs ran into that limit (bummer
+        for Edge which just shipped it...). Now that we agree on a high
+        arbitrary program limit, let's update it! While I'm doing this
+        there are a few other spots that I polished to use Checked or
+        better check limits overall.
+
+        * wasm/WasmB3IRGenerator.cpp:
+        (JSC::Wasm::B3IRGenerator::addLocal):
+        * wasm/WasmFormat.cpp:
+        (JSC::Wasm::Segment::create):
+        * wasm/WasmFunctionParser.h:
+        (JSC::Wasm::FunctionParser<Context>::parse):
+        * wasm/WasmInstance.cpp:
+        * wasm/WasmLimits.h:
+        * wasm/WasmModuleParser.cpp:
+        (JSC::Wasm::ModuleParser::parseGlobal):
+        (JSC::Wasm::ModuleParser::parseCode):
+        (JSC::Wasm::ModuleParser::parseData):
+        * wasm/WasmSignature.h:
+        (JSC::Wasm::Signature::allocatedSize):
+        * wasm/WasmTable.cpp:
+        (JSC::Wasm::Table::Table):
+        * wasm/js/JSWebAssemblyTable.cpp:
+        (JSC::JSWebAssemblyTable::JSWebAssemblyTable):
+        (JSC::JSWebAssemblyTable::grow):
+
 2017-10-26  Michael Saboff  <[email protected]>
 
         REGRESSION(r222601): We fail to properly backtrack into a sub pattern of a parenthesis with non-zero minimum

Modified: trunk/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp (224121 => 224122)


--- trunk/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp	2017-10-27 18:38:43 UTC (rev 224121)
+++ trunk/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp	2017-10-27 18:42:27 UTC (rev 224122)
@@ -511,7 +511,10 @@
 
 auto B3IRGenerator::addLocal(Type type, uint32_t count) -> PartialResult
 {
-    WASM_COMPILE_FAIL_IF(!m_locals.tryReserveCapacity(m_locals.size() + count), "can't allocate memory for ", m_locals.size() + count, " locals");
+    Checked<uint32_t, RecordOverflow> totalBytesChecked = count;
+    totalBytesChecked += m_locals.size();
+    uint32_t totalBytes;
+    WASM_COMPILE_FAIL_IF((totalBytesChecked.safeGet(totalBytes) == CheckedState::DidOverflow) || !m_locals.tryReserveCapacity(totalBytes), "can't allocate memory for ", totalBytes, " locals");
 
     for (uint32_t i = 0; i < count; ++i) {
         Variable* local = m_proc.addVariable(toB3Type(type));

Modified: trunk/Source/_javascript_Core/wasm/WasmFormat.cpp (224121 => 224122)


--- trunk/Source/_javascript_Core/wasm/WasmFormat.cpp	2017-10-27 18:38:43 UTC (rev 224121)
+++ trunk/Source/_javascript_Core/wasm/WasmFormat.cpp	2017-10-27 18:42:27 UTC (rev 224122)
@@ -30,6 +30,7 @@
 #if ENABLE(WEBASSEMBLY)
 
 #include "WasmMemory.h"
+#include <wtf/CheckedArithmetic.h>
 #include <wtf/FastMalloc.h>
 
 namespace JSC { namespace Wasm {
@@ -36,7 +37,12 @@
 
 Segment* Segment::create(I32InitExpr offset, uint32_t sizeInBytes)
 {
-    auto allocated = tryFastCalloc(sizeof(Segment) + sizeInBytes, 1);
+    Checked<uint32_t, RecordOverflow> totalBytesChecked = sizeInBytes;
+    totalBytesChecked += sizeof(Segment);
+    uint32_t totalBytes;
+    if (totalBytesChecked.safeGet(totalBytes) == CheckedState::DidOverflow)
+        return nullptr;
+    auto allocated = tryFastCalloc(totalBytes, 1);
     Segment* segment;
     if (!allocated.getValue(segment))
         return nullptr;

Modified: trunk/Source/_javascript_Core/wasm/WasmFunctionParser.h (224121 => 224122)


--- trunk/Source/_javascript_Core/wasm/WasmFunctionParser.h	2017-10-27 18:38:43 UTC (rev 224121)
+++ trunk/Source/_javascript_Core/wasm/WasmFunctionParser.h	2017-10-27 18:42:27 UTC (rev 224122)
@@ -112,7 +112,7 @@
 
     WASM_PARSER_FAIL_IF(!m_context.addArguments(m_signature), "can't add ", m_signature.argumentCount(), " arguments to Function");
     WASM_PARSER_FAIL_IF(!parseVarUInt32(localCount), "can't get local count");
-    WASM_PARSER_FAIL_IF(localCount == std::numeric_limits<uint32_t>::max(), "Function section's local count is too big ", localCount);
+    WASM_PARSER_FAIL_IF(localCount > maxFunctionLocals, "Function section's local count is too big ", localCount, " maximum ", maxFunctionLocals);
 
     for (uint32_t i = 0; i < localCount; ++i) {
         uint32_t numberOfLocals;
@@ -119,7 +119,7 @@
         Type typeOfLocal;
 
         WASM_PARSER_FAIL_IF(!parseVarUInt32(numberOfLocals), "can't get Function's number of locals in group ", i);
-        WASM_PARSER_FAIL_IF(numberOfLocals == std::numeric_limits<uint32_t>::max(), "Function section's ", i, "th local group count is too big ", numberOfLocals);
+        WASM_PARSER_FAIL_IF(numberOfLocals > maxFunctionLocals, "Function section's ", i, "th local group count is too big ", numberOfLocals, " maximum ", maxFunctionLocals);
         WASM_PARSER_FAIL_IF(!parseValueType(typeOfLocal), "can't get Function local's type in group ", i);
         WASM_TRY_ADD_TO_CONTEXT(addLocal(typeOfLocal, numberOfLocals));
     }

Modified: trunk/Source/_javascript_Core/wasm/WasmInstance.cpp (224121 => 224122)


--- trunk/Source/_javascript_Core/wasm/WasmInstance.cpp	2017-10-27 18:38:43 UTC (rev 224121)
+++ trunk/Source/_javascript_Core/wasm/WasmInstance.cpp	2017-10-27 18:42:27 UTC (rev 224122)
@@ -26,17 +26,18 @@
 #include "config.h"
 #include "WasmInstance.h"
 
+#if ENABLE(WEBASSEMBLY)
+
 #include "Register.h"
 #include "WasmModuleInformation.h"
+#include <wtf/CheckedArithmetic.h>
 
-#if ENABLE(WEBASSEMBLY)
-
 namespace JSC { namespace Wasm {
 
 namespace {
 size_t globalMemoryByteSize(Module& module)
 {
-    return module.moduleInformation().globals.size() * sizeof(Register);
+    return (Checked<size_t>(module.moduleInformation().globals.size()) * sizeof(Register)).unsafeGet();
 }
 }
 

Modified: trunk/Source/_javascript_Core/wasm/WasmLimits.h (224121 => 224122)


--- trunk/Source/_javascript_Core/wasm/WasmLimits.h	2017-10-27 18:38:43 UTC (rev 224121)
+++ trunk/Source/_javascript_Core/wasm/WasmLimits.h	2017-10-27 18:42:27 UTC (rev 224122)
@@ -46,6 +46,8 @@
 
 constexpr size_t maxStringSize = 100000;
 constexpr size_t maxModuleSize = 1024 * 1024 * 1024;
+constexpr size_t maxFunctionSize = 7654321;
+constexpr size_t maxFunctionLocals = 50000;
 constexpr size_t maxFunctionParams = 1000;
 
 constexpr size_t maxTableEntries = 10000000;

Modified: trunk/Source/_javascript_Core/wasm/WasmModuleParser.cpp (224121 => 224122)


--- trunk/Source/_javascript_Core/wasm/WasmModuleParser.cpp	2017-10-27 18:38:43 UTC (rev 224121)
+++ trunk/Source/_javascript_Core/wasm/WasmModuleParser.cpp	2017-10-27 18:42:27 UTC (rev 224122)
@@ -340,7 +340,8 @@
     uint32_t globalCount;
     WASM_PARSER_FAIL_IF(!parseVarUInt32(globalCount), "can't get Global section's count");
     WASM_PARSER_FAIL_IF(globalCount > maxGlobals, "Global section's count is too big ", globalCount, " maximum ", maxGlobals);
-    WASM_PARSER_FAIL_IF(!m_info->globals.tryReserveCapacity(globalCount + m_info->firstInternalGlobal), "can't allocate memory for ", globalCount + m_info->firstInternalGlobal, " globals");
+    size_t totalBytes = globalCount + m_info->firstInternalGlobal;
+    WASM_PARSER_FAIL_IF((static_cast<uint32_t>(totalBytes) < globalCount) || !m_info->globals.tryReserveCapacity(totalBytes), "can't allocate memory for ", totalBytes, " globals");
 
     for (uint32_t globalIndex = 0; globalIndex < globalCount; ++globalIndex) {
         Global global;
@@ -474,7 +475,7 @@
         WASM_PARSER_FAIL_IF(!parseVarUInt32(functionSize), "can't get ", i, "th Code function's size");
         WASM_PARSER_FAIL_IF(functionSize > length(), "Code function's size ", functionSize, " exceeds the module's size ", length());
         WASM_PARSER_FAIL_IF(functionSize > length() - m_offset, "Code function's size ", functionSize, " exceeds the module's remaining size", length() - m_offset);
-        WASM_PARSER_FAIL_IF(functionSize > std::numeric_limits<uint32_t>::max(), "Code function's size ", functionSize, " is too big");
+        WASM_PARSER_FAIL_IF(functionSize > maxFunctionSize, "Code function's size ", functionSize, " is too big");
 
         m_info->functionLocationInBinary[i].start = m_offset;
         m_info->functionLocationInBinary[i].end = m_offset + functionSize;
@@ -573,7 +574,7 @@
         WASM_FAIL_IF_HELPER_FAILS(parseInitExpr(initOpcode, initExprBits, initExprType));
         WASM_PARSER_FAIL_IF(initExprType != I32, segmentNumber, "th Data segment's init_expr must produce an i32");
         WASM_PARSER_FAIL_IF(!parseVarUInt32(dataByteLength), "can't get ", segmentNumber, "th Data segment's data byte length");
-        WASM_PARSER_FAIL_IF(dataByteLength == std::numeric_limits<uint32_t>::max(), segmentNumber, "th Data segment's data byte length is too big ", dataByteLength);
+        WASM_PARSER_FAIL_IF(dataByteLength > maxModuleSize, segmentNumber, "th Data segment's data byte length is too big ", dataByteLength, " maximum ", maxModuleSize);
 
         Segment* segment = Segment::create(makeI32InitExpr(initOpcode, initExprBits), dataByteLength);
         WASM_PARSER_FAIL_IF(!segment, "can't allocate enough memory for ", segmentNumber, "th Data segment of size ", dataByteLength);

Modified: trunk/Source/_javascript_Core/wasm/WasmSignature.h (224121 => 224122)


--- trunk/Source/_javascript_Core/wasm/WasmSignature.h	2017-10-27 18:38:43 UTC (rev 224121)
+++ trunk/Source/_javascript_Core/wasm/WasmSignature.h	2017-10-27 18:42:27 UTC (rev 224122)
@@ -31,6 +31,7 @@
 #include "WasmOps.h"
 #include <cstdint>
 #include <cstring>
+#include <wtf/CheckedArithmetic.h>
 #include <wtf/HashMap.h>
 #include <wtf/HashTraits.h>
 #include <wtf/StdLibExtras.h>
@@ -64,9 +65,9 @@
         return i + reinterpret_cast<Type*>(reinterpret_cast<char*>(this) + sizeof(Signature));
     }
     Type* storage(SignatureArgCount i) const { return const_cast<Signature*>(this)->storage(i); }
-    static size_t allocatedSize(SignatureArgCount argCount)
+    static size_t allocatedSize(Checked<SignatureArgCount> argCount)
     {
-        return sizeof(Signature) + (s_retCount + argCount) * sizeof(Type);
+        return (sizeof(Signature) + (s_retCount + argCount) * sizeof(Type)).unsafeGet();
     }
 
 public:

Modified: trunk/Source/_javascript_Core/wasm/WasmTable.cpp (224121 => 224122)


--- trunk/Source/_javascript_Core/wasm/WasmTable.cpp	2017-10-27 18:38:43 UTC (rev 224121)
+++ trunk/Source/_javascript_Core/wasm/WasmTable.cpp	2017-10-27 18:42:27 UTC (rev 224122)
@@ -54,8 +54,8 @@
 
     // FIXME: It might be worth trying to pre-allocate maximum here. The spec recommends doing so.
     // But for now, we're not doing that.
-    m_functions = MallocPtr<Wasm::CallableFunction>::malloc(sizeof(Wasm::CallableFunction) * static_cast<size_t>(size()));
-    m_instances = MallocPtr<Instance*>::malloc(sizeof(Instance*) * static_cast<size_t>(size()));
+    m_functions = MallocPtr<Wasm::CallableFunction>::malloc((sizeof(Wasm::CallableFunction) * Checked<size_t>(size())).unsafeGet());
+    m_instances = MallocPtr<Instance*>::malloc((sizeof(Instance*) * Checked<size_t>(size())).unsafeGet());
     for (uint32_t i = 0; i < size(); ++i) {
         new (&m_functions.get()[i]) CallableFunction();
         ASSERT(m_functions.get()[i].signatureIndex == Wasm::Signature::invalidIndex); // We rely on this in compiled code.

Modified: trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyTable.cpp (224121 => 224122)


--- trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyTable.cpp	2017-10-27 18:38:43 UTC (rev 224121)
+++ trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyTable.cpp	2017-10-27 18:42:27 UTC (rev 224122)
@@ -30,6 +30,7 @@
 
 #include "JSCInlines.h"
 #include "JSWebAssemblyInstance.h"
+#include <wtf/CheckedArithmetic.h>
 
 namespace JSC {
 
@@ -61,7 +62,7 @@
 {
     // FIXME: It might be worth trying to pre-allocate maximum here. The spec recommends doing so.
     // But for now, we're not doing that.
-    m_jsFunctions = MallocPtr<WriteBarrier<JSObject>>::malloc(sizeof(WriteBarrier<JSObject>) * static_cast<size_t>(size()));
+    m_jsFunctions = MallocPtr<WriteBarrier<JSObject>>::malloc((sizeof(WriteBarrier<JSObject>) * Checked<size_t>(size())).unsafeGet());
     for (uint32_t i = 0; i < size(); ++i)
         new(&m_jsFunctions.get()[i]) WriteBarrier<JSObject>();
 }
@@ -100,7 +101,7 @@
         return false;
 
     size_t newSize = grew.value();
-    m_jsFunctions.realloc(sizeof(WriteBarrier<JSObject>) * newSize);
+    m_jsFunctions.realloc((sizeof(WriteBarrier<JSObject>) * Checked<size_t>(newSize)).unsafeGet());
 
     for (size_t i = oldSize; i < newSize; ++i)
         new (&m_jsFunctions.get()[i]) WriteBarrier<JSObject>();
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to