Bug 1594561 - Allow dropped segs with mem/table.init when len=0. r=lth
authorRyan Hunt <rhunt@eqrion.net>
Fri, 15 Nov 2019 17:52:25 +0000
changeset 502754 263c029519073e3d6fff07d791d90f01b609ce82
parent 502753 857a699a808896b2256f85a290326661f36e0491
child 502755 e318a3f2027c8209ddb3afbe312cfe953953d938
push id36823
push usermalexandru@mozilla.com
push dateWed, 20 Nov 2019 09:47:58 +0000
treeherdermozilla-central@79821df17239 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerslth
bugs1594561
milestone72.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 1594561 - Allow dropped segs with mem/table.init when len=0. r=lth This was an ambiguity in the spec between the prose and formalism. The spec interpreter implements it this way. Differential Revision: https://phabricator.services.mozilla.com/D52130
js/src/wasm/WasmInstance.cpp
--- a/js/src/wasm/WasmInstance.cpp
+++ b/js/src/wasm/WasmInstance.cpp
@@ -581,16 +581,22 @@ inline int32_t WasmMemoryFill(T memBase,
 /* static */ int32_t Instance::memInit(Instance* instance, uint32_t dstOffset,
                                        uint32_t srcOffset, uint32_t len,
                                        uint32_t segIndex) {
   MOZ_ASSERT(SASigMemInit.failureMode == FailureMode::FailOnNegI32);
 
   MOZ_RELEASE_ASSERT(size_t(segIndex) < instance->passiveDataSegments_.length(),
                      "ensured by validation");
 
+  // Zero length inits that are out-of-bounds do not trap, even if the segment
+  // has been dropped.
+  if (len == 0) {
+    return 0;
+  }
+
   if (!instance->passiveDataSegments_[segIndex]) {
     JS_ReportErrorNumberASCII(TlsContext.get(), GetErrorMessage, nullptr,
                               JSMSG_WASM_DROPPED_DATA_SEG);
     return -1;
   }
 
   const DataSegment& seg = *instance->passiveDataSegments_[segIndex];
   MOZ_RELEASE_ASSERT(!seg.active());
@@ -606,21 +612,16 @@ inline int32_t WasmMemoryFill(T memBase,
   // to
   //   memoryBase[ dstOffset .. dstOffset + len - 1 ]
 
   // Bounds check and deal with arithmetic overflow.
   uint64_t dstOffsetLimit = uint64_t(dstOffset) + uint64_t(len);
   uint64_t srcOffsetLimit = uint64_t(srcOffset) + uint64_t(len);
 
   if (dstOffsetLimit > memLen || srcOffsetLimit > segLen) {
-    // Zero length inits that are out-of-bounds do not trap.
-    if (len == 0) {
-      return 0;
-    }
-
     JS_ReportErrorNumberASCII(TlsContext.get(), GetErrorMessage, nullptr,
                               JSMSG_WASM_OUT_OF_BOUNDS);
     return -1;
   }
 
   // The required read/write direction is upward, but that is not currently
   // observable as there are no fences nor any read/write protect operation.
   SharedMem<uint8_t*> dataPtr = mem->buffer().dataPointerEither();
@@ -770,16 +771,22 @@ bool Instance::initElems(uint32_t tableI
                                          uint32_t srcOffset, uint32_t len,
                                          uint32_t segIndex,
                                          uint32_t tableIndex) {
   MOZ_ASSERT(SASigTableInit.failureMode == FailureMode::FailOnNegI32);
 
   MOZ_RELEASE_ASSERT(size_t(segIndex) < instance->passiveElemSegments_.length(),
                      "ensured by validation");
 
+  // Zero length inits that are out-of-bounds do not trap, even if the segment
+  // has been dropped.
+  if (len == 0) {
+    return 0;
+  }
+
   if (!instance->passiveElemSegments_[segIndex]) {
     JS_ReportErrorNumberASCII(TlsContext.get(), GetErrorMessage, nullptr,
                               JSMSG_WASM_DROPPED_ELEM_SEG);
     return -1;
   }
 
   const ElemSegment& seg = *instance->passiveElemSegments_[segIndex];
   MOZ_RELEASE_ASSERT(!seg.active());
@@ -794,21 +801,16 @@ bool Instance::initElems(uint32_t tableI
   // to
   //   tableBase[ dstOffset .. dstOffset + len - 1 ]
 
   // Bounds check and deal with arithmetic overflow.
   uint64_t dstOffsetLimit = uint64_t(dstOffset) + uint64_t(len);
   uint64_t srcOffsetLimit = uint64_t(srcOffset) + uint64_t(len);
 
   if (dstOffsetLimit > tableLen || srcOffsetLimit > segLen) {
-    // Zero length inits that are out-of-bounds do not trap.
-    if (len == 0) {
-      return 0;
-    }
-
     JS_ReportErrorNumberASCII(TlsContext.get(), GetErrorMessage, nullptr,
                               JSMSG_WASM_OUT_OF_BOUNDS);
     return -1;
   }
 
   if (!instance->initElems(tableIndex, seg, dstOffset, srcOffset, len)) {
     return -1;  // OOM, which has already been reported.
   }