@@ 445,6 445,13 @@ struct Process {
using Pointer = std::pair<bool, uintptr_t>;
auto memory_at(Pointer const) const -> void const*;
auto memory_at(Pointer const) -> void*;
+ inline auto memory_at(size_t const ptr) -> uint8_t*
+ {
+ if (ptr >= (MEM_PAGE_SIZE * memory.size())) {
+ return nullptr;
+ }
+ return memory.front().data() + ptr;
+ }
explicit inline Process(pid_type const p, Core* c, Module const& m)
: pid{p}, core{c}, module{m}, strtab{&m.strings_table}, stack{*this}
@@ 2078,36 2078,41 @@ auto execute(ECALL const, Stack&, ip_type const) -> void
auto execute(SM const op, Stack& stack, ip_type const ip) -> void
{
- auto& registers = stack.frames.back().registers;
- auto const base = get_value(registers, op.instruction.in, ip);
+ auto const base = get_value(stack, op.instruction.in, ip);
auto const offset = op.instruction.immediate;
auto const unit = op.instruction.spec;
auto const copy_size = (1 << unit);
- auto const addr = offset + (base.holds<void>() ? 0 : base.get<uint64_t>());
- auto& memory = stack.proc->memory.front();
+ auto const user_addr = offset + (base.holds<void>() ? 0 : base.get<uint64_t>());
+ auto const addr = stack.proc->memory_at(user_addr);
+ if (addr == nullptr) {
+ auto o = std::ostringstream{};
+ o << "invalid store address: ";
+ o << std::hex << std::setfill('0') << std::setw(16) << user_addr;
+ throw abort_execution{ip, o.str()};
+ }
- auto const in = get_value(registers, op.instruction.out, ip).get<uint64_t>();
+ auto const in = get_value(stack, op.instruction.out, ip).get<uint64_t>();
switch (unit) {
case 0: {
auto const val = static_cast<uint8_t>(in);
- memcpy(memory.data() + addr, &val, copy_size);
+ memcpy(addr, &val, copy_size);
break;
}
case 1: {
auto const val = htole16(static_cast<uint16_t>(in));
- memcpy(memory.data() + addr, &val, copy_size);
+ memcpy(addr, &val, copy_size);
break;
}
case 2: {
auto const val = htole32(static_cast<uint32_t>(in));
- memcpy(memory.data() + addr, &val, copy_size);
+ memcpy(addr, &val, copy_size);
break;
}
case 3: {
auto const val = htole64(static_cast<uint64_t>(in));
- memcpy(memory.data() + addr, &val, copy_size);
+ memcpy(addr, &val, copy_size);
break;
}
case 4:
@@ 2117,39 2122,44 @@ auto execute(SM const op, Stack& stack, ip_type const ip) -> void
}
auto execute(LM const op, Stack& stack, ip_type const ip) -> void
{
- auto& registers = stack.frames.back().registers;
- auto const base = get_value(registers, op.instruction.in, ip);
+ auto const base = get_value(stack, op.instruction.in, ip);
auto const offset = op.instruction.immediate;
auto const unit = op.instruction.spec;
auto const copy_size = (1 << unit);
- auto const addr = offset + (base.holds<void>() ? 0 : base.get<uint64_t>());
- auto& memory = stack.proc->memory.front();
+ auto const user_addr = offset + (base.holds<void>() ? 0 : base.get<uint64_t>());
+ auto const addr = stack.proc->memory_at(user_addr);
+ if (addr == nullptr) {
+ auto o = std::ostringstream{};
+ o << "invalid load address: ";
+ o << std::hex << std::setfill('0') << std::setw(16) << user_addr;
+ throw abort_execution{ip, o.str()};
+ }
- auto out = get_proxy(registers, op.instruction.out, ip);
+ auto out = get_proxy(stack, op.instruction.out, ip);
switch (unit) {
case 0: {
auto val = uint8_t{};
- memcpy(&val, memory.data() + addr, copy_size);
+ memcpy(&val, addr, copy_size);
out = static_cast<uint64_t>(val);
break;
}
case 1: {
auto val = uint16_t{};
- memcpy(&val, memory.data() + addr, copy_size);
+ memcpy(&val, addr, copy_size);
out = static_cast<uint64_t>(le16toh(val));
break;
}
case 2: {
auto val = uint32_t{};
- memcpy(&val, memory.data() + addr, copy_size);
+ memcpy(&val, addr, copy_size);
out = static_cast<uint64_t>(le32toh(val));
break;
}
case 3: {
auto val = uint64_t{};
- memcpy(&val, memory.data() + addr, copy_size);
+ memcpy(&val, addr, copy_size);
out = le64toh(val);
break;
}