summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/interp/interp-inl.h6
-rw-r--r--src/interp/interp.cc38
-rw-r--r--src/interp/interp.h1
-rw-r--r--src/wast-parser.cc65
-rw-r--r--src/wast-parser.h1
-rw-r--r--src/wat-writer.cc6
6 files changed, 71 insertions, 46 deletions
diff --git a/src/interp/interp-inl.h b/src/interp/interp-inl.h
index 9cab1fa9..f10efaab 100644
--- a/src/interp/interp-inl.h
+++ b/src/interp/interp-inl.h
@@ -633,7 +633,11 @@ inline Memory::Ptr Memory::New(interp::Store& store, MemoryType type) {
}
inline bool Memory::IsValidAccess(u64 offset, u64 addend, u64 size) const {
- return offset + addend + size <= data_.size();
+ // FIXME: make this faster.
+ return offset <= data_.size() &&
+ addend <= data_.size() &&
+ size <= data_.size() &&
+ offset + addend + size <= data_.size();
}
inline bool Memory::IsValidAtomicAccess(u64 offset,
diff --git a/src/interp/interp.cc b/src/interp/interp.cc
index 5262edbe..2f5120d2 100644
--- a/src/interp/interp.cc
+++ b/src/interp/interp.cc
@@ -1023,6 +1023,10 @@ Value Thread::Pop() {
return value;
}
+u64 Thread::PopPtr(const Memory::Ptr& memory) {
+ return memory->type().limits.is_64 ? Pop<u64>() : Pop<u32>();
+}
+
template <typename T>
void WABT_VECTORCALL Thread::Push(T value) {
Push(Value::Make(value));
@@ -1187,15 +1191,15 @@ RunResult Thread::StepInternal(Trap::Ptr* out_trap) {
case O::MemoryGrow: {
Memory::Ptr memory{store_, inst_->memories()[instr.imm_u32]};
u64 old_size = memory->PageSize();
- if (Failed(memory->Grow(Pop<u32>()))) {
- if (memory->type().limits.is_64) {
+ if (memory->type().limits.is_64) {
+ if (Failed(memory->Grow(Pop<u64>()))) {
Push<s64>(-1);
} else {
- Push<s32>(-1);
+ Push<u64>(old_size);
}
} else {
- if (memory->type().limits.is_64) {
- Push<u64>(old_size);
+ if (Failed(memory->Grow(Pop<u32>()))) {
+ Push<s32>(-1);
} else {
Push<u32>(old_size);
}
@@ -1754,7 +1758,7 @@ RunResult Thread::DoCall(const Func::Ptr& func, Trap::Ptr* out_trap) {
template <typename T>
RunResult Thread::Load(Instr instr, T* out, Trap::Ptr* out_trap) {
Memory::Ptr memory{store_, inst_->memories()[instr.imm_u32x2.fst]};
- u64 offset = memory->type().limits.is_64 ? Pop<u64>() : Pop<u32>();
+ u64 offset = PopPtr(memory);
TRAP_IF(Failed(memory->Load(offset, instr.imm_u32x2.snd, out)),
StringPrintf("out of bounds memory access: access at %" PRIu64
"+%" PRIzd " >= max value %" PRIu64,
@@ -1777,7 +1781,7 @@ template <typename T, typename V>
RunResult Thread::DoStore(Instr instr, Trap::Ptr* out_trap) {
Memory::Ptr memory{store_, inst_->memories()[instr.imm_u32x2.fst]};
V val = static_cast<V>(Pop<T>());
- u64 offset = memory->type().limits.is_64 ? Pop<u64>() : Pop<u32>();
+ u64 offset = PopPtr(memory);
TRAP_IF(Failed(memory->Store(offset, instr.imm_u32x2.snd, val)),
StringPrintf("out of bounds memory access: access at %" PRIu64
"+%" PRIzd " >= max value %" PRIu64,
@@ -1843,7 +1847,7 @@ RunResult Thread::DoMemoryInit(Instr instr, Trap::Ptr* out_trap) {
auto&& data = inst_->datas()[instr.imm_u32x2.snd];
auto size = Pop<u32>();
auto src = Pop<u32>();
- auto dst = Pop<u32>();
+ auto dst = PopPtr(memory);
TRAP_IF(Failed(memory->Init(dst, data, src, size)),
"out of bounds memory access: memory.init out of bounds");
return RunResult::Ok;
@@ -1857,9 +1861,9 @@ RunResult Thread::DoDataDrop(Instr instr) {
RunResult Thread::DoMemoryCopy(Instr instr, Trap::Ptr* out_trap) {
Memory::Ptr mem_dst{store_, inst_->memories()[instr.imm_u32x2.fst]};
Memory::Ptr mem_src{store_, inst_->memories()[instr.imm_u32x2.snd]};
- auto size = Pop<u32>();
- auto src = Pop<u32>();
- auto dst = Pop<u32>();
+ auto size = PopPtr(mem_src);
+ auto src = PopPtr(mem_src);
+ auto dst = PopPtr(mem_dst);
// TODO: change to "out of bounds"
TRAP_IF(Failed(Memory::Copy(*mem_dst, dst, *mem_src, src, size)),
"out of bounds memory access: memory.copy out of bound");
@@ -1868,9 +1872,9 @@ RunResult Thread::DoMemoryCopy(Instr instr, Trap::Ptr* out_trap) {
RunResult Thread::DoMemoryFill(Instr instr, Trap::Ptr* out_trap) {
Memory::Ptr memory{store_, inst_->memories()[instr.imm_u32]};
- auto size = Pop<u32>();
+ auto size = PopPtr(memory);
auto value = Pop<u32>();
- auto dst = Pop<u32>();
+ auto dst = PopPtr(memory);
TRAP_IF(Failed(memory->Fill(dst, value, size)),
"out of bounds memory access: memory.fill out of bounds");
return RunResult::Ok;
@@ -2151,7 +2155,7 @@ RunResult Thread::DoSimdLoadExtend(Instr instr, Trap::Ptr* out_trap) {
template <typename T, typename V>
RunResult Thread::DoAtomicLoad(Instr instr, Trap::Ptr* out_trap) {
Memory::Ptr memory{store_, inst_->memories()[instr.imm_u32x2.fst]};
- u64 offset = memory->type().limits.is_64 ? Pop<u64>() : Pop<u32>();
+ u64 offset = PopPtr(memory);
V val;
TRAP_IF(Failed(memory->AtomicLoad(offset, instr.imm_u32x2.snd, &val)),
StringPrintf("invalid atomic access at %" PRIaddress "+%u", offset,
@@ -2164,7 +2168,7 @@ template <typename T, typename V>
RunResult Thread::DoAtomicStore(Instr instr, Trap::Ptr* out_trap) {
Memory::Ptr memory{store_, inst_->memories()[instr.imm_u32x2.fst]};
V val = static_cast<V>(Pop<T>());
- u64 offset = memory->type().limits.is_64 ? Pop<u64>() : Pop<u32>();
+ u64 offset = PopPtr(memory);
TRAP_IF(Failed(memory->AtomicStore(offset, instr.imm_u32x2.snd, val)),
StringPrintf("invalid atomic access at %" PRIaddress "+%u", offset,
instr.imm_u32x2.snd));
@@ -2177,7 +2181,7 @@ RunResult Thread::DoAtomicRmw(BinopFunc<T, T> f,
Trap::Ptr* out_trap) {
Memory::Ptr memory{store_, inst_->memories()[instr.imm_u32x2.fst]};
T val = static_cast<T>(Pop<R>());
- u64 offset = memory->type().limits.is_64 ? Pop<u64>() : Pop<u32>();
+ u64 offset = PopPtr(memory);
T old;
TRAP_IF(Failed(memory->AtomicRmw(offset, instr.imm_u32x2.snd, val, f, &old)),
StringPrintf("invalid atomic access at %" PRIaddress "+%u", offset,
@@ -2192,7 +2196,7 @@ RunResult Thread::DoAtomicRmwCmpxchg(Instr instr, Trap::Ptr* out_trap) {
V replace = static_cast<V>(Pop<T>());
V expect = static_cast<V>(Pop<T>());
V old;
- u64 offset = memory->type().limits.is_64 ? Pop<u64>() : Pop<u32>();
+ u64 offset = PopPtr(memory);
TRAP_IF(Failed(memory->AtomicRmwCmpxchg(offset, instr.imm_u32x2.snd, expect,
replace, &old)),
StringPrintf("invalid atomic access at %" PRIaddress "+%u", offset,
diff --git a/src/interp/interp.h b/src/interp/interp.h
index 32f6a73e..b4de72e4 100644
--- a/src/interp/interp.h
+++ b/src/interp/interp.h
@@ -1065,6 +1065,7 @@ class Thread : public Object {
template <typename T>
T WABT_VECTORCALL Pop();
Value Pop();
+ u64 PopPtr(const Memory::Ptr& memory);
template <typename T>
void WABT_VECTORCALL Push(T);
diff --git a/src/wast-parser.cc b/src/wast-parser.cc
index 79085262..872c61c2 100644
--- a/src/wast-parser.cc
+++ b/src/wast-parser.cc
@@ -939,6 +939,22 @@ bool WastParser::ParseAlignOpt(Address* out_align) {
}
}
+Result WastParser::ParseLimitsIndex(Limits* out_limits) {
+ WABT_TRACE(ParseLimitsIndex);
+
+ if (PeekMatch(TokenType::ValueType)) {
+ if (GetToken().type() == Type::I64) {
+ Consume();
+ out_limits->is_64 = true;
+ } else if (GetToken().type() == Type::I32) {
+ Consume();
+ out_limits->is_64 = false;
+ }
+ }
+
+ return Result::Ok;
+}
+
Result WastParser::ParseLimits(Limits* out_limits) {
WABT_TRACE(ParseLimits);
@@ -954,11 +970,6 @@ Result WastParser::ParseLimits(Limits* out_limits) {
out_limits->is_shared = true;
}
- if (PeekMatch(TokenType::ValueType) && GetToken().type() == Type::I64) {
- Consume();
- out_limits->is_64 = true;
- }
-
return Result::Ok;
}
@@ -1387,6 +1398,7 @@ Result WastParser::ParseImportModuleField(Module* module) {
Consume();
ParseBindVarOpt(&name);
auto import = MakeUnique<MemoryImport>(name);
+ CHECK_RESULT(ParseLimitsIndex(&import->memory.page_limits));
CHECK_RESULT(ParseLimits(&import->memory.page_limits));
EXPECT(Rpar);
field = MakeUnique<ImportModuleField>(std::move(import), loc);
@@ -1441,32 +1453,35 @@ Result WastParser::ParseMemoryModuleField(Module* module) {
CheckImportOrdering(module);
auto import = MakeUnique<MemoryImport>(name);
CHECK_RESULT(ParseInlineImport(import.get()));
+ CHECK_RESULT(ParseLimitsIndex(&import->memory.page_limits));
CHECK_RESULT(ParseLimits(&import->memory.page_limits));
auto field =
MakeUnique<ImportModuleField>(std::move(import), GetLocation());
module->AppendField(std::move(field));
- } else if (MatchLpar(TokenType::Data)) {
- auto data_segment_field = MakeUnique<DataSegmentModuleField>(loc);
- DataSegment& data_segment = data_segment_field->data_segment;
- data_segment.memory_var = Var(module->memories.size());
- data_segment.offset.push_back(MakeUnique<ConstExpr>(Const::I32(0)));
- data_segment.offset.back().loc = loc;
- ParseTextListOpt(&data_segment.data);
- EXPECT(Rpar);
-
- auto memory_field = MakeUnique<MemoryModuleField>(loc, name);
- uint32_t byte_size = WABT_ALIGN_UP_TO_PAGE(data_segment.data.size());
- uint32_t page_size = WABT_BYTES_TO_PAGES(byte_size);
- memory_field->memory.page_limits.initial = page_size;
- memory_field->memory.page_limits.max = page_size;
- memory_field->memory.page_limits.has_max = true;
-
- module->AppendField(std::move(memory_field));
- module->AppendField(std::move(data_segment_field));
} else {
auto field = MakeUnique<MemoryModuleField>(loc, name);
- CHECK_RESULT(ParseLimits(&field->memory.page_limits));
- module->AppendField(std::move(field));
+ CHECK_RESULT(ParseLimitsIndex(&field->memory.page_limits));
+ if (MatchLpar(TokenType::Data)) {
+ auto data_segment_field = MakeUnique<DataSegmentModuleField>(loc);
+ DataSegment& data_segment = data_segment_field->data_segment;
+ data_segment.memory_var = Var(module->memories.size());
+ data_segment.offset.push_back(MakeUnique<ConstExpr>(Const::I32(0)));
+ data_segment.offset.back().loc = loc;
+ ParseTextListOpt(&data_segment.data);
+ EXPECT(Rpar);
+
+ uint32_t byte_size = WABT_ALIGN_UP_TO_PAGE(data_segment.data.size());
+ uint32_t page_size = WABT_BYTES_TO_PAGES(byte_size);
+ field->memory.page_limits.initial = page_size;
+ field->memory.page_limits.max = page_size;
+ field->memory.page_limits.has_max = true;
+
+ module->AppendField(std::move(field));
+ module->AppendField(std::move(data_segment_field));
+ } else {
+ CHECK_RESULT(ParseLimits(&field->memory.page_limits));
+ module->AppendField(std::move(field));
+ }
}
AppendInlineExportFields(module, &export_fields, module->memories.size() - 1);
diff --git a/src/wast-parser.h b/src/wast-parser.h
index 57c0264f..b25709de 100644
--- a/src/wast-parser.h
+++ b/src/wast-parser.h
@@ -137,6 +137,7 @@ class WastParser {
Result ParseQuotedText(std::string* text);
bool ParseOffsetOpt(Address* offset);
bool ParseAlignOpt(Address* align);
+ Result ParseLimitsIndex(Limits*);
Result ParseLimits(Limits*);
Result ParseNat(uint64_t*);
diff --git a/src/wat-writer.cc b/src/wat-writer.cc
index aa781f31..5e08af96 100644
--- a/src/wat-writer.cc
+++ b/src/wat-writer.cc
@@ -1267,6 +1267,9 @@ void WatWriter::WriteEvent(const Event& event) {
}
void WatWriter::WriteLimits(const Limits& limits) {
+ if (limits.is_64) {
+ Writef("i64");
+ }
Writef("%" PRIu64, limits.initial);
if (limits.has_max) {
Writef("%" PRIu64, limits.max);
@@ -1274,9 +1277,6 @@ void WatWriter::WriteLimits(const Limits& limits) {
if (limits.is_shared) {
Writef("shared");
}
- if (limits.is_64) {
- Writef("i64");
- }
}
void WatWriter::WriteTable(const Table& table) {