[wasm][memory64] Fix decoding of limits values
For memory64, we modified the {consume_resizable_limits} method to support 64-bit LEBs. This method is not only used for memory limits though, and other limits should be unaffected (they are always 32-bit values, even in memory64). This CL refactors decoding such that the {has_maximum} fields are initialized earlier, and flags are only decoded once (in particular not again inside {consume_resizable_limits}. Instead, the caller specifies whether values should be decoded as 32-bit or 64-bit values. R=jkummerow@chromium.org Bug: v8:10949, v8:13401 Change-Id: I2fb76c3efcf153d1490d88c4456de1524fd508b3 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3968482 Reviewed-by: Jakob Kummerow <jkummerow@chromium.org> Commit-Queue: Clemens Backes <clemensb@chromium.org> Cr-Commit-Position: refs/heads/main@{#83849}
This commit is contained in:
parent
8c7c087812
commit
d4e517d6ba
@ -809,25 +809,26 @@ class ModuleDecoderTemplate : public Decoder {
|
||||
break;
|
||||
}
|
||||
table->type = type;
|
||||
uint8_t flags = validate_table_flags("element count");
|
||||
consume_table_flags("element count", &table->has_maximum_size);
|
||||
consume_resizable_limits(
|
||||
"element count", "elements", std::numeric_limits<uint32_t>::max(),
|
||||
&table->initial_size, &table->has_maximum_size,
|
||||
&table->initial_size, table->has_maximum_size,
|
||||
std::numeric_limits<uint32_t>::max(), &table->maximum_size,
|
||||
flags);
|
||||
k32BitLimits);
|
||||
break;
|
||||
}
|
||||
case kExternalMemory: {
|
||||
// ===== Imported memory =============================================
|
||||
if (!AddMemory(module_.get())) break;
|
||||
uint8_t flags = validate_memory_flags(&module_->has_shared_memory,
|
||||
&module_->is_memory64);
|
||||
consume_memory_flags(&module_->has_shared_memory,
|
||||
&module_->is_memory64,
|
||||
&module_->has_maximum_pages);
|
||||
uint32_t max_pages = module_->is_memory64 ? kSpecMaxMemory64Pages
|
||||
: kSpecMaxMemory32Pages;
|
||||
consume_resizable_limits("memory", "pages", max_pages,
|
||||
&module_->initial_pages,
|
||||
&module_->has_maximum_pages, max_pages,
|
||||
&module_->maximum_pages, flags);
|
||||
consume_resizable_limits(
|
||||
"memory", "pages", max_pages, &module_->initial_pages,
|
||||
module_->has_maximum_pages, max_pages, &module_->maximum_pages,
|
||||
module_->is_memory64 ? k64BitLimits : k32BitLimits);
|
||||
break;
|
||||
}
|
||||
case kExternalGlobal: {
|
||||
@ -920,11 +921,12 @@ class ModuleDecoderTemplate : public Decoder {
|
||||
}
|
||||
table->type = table_type;
|
||||
|
||||
uint8_t flags = validate_table_flags("table elements");
|
||||
consume_resizable_limits(
|
||||
"table elements", "elements", std::numeric_limits<uint32_t>::max(),
|
||||
&table->initial_size, &table->has_maximum_size,
|
||||
std::numeric_limits<uint32_t>::max(), &table->maximum_size, flags);
|
||||
consume_table_flags("table elements", &table->has_maximum_size);
|
||||
consume_resizable_limits("table elements", "elements",
|
||||
std::numeric_limits<uint32_t>::max(),
|
||||
&table->initial_size, table->has_maximum_size,
|
||||
std::numeric_limits<uint32_t>::max(),
|
||||
&table->maximum_size, k32BitLimits);
|
||||
|
||||
if (has_initializer) {
|
||||
table->initial_value = consume_init_expr(module_.get(), table_type);
|
||||
@ -938,14 +940,14 @@ class ModuleDecoderTemplate : public Decoder {
|
||||
for (uint32_t i = 0; ok() && i < memory_count; i++) {
|
||||
tracer_.MemoryOffset(pc_offset());
|
||||
if (!AddMemory(module_.get())) break;
|
||||
uint8_t flags = validate_memory_flags(&module_->has_shared_memory,
|
||||
&module_->is_memory64);
|
||||
consume_memory_flags(&module_->has_shared_memory, &module_->is_memory64,
|
||||
&module_->has_maximum_pages);
|
||||
uint32_t max_pages =
|
||||
module_->is_memory64 ? kSpecMaxMemory64Pages : kSpecMaxMemory32Pages;
|
||||
consume_resizable_limits("memory", "pages", max_pages,
|
||||
&module_->initial_pages,
|
||||
&module_->has_maximum_pages, max_pages,
|
||||
&module_->maximum_pages, flags);
|
||||
consume_resizable_limits(
|
||||
"memory", "pages", max_pages, &module_->initial_pages,
|
||||
module_->has_maximum_pages, max_pages, &module_->maximum_pages,
|
||||
module_->is_memory64 ? k64BitLimits : k32BitLimits);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1915,19 +1917,20 @@ class ModuleDecoderTemplate : public Decoder {
|
||||
return index;
|
||||
}
|
||||
|
||||
uint8_t validate_table_flags(const char* name) {
|
||||
void consume_table_flags(const char* name, bool* has_maximum_out) {
|
||||
tracer_.Bytes(pc_, 1);
|
||||
uint8_t flags = consume_u8("table limits flags");
|
||||
tracer_.Description(flags == kNoMaximum ? " no maximum" : " with maximum");
|
||||
tracer_.NextLine();
|
||||
static_assert(kNoMaximum < kWithMaximum);
|
||||
static_assert(kNoMaximum == 0 && kWithMaximum == 1);
|
||||
*has_maximum_out = flags == kWithMaximum;
|
||||
if (V8_UNLIKELY(flags > kWithMaximum)) {
|
||||
errorf(pc() - 1, "invalid %s limits flags", name);
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
uint8_t validate_memory_flags(bool* is_shared_out, bool* is_memory64_out) {
|
||||
void consume_memory_flags(bool* is_shared_out, bool* is_memory64_out,
|
||||
bool* has_maximum_out) {
|
||||
tracer_.Bytes(pc_, 1);
|
||||
uint8_t flags = consume_u8("memory limits flags");
|
||||
// Flags 0..7 are valid (3 bits).
|
||||
@ -1935,10 +1938,11 @@ class ModuleDecoderTemplate : public Decoder {
|
||||
errorf(pc() - 1, "invalid memory limits flags 0x%x", flags);
|
||||
}
|
||||
// Decode the three bits.
|
||||
bool is_memory64 = flags & 0x4;
|
||||
bool is_shared = flags & 0x2;
|
||||
bool has_maximum = flags & 0x1;
|
||||
bool is_shared = flags & 0x2;
|
||||
bool is_memory64 = flags & 0x4;
|
||||
// Store into output parameters.
|
||||
*has_maximum_out = has_maximum;
|
||||
*is_shared_out = is_shared;
|
||||
*is_memory64_out = is_memory64;
|
||||
|
||||
@ -1959,21 +1963,19 @@ class ModuleDecoderTemplate : public Decoder {
|
||||
if (is_memory64) tracer_.Description(" mem64");
|
||||
tracer_.Description(has_maximum ? " with maximum" : " no maximum");
|
||||
tracer_.NextLine();
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
enum ResizableLimitsType : bool { k32BitLimits, k64BitLimits };
|
||||
void consume_resizable_limits(const char* name, const char* units,
|
||||
uint32_t max_initial, uint32_t* initial,
|
||||
bool* has_max, uint32_t max_maximum,
|
||||
uint32_t* maximum, uint8_t flags) {
|
||||
bool has_maximum, uint32_t max_maximum,
|
||||
uint32_t* maximum, ResizableLimitsType type) {
|
||||
const byte* pos = pc();
|
||||
// For memory64 we need to read the numbers as LEB-encoded 64-bit unsigned
|
||||
// integer. All V8 limits are still within uint32_t range though.
|
||||
const bool is_memory64 =
|
||||
flags == kMemory64NoMaximum || flags == kMemory64WithMaximum;
|
||||
uint64_t initial_64 = is_memory64 ? consume_u64v("initial size", tracer_)
|
||||
: consume_u32v("initial size", tracer_);
|
||||
// Note that even if we read the values as 64-bit value, all V8 limits are
|
||||
// still within uint32_t range.
|
||||
uint64_t initial_64 = type == k64BitLimits
|
||||
? consume_u64v("initial size", tracer_)
|
||||
: consume_u32v("initial size", tracer_);
|
||||
if (initial_64 > max_initial) {
|
||||
errorf(pos,
|
||||
"initial %s size (%" PRIu64
|
||||
@ -1983,11 +1985,11 @@ class ModuleDecoderTemplate : public Decoder {
|
||||
*initial = static_cast<uint32_t>(initial_64);
|
||||
tracer_.Description(*initial);
|
||||
tracer_.NextLine();
|
||||
if (flags & 1) {
|
||||
*has_max = true;
|
||||
if (has_maximum) {
|
||||
pos = pc();
|
||||
uint64_t maximum_64 = is_memory64 ? consume_u64v("maximum size", tracer_)
|
||||
: consume_u32v("maximum size", tracer_);
|
||||
uint64_t maximum_64 = type == k64BitLimits
|
||||
? consume_u64v("maximum size", tracer_)
|
||||
: consume_u32v("maximum size", tracer_);
|
||||
if (maximum_64 > max_maximum) {
|
||||
errorf(pos,
|
||||
"maximum %s size (%" PRIu64
|
||||
@ -2003,7 +2005,6 @@ class ModuleDecoderTemplate : public Decoder {
|
||||
tracer_.Description(*maximum);
|
||||
tracer_.NextLine();
|
||||
} else {
|
||||
*has_max = false;
|
||||
*maximum = max_initial;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user