aboutsummaryrefslogtreecommitdiff
path: root/src/interp/linear
diff options
context:
space:
mode:
authorXavier Del Campo Romero <xavi92@disroot.org>2025-11-15 18:50:55 +0100
committerXavier Del Campo Romero <xavi92@disroot.org>2025-11-15 18:50:55 +0100
commitb1034b86023672e6750da49b01a7d429cd8339d0 (patch)
tree6147dac325b2bb062bfb35e0aa09d81f7e5758fe /src/interp/linear
parent0b2a1fd9439d5ab1cdc076d7b9f1e763c4900b74 (diff)
downloadnanowasm-b1034b86023672e6750da49b01a7d429cd8339d0.tar.gz
Check memory linear accesses are within bounds
WebAssembly defines how many pages of linear memory are owned by the instance on startup. This limit can then be bumped via the grow_memory operator. Therefore, accesses outside the defined bounds are considered an exception.
Diffstat (limited to 'src/interp/linear')
-rw-r--r--src/interp/linear/CMakeLists.txt1
-rw-r--r--src/interp/linear/check.c23
-rw-r--r--src/interp/linear/load.c17
-rw-r--r--src/interp/linear/store.c16
4 files changed, 55 insertions, 2 deletions
diff --git a/src/interp/linear/CMakeLists.txt b/src/interp/linear/CMakeLists.txt
index 0f0e056..7ed9e91 100644
--- a/src/interp/linear/CMakeLists.txt
+++ b/src/interp/linear/CMakeLists.txt
@@ -6,6 +6,7 @@
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
target_sources(${PROJECT_NAME} PRIVATE
+ check.c
load.c
store.c
)
diff --git a/src/interp/linear/check.c b/src/interp/linear/check.c
new file mode 100644
index 0000000..f2bea9a
--- /dev/null
+++ b/src/interp/linear/check.c
@@ -0,0 +1,23 @@
+/*
+ * nanowasm, a tiny WebAssembly/Wasm interpreter
+ * Copyright (C) 2023-2025 Xavier Del Campo Romero
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
+#include <nanowasm/nw.h>
+#include <nanowasm/linear.h>
+#include <nw/interp.h>
+#include <nw/mem.h>
+#include <nw/log.h>
+
+int nwp_linear_check(const struct nw_interp *const i,
+ const unsigned long offset, const size_t n)
+{
+ const unsigned long pagesize = 64lu << 10lu,
+ end = i->linear.n_pages * pagesize;
+
+ return offset >= end || n > end || offset >= end - n;
+}
diff --git a/src/interp/linear/load.c b/src/interp/linear/load.c
index afc6154..38294c4 100644
--- a/src/interp/linear/load.c
+++ b/src/interp/linear/load.c
@@ -9,6 +9,7 @@
#include <nanowasm/nw.h>
#include <nanowasm/linear.h>
+#include <nw/linear.h>
#include <nw/interp.h>
#include <nw/mem.h>
#include <nw/log.h>
@@ -17,7 +18,21 @@ enum nw_state nwp_linear_load(struct nw_interp *const i,
struct nw_sm_io *const io, const unsigned long offset)
{
const struct nw_interp_cfg *const cfg = &i->cfg;
- const enum nw_state n = nwp_mem_load(&cfg->linear, io, offset, cfg->user);
+ enum nw_state n;
+
+ if (nwp_linear_check(i, offset, io->n))
+ {
+ static const char *const exc = "out-of-bounds read access to "
+ "linear memory";
+
+#ifdef NW_LOG
+ nwp_log("%s, addr=%#lx, sz=%#lx\n", exc, offset, io->n);
+#endif
+ i->exception = exc;
+ return NW_FATAL;
+ }
+
+ n = nwp_mem_load(&cfg->linear, io, offset, cfg->user);
if (n == NW_FATAL)
{
diff --git a/src/interp/linear/store.c b/src/interp/linear/store.c
index 6edffd9..904b969 100644
--- a/src/interp/linear/store.c
+++ b/src/interp/linear/store.c
@@ -18,7 +18,21 @@ enum nw_state nwp_linear_store(struct nw_interp *const i,
struct nw_sm_io *const io, const unsigned long offset)
{
const struct nw_interp_cfg *const cfg = &i->cfg;
- const enum nw_state n = nwp_mem_store(&cfg->linear, io, offset, cfg->user);
+ enum nw_state n;
+
+ if (nwp_linear_check(i, offset, io->n))
+ {
+ static const char *const exc = "out-of-bounds write access to "
+ "linear memory";
+
+#ifdef NW_LOG
+ nwp_log("%s, addr=%#lx, sz=%#lx\n", exc, offset, io->n);
+#endif
+ i->exception = exc;
+ return NW_FATAL;
+ }
+
+ n = nwp_mem_store(&cfg->linear, io, offset, cfg->user);
if (n == NW_FATAL)
{