Bug 1435525 - Baldr: eagerly reject too-big code section sizes and clamp masm reservation size (r=lth)
authorLuke Wagner <luke@mozilla.com>
Wed, 07 Feb 2018 10:06:54 -0600
changeset 402783 687cee80487fc2416b2ecacf8ca8e54de1f72ec2
parent 402782 dc993d9b8464df70efea9bcd1ae99db6162180c0
child 402784 21f35c5ec16771aaf32b82d4afc2f7021dc65fcb
push id33402
push useraciure@mozilla.com
push dateWed, 07 Feb 2018 22:06:27 +0000
treeherdermozilla-central@8cc2427a322c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerslth
bugs1435525
milestone60.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1435525 - Baldr: eagerly reject too-big code section sizes and clamp masm reservation size (r=lth)
js/src/wasm/WasmBinaryConstants.h
js/src/wasm/WasmGenerator.cpp
js/src/wasm/WasmJS.cpp
js/src/wasm/WasmValidate.cpp
--- a/js/src/wasm/WasmBinaryConstants.h
+++ b/js/src/wasm/WasmBinaryConstants.h
@@ -582,17 +582,18 @@ static const unsigned MaxDataSegments   
 static const unsigned MaxElemSegments        = 10000000;
 static const unsigned MaxTableInitialLength  = 10000000;
 static const unsigned MaxStringBytes         =   100000;
 static const unsigned MaxLocals              =    50000;
 static const unsigned MaxParams              =     1000;
 static const unsigned MaxBrTableElems        =  1000000;
 static const unsigned MaxMemoryInitialPages  = 16384;
 static const unsigned MaxMemoryMaximumPages  = 65536;
-static const unsigned MaxModuleBytes         = 1024 * 1024 * 1024;
+static const unsigned MaxCodeSectionBytes    = 1024 * 1024 * 1024;
+static const unsigned MaxModuleBytes         = MaxCodeSectionBytes;
 static const unsigned MaxFunctionBytes       =  7654321;
 
 // A magic value of the FramePointer to indicate after a return to the entry
 // stub that an exception has been caught and that we should throw.
 
 static const unsigned FailFP = 0xbad;
 
 // Asserted by Decoder::readVarU32.
--- a/js/src/wasm/WasmGenerator.cpp
+++ b/js/src/wasm/WasmGenerator.cpp
@@ -206,19 +206,19 @@ ModuleGenerator::init(Metadata* maybeAsm
     if (!funcToCodeRange_.appendN(BAD_CODE_RANGE, env_->funcSigs.length()))
         return false;
 
     // Pre-reserve space for large Vectors to avoid the significant cost of the
     // final reallocs. In particular, the MacroAssembler can be enormous, so be
     // extra conservative. Note, podResizeToFit calls at the end will trim off
     // unneeded capacity.
 
-    uint32_t codeSectionSize = env_->codeSection ? env_->codeSection->size : 0;
-
-    if (!masm_.reserve(size_t(1.2 * EstimateCompiledCodeSize(tier(), codeSectionSize))))
+    size_t codeSectionSize = env_->codeSection ? env_->codeSection->size : 0;
+    size_t estimatedCodeSize = 1.2 * EstimateCompiledCodeSize(tier(), codeSectionSize);
+    if (!masm_.reserve(Min(estimatedCodeSize, MaxCodeBytesPerProcess)))
         return false;
 
     if (!metadataTier_->codeRanges.reserve(2 * env_->numFuncDefs()))
         return false;
 
     const size_t ByteCodesPerCallSite = 10;
     if (!metadataTier_->callSites.reserve(codeSectionSize / ByteCodesPerCallSite))
         return false;
@@ -777,17 +777,17 @@ ModuleGenerator::compileFuncDef(uint32_t
     uint32_t threshold;
     switch (tier()) {
       case Tier::Baseline: threshold = JitOptions.wasmBatchBaselineThreshold; break;
       case Tier::Ion:      threshold = JitOptions.wasmBatchIonThreshold;      break;
       default:             MOZ_CRASH("Invalid tier value");                   break;
     }
 
     batchedBytecode_ += funcBytecodeLength;
-    MOZ_ASSERT(batchedBytecode_ <= MaxModuleBytes);
+    MOZ_ASSERT(batchedBytecode_ <= MaxCodeSectionBytes);
     return batchedBytecode_ <= threshold || launchBatchCompile();
 }
 
 bool
 ModuleGenerator::finishFuncDefs()
 {
     MOZ_ASSERT(!finishedFuncDefs_);
 
--- a/js/src/wasm/WasmJS.cpp
+++ b/js/src/wasm/WasmJS.cpp
@@ -2513,17 +2513,17 @@ class CompileStreamTask : public Promise
 
             if (!StartsCodeSection(envBytes_.begin(), envBytes_.end(), &codeSection_))
                 return true;
 
             uint32_t extraBytes = envBytes_.length() - codeSection_.start;
             if (extraBytes)
                 envBytes_.shrinkTo(codeSection_.start);
 
-            if (codeSection_.size > MaxModuleBytes)
+            if (codeSection_.size > MaxCodeSectionBytes)
                 return rejectAndDestroyBeforeHelperThreadStarted(JSMSG_OUT_OF_MEMORY);
 
             if (!codeBytes_.resize(codeSection_.size))
                 return rejectAndDestroyBeforeHelperThreadStarted(JSMSG_OUT_OF_MEMORY);
 
             codeStreamEnd_ = codeBytes_.begin();
             exclusiveCodeStreamEnd_.lock().get() = codeStreamEnd_;
 
--- a/js/src/wasm/WasmValidate.cpp
+++ b/js/src/wasm/WasmValidate.cpp
@@ -1717,16 +1717,19 @@ wasm::DecodeModuleEnvironment(Decoder& d
         return false;
 
     if (!DecodeElemSection(d, env))
         return false;
 
     if (!d.startSection(SectionId::Code, env, &env->codeSection, "code"))
         return false;
 
+    if (env->codeSection && env->codeSection->size > MaxCodeSectionBytes)
+        return d.fail("code section too big");
+
     return true;
 }
 
 static bool
 DecodeFunctionBody(Decoder& d, const ModuleEnvironment& env, uint32_t funcIndex)
 {
     uint32_t bodySize;
     if (!d.readVarU32(&bodySize))