/* * 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 #include #include #include #include #include static enum nw_state read_meta(struct nw_interp *const i) { struct nw_find_local *const f = i->state; const struct nw_local_meta *const m = &f->meta; const nw_varuint32 index = f->index - f->entry_i; const enum nw_state n = nwp_stack_read(i, &f->io, f->addr); size_t sz; nw_varuint32 count; if (n) return n; f->addr += sizeof f->meta; count = m->entry_count; if (nwp_type_sz(m->type, &sz)) { static const char *const exc = "invalid type"; i->exception = exc; #ifdef NW_LOG nwp_log("%s: %#x\n", exc, (unsigned)m->type); #endif return NW_FATAL; } else if (index < count) { const size_t offset = sz * index; if (f->addr > ULONG_MAX - offset) { static const char *const exc = "out-of-bounds access to local"; i->exception = exc; #ifdef NW_LOG nwp_log("%s: addr: %lu, offset: %lu\n", exc, (unsigned long)f->addr, (unsigned long)offset); #endif return NW_FATAL; } else if ((f->addr += offset) >= i->fr.local_end) { static const char *const exc = "invalid local index"; i->exception = exc; #ifdef NW_LOG nwp_log("%s: %lu\n", exc, (unsigned long)f->index); #endif return NW_FATAL; } i->next = f->next; } else { const size_t offset = sz * count; f->entry_i += count; if (f->addr > ULONG_MAX - offset) { static const char *const exc = "out-of-bounds access to local"; i->exception = exc; #ifdef NW_LOG nwp_log("%s: addr: %lu, offset: %lu\n", exc, (unsigned long)f->addr, (unsigned long)offset); #endif return NW_FATAL; } else if ((f->addr += offset) >= i->fr.local_end) { static const char *const exc = "invalid local index"; i->exception = exc; #ifdef NW_LOG nwp_log("%s: %lu\n", exc, (unsigned long)f->index); #endif return NW_FATAL; } else { struct nw_sm_io io = {0}; io.buf = &f->meta; io.n = sizeof f->meta; f->io = io; } } return NW_AGAIN; } void nwp_find_local(struct nw_interp *const i, struct nw_find_local *const f, const nw_varuint32 index, enum nw_state (*const next)(struct nw_interp *), void *const args) { const struct nw_find_local fl = {0}; *f = fl; f->index = index; f->next = next; f->addr = i->fr.local_start; f->io.buf = &f->meta; f->io.n = sizeof f->meta; i->state = f; i->args = args; i->next = read_meta; }