COMMIT_MESSAGE

 1WebAssembly: enforce size limits
 2

Source/JavaScriptCore/ChangeLog

 12017-05-15 JF Bastien <jfbastien@apple.com>
 2
 3 WebAssembly: enforce size limits
 4 https://bugs.webkit.org/show_bug.cgi?id=165833
 5 <rdar://problem/29760219>
 6
 7 Reviewed by NOBODY (OOPS!).
 8
 9 Use the same limits as V8.
 10
 11 * JavaScriptCore.xcodeproj/project.pbxproj:
 12 * wasm/WasmLimits.h: Added.
 13 * wasm/WasmModuleParser.cpp:
 14 * wasm/WasmParser.h:
 15 (JSC::Wasm::Parser<SuccessType>::consumeUTF8String):
 16
1172017-05-15 Mark Lam <mark.lam@apple.com>
218
319 Rolling out r214038 and r213697: Crashes when using computed properties with rest destructuring and object spread.

Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

20802080 A7FB61001040C38B0017A286 /* PropertyDescriptor.h in Headers */ = {isa = PBXBuildFile; fileRef = A7FB604B103F5EAB0017A286 /* PropertyDescriptor.h */; settings = {ATTRIBUTES = (Private, ); }; };
20812081 A7FCC26D17A0B6AA00786D1A /* FTLSwitchCase.h in Headers */ = {isa = PBXBuildFile; fileRef = A7FCC26C17A0B6AA00786D1A /* FTLSwitchCase.h */; settings = {ATTRIBUTES = (Private, ); }; };
20822082 A8A4748E151A8306004123FF /* libWTF.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A8A4748D151A8306004123FF /* libWTF.a */; };
 2083 AD00659E1ECAC812000CA926 /* WasmLimits.h in Headers */ = {isa = PBXBuildFile; fileRef = AD00659D1ECAC7FE000CA926 /* WasmLimits.h */; settings = {ATTRIBUTES = (Private, ); }; };
20832084 AD2FCBE21DB58DAD00B3E736 /* JSWebAssemblyCompileError.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AD2FCBA61DB58DA400B3E736 /* JSWebAssemblyCompileError.cpp */; };
20842085 AD2FCBE31DB58DAD00B3E736 /* JSWebAssemblyCompileError.h in Headers */ = {isa = PBXBuildFile; fileRef = AD2FCBA71DB58DA400B3E736 /* JSWebAssemblyCompileError.h */; };
20852086 AD2FCBE41DB58DAD00B3E736 /* JSWebAssemblyInstance.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AD2FCBA81DB58DA400B3E736 /* JSWebAssemblyInstance.cpp */; };

47114712 A8A4748D151A8306004123FF /* libWTF.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libWTF.a; sourceTree = BUILT_PRODUCTS_DIR; };
47124713 A8E894310CD0602400367179 /* JSCallbackObjectFunctions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCallbackObjectFunctions.h; sourceTree = "<group>"; };
47134714 A8E894330CD0603F00367179 /* JSGlobalObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSGlobalObject.h; sourceTree = "<group>"; };
 4715 AD00659D1ECAC7FE000CA926 /* WasmLimits.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmLimits.h; sourceTree = "<group>"; };
47144716 AD1CF06816DCAB2D00B97123 /* PropertyTable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PropertyTable.cpp; sourceTree = "<group>"; };
47154717 AD2FCB8C1DB5844000B3E736 /* JSWebAssemblyModule.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JSWebAssemblyModule.cpp; path = js/JSWebAssemblyModule.cpp; sourceTree = "<group>"; };
47164718 AD2FCB8D1DB5844000B3E736 /* JSWebAssemblyModule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JSWebAssemblyModule.h; path = js/JSWebAssemblyModule.h; sourceTree = "<group>"; };

64306432 53F40E8A1D5901BB0099A1B6 /* WasmFunctionParser.h */,
64316433 AD8FF3961EB5BD850087FF82 /* WasmIndexOrName.cpp */,
64326434 AD8FF3951EB5BD850087FF82 /* WasmIndexOrName.h */,
 6435 AD00659D1ECAC7FE000CA926 /* WasmLimits.h */,
64336436 53E9E0A91EAE83DE00FEE251 /* WasmMachineThreads.cpp */,
64346437 53E9E0AA1EAE83DE00FEE251 /* WasmMachineThreads.h */,
64356438 535557151D9DFA32006D583B /* WasmMemory.cpp */,

94699472 0F1FB38F1E173A6700A9BE50 /* SynchronousStopTheWorldMutatorScheduler.h in Headers */,
94709473 A784A26411D16622005776AC /* SyntaxChecker.h in Headers */,
94719474 DC7997831CDE9FA0004D4A09 /* TagRegistersMode.h in Headers */,
 9475 AD00659E1ECAC812000CA926 /* WasmLimits.h in Headers */,
94729476 70ECA6081AFDBEA200449739 /* TemplateRegistry.h in Headers */,
94739477 70ECA6091AFDBEA200449739 /* TemplateRegistryKey.h in Headers */,
94749478 95D4261AF4C84CE2ACBAC981 /* TemplateRegistryKeyTable.h in Headers */,

Source/JavaScriptCore/wasm/WasmLimits.h

 1/*
 2 * Copyright (C) 2017 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#pragma once
 27
 28#if ENABLE(WEBASSEMBLY)
 29
 30#include <cstdint>
 31
 32namespace JSC {
 33
 34namespace Wasm {
 35
 36// These limits are arbitrary except that they match the limits imposed
 37// by other browsers' implementation of WebAssembly. It is desirable for
 38// us to accept at least the same inputs.
 39
 40constexpr size_t maxTypes = 1000000;
 41constexpr size_t maxFunctions = 1000000;
 42constexpr size_t maxImports = 100000;
 43constexpr size_t maxExports = 100000;
 44constexpr size_t maxGlobals = 1000000;
 45constexpr size_t maxDataSegments = 100000;
 46
 47constexpr size_t maxStringSize = 100000;
 48constexpr size_t maxModuleSize = 1024 * 1024 * 1024;
 49constexpr size_t maxFunctionSize = 128 * 1024;
 50constexpr size_t maxFunctionParams = 1000;
 51
 52constexpr size_t maxTableEntries = 10000000;
 53
 54} } // namespace JSC::Wasm
 55
 56#endif // ENABLE(WEBASSEMBLY)

Source/JavaScriptCore/wasm/WasmModuleParser.cpp

@@auto ModuleParser::parse() -> Result
5151 uint32_t versionNumber;
5252
5353 WASM_PARSER_FAIL_IF(length() < minSize, "expected a module of at least ", minSize, " bytes");
 54 WASM_PARSER_FAIL_IF(length() > maxModuleSize, "module size ", length(), " is too large, maximum ", maxModuleSize);
5455 WASM_PARSER_FAIL_IF(!consumeCharacter(0) || !consumeString("asm"), "modules doesn't start with '\\0asm'");
5556 WASM_PARSER_FAIL_IF(!parseUInt32(versionNumber), "can't parse version number");
5657 WASM_PARSER_FAIL_IF(versionNumber != expectedVersionNumber, "unexpected version number ", versionNumber, " expected ", expectedVersionNumber);

@@auto ModuleParser::parseType() -> PartialResult
102103 uint32_t count;
103104
104105 WASM_PARSER_FAIL_IF(!parseVarUInt32(count), "can't get Type section's count");
105  WASM_PARSER_FAIL_IF(count == std::numeric_limits<uint32_t>::max(), "Type section's count is too big ", count);
 106 WASM_PARSER_FAIL_IF(count > maxTypes, "Type section's count is too big ", count, " maximum ", maxTypes);
106107 WASM_PARSER_FAIL_IF(!m_info->usedSignatures.tryReserveCapacity(count), "can't allocate enough memory for Type section's ", count, " entries");
107108
108109 for (uint32_t i = 0; i < count; ++i) {

@@auto ModuleParser::parseType() -> PartialResult
113114 WASM_PARSER_FAIL_IF(!parseInt7(type), "can't get ", i, "th Type's type");
114115 WASM_PARSER_FAIL_IF(type != Func, i, "th Type is non-Func ", type);
115116 WASM_PARSER_FAIL_IF(!parseVarUInt32(argumentCount), "can't get ", i, "th Type's argument count");
116  WASM_PARSER_FAIL_IF(argumentCount == std::numeric_limits<uint32_t>::max(), i, "th argument count is too big ", argumentCount);
 117 WASM_PARSER_FAIL_IF(argumentCount > maxFunctionParams, i, "th argument count is too big ", argumentCount, " maximum ", maxFunctionParams);
117118 RefPtr<Signature> maybeSignature = Signature::tryCreate(argumentCount);
118119 WASM_PARSER_FAIL_IF(!maybeSignature, "can't allocate enough memory for Type section's ", i, "th signature");
119120 Ref<Signature> signature = maybeSignature.releaseNonNull();

@@auto ModuleParser::parseImport() -> PartialResult
145146{
146147 uint32_t importCount;
147148 WASM_PARSER_FAIL_IF(!parseVarUInt32(importCount), "can't get Import section's count");
148  WASM_PARSER_FAIL_IF(importCount == std::numeric_limits<uint32_t>::max(), "Import section's count is too big ", importCount);
 149 WASM_PARSER_FAIL_IF(importCount > maxImports, "Import section's count is too big ", importCount, " maximum ", maxImports);
149150 WASM_PARSER_FAIL_IF(!m_info->globals.tryReserveCapacity(importCount), "can't allocate enough memory for ", importCount, " globals"); // FIXME this over-allocates when we fix the FIXMEs below.
150151 WASM_PARSER_FAIL_IF(!m_info->imports.tryReserveCapacity(importCount), "can't allocate enough memory for ", importCount, " imports"); // FIXME this over-allocates when we fix the FIXMEs below.
151152 WASM_PARSER_FAIL_IF(!m_info->importFunctionSignatureIndices.tryReserveCapacity(importCount), "can't allocate enough memory for ", importCount, " import function signatures"); // FIXME this over-allocates when we fix the FIXMEs below.

@@auto ModuleParser::parseFunction() -> PartialResult
211212{
212213 uint32_t count;
213214 WASM_PARSER_FAIL_IF(!parseVarUInt32(count), "can't get Function section's count");
214  WASM_PARSER_FAIL_IF(count == std::numeric_limits<uint32_t>::max(), "Function section's count is too big ", count);
 215 WASM_PARSER_FAIL_IF(count > maxFunctions, "Function section's count is too big ", count, " maximum ", maxFunctions);
215216 WASM_PARSER_FAIL_IF(!m_info->internalFunctionSignatureIndices.tryReserveCapacity(count), "can't allocate enough memory for ", count, " Function signatures");
216217 WASM_PARSER_FAIL_IF(!m_info->functionLocationInBinary.tryReserveCapacity(count), "can't allocate enough memory for ", count, "Function locations");
217218

@@auto ModuleParser::parseGlobal() -> PartialResult
334335{
335336 uint32_t globalCount;
336337 WASM_PARSER_FAIL_IF(!parseVarUInt32(globalCount), "can't get Global section's count");
 338 WASM_PARSER_FAIL_IF(globalCount > maxGlobals, "Global section's count is too big ", globalCount, " maximum ", maxGlobals);
337339 WASM_PARSER_FAIL_IF(!m_info->globals.tryReserveCapacity(globalCount + m_info->firstInternalGlobal), "can't allocate memory for ", globalCount + m_info->firstInternalGlobal, " globals");
338340
339341 for (uint32_t globalIndex = 0; globalIndex < globalCount; ++globalIndex) {

@@auto ModuleParser::parseExport() -> PartialResult
359361{
360362 uint32_t exportCount;
361363 WASM_PARSER_FAIL_IF(!parseVarUInt32(exportCount), "can't get Export section's count");
362  WASM_PARSER_FAIL_IF(exportCount == std::numeric_limits<uint32_t>::max(), "Export section's count is too big ", exportCount);
 364 WASM_PARSER_FAIL_IF(exportCount > maxExports, "Export section's count is too big ", exportCount, " maximum ", maxExports);
363365 WASM_PARSER_FAIL_IF(!m_info->exports.tryReserveCapacity(exportCount), "can't allocate enough memory for ", exportCount, " exports");
364366
365367 HashSet<String> exportNames;

@@auto ModuleParser::parseElement() -> PartialResult
424426
425427 uint32_t elementCount;
426428 WASM_PARSER_FAIL_IF(!parseVarUInt32(elementCount), "can't get Element section's count");
427  WASM_PARSER_FAIL_IF(elementCount == std::numeric_limits<uint32_t>::max(), "Element section's count is too big ", elementCount);
 429 WASM_PARSER_FAIL_IF(elementCount > maxTableEntries, "Element section's count is too big ", elementCount, " maximum ", maxTableEntries);
428430 WASM_PARSER_FAIL_IF(!m_info->elements.tryReserveCapacity(elementCount), "can't allocate memory for ", elementCount, " Elements");
429431 for (unsigned elementNum = 0; elementNum < elementCount; ++elementNum) {
430432 uint32_t tableIndex;

@@auto ModuleParser::parseCode() -> PartialResult
471473 WASM_PARSER_FAIL_IF(!parseVarUInt32(functionSize), "can't get ", i, "th Code function's size");
472474 WASM_PARSER_FAIL_IF(functionSize > length(), "Code function's size ", functionSize, " exceeds the module's size ", length());
473475 WASM_PARSER_FAIL_IF(functionSize > length() - m_offset, "Code function's size ", functionSize, " exceeds the module's remaining size", length() - m_offset);
 476 WASM_PARSER_FAIL_IF(functionSize > maxFunctionSize, "Code function's size ", functionSize, " is too big, maximum ", maxFunctionSize);
474477
475478 m_info->functionLocationInBinary[i].start = m_offset;
476479 m_info->functionLocationInBinary[i].end = m_offset + functionSize;

@@auto ModuleParser::parseData() -> PartialResult
555558 uint32_t segmentCount;
556559 WASM_PARSER_FAIL_IF(!m_info->memory, "Data section cannot exist without a Memory section or Import");
557560 WASM_PARSER_FAIL_IF(!parseVarUInt32(segmentCount), "can't get Data section's count");
558  WASM_PARSER_FAIL_IF(segmentCount == std::numeric_limits<uint32_t>::max(), "Data section's count is too big ", segmentCount);
 561 WASM_PARSER_FAIL_IF(segmentCount > maxDataSegments, "Data section's count is too big ", segmentCount, " maximum ", maxDataSegments);
559562 WASM_PARSER_FAIL_IF(!m_info->data.tryReserveCapacity(segmentCount), "can't allocate enough memory for Data section's ", segmentCount, " segments");
560563
561564 for (uint32_t segmentNumber = 0; segmentNumber < segmentCount; ++segmentNumber) {

Source/JavaScriptCore/wasm/WasmParser.h

3030#include "B3Compilation.h"
3131#include "B3Procedure.h"
3232#include "WasmFormat.h"
 33#include "WasmLimits.h"
3334#include "WasmModuleInformation.h"
3435#include "WasmOps.h"
3536#include "WasmSections.h"

@@ALWAYS_INLINE bool Parser<SuccessType>::consumeUTF8String(Name& result, size_t s
146147{
147148 if (length() < stringLength || m_offset > length() - stringLength)
148149 return false;
 150 if (stringLength > maxStringSize)
 151 return false;
149152 if (!result.tryReserveCapacity(stringLength))
150153 return false;
151154