From f25b015e5b668028c34974bbb22faa4105c26690 Mon Sep 17 00:00:00 2001 From: Xavier Del Campo Romero Date: Sun, 26 Nov 2023 22:43:30 +0100 Subject: First commit --- src/section/type.c | 180 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 180 insertions(+) create mode 100644 src/section/type.c (limited to 'src/section/type.c') diff --git a/src/section/type.c b/src/section/type.c new file mode 100644 index 0000000..0bf7a06 --- /dev/null +++ b/src/section/type.c @@ -0,0 +1,180 @@ +/* + * nanowasm, a tiny WebAssembly/Wasm interpreter + * Copyright (C) 2023-2024 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 +#include + +static int check_value_type(FILE *const f, enum value_type *const vtype) +{ + varint7 value_type; + + if (varint7_read(f, &value_type)) + { + LOG("%s: varint7_read failed\n", __func__); + return -1; + } + else if (vtype && get_value_type(value_type, vtype)) + { + LOG("%s: get_value_type failed\n", __func__); + return -1; + } + + return 0; +} + +static int check_func_type(FILE *const f, struct retval *const r) +{ + varint7 form; + varuint32 param_count; + + if (varint7_read(f, &form)) + { + LOG("%s: varint7_read failed\n", __func__); + return -1; + } + else if (varuint32_read(f, ¶m_count)) + { + LOG("%s: varuint32_read failed\n", __func__); + return -1; + } + + for (varuint32 i = 0; i < param_count; i++) + if (check_value_type(f, NULL)) + { + LOG("%s: check_value_type failed\n", __func__); + return -1; + } + + varuint1 return_count; + enum value_type vtype; + + if (varuint1_read(f, &return_count)) + { + LOG("%s: varuint1_read failed\n", __func__); + return -1; + } + else if (return_count && check_value_type(f, &vtype)) + { + LOG("%s: check_value_type 2 failed\n", __func__); + return -1; + } + + *r = (const struct retval) + { + .returns = return_count, + .type = vtype + }; + + return 0; +} + +static int run(FILE *const f, const unsigned long len, const varuint32 idx, + struct nw_frame *const fr) +{ + const long start = ftell(f); + varuint32 count; + + if (start < 0) + { + LOG("%s: ftell(3): %s\n", __func__, strerror(errno)); + return -1; + } + else if (varuint32_read(f, &count)) + { + LOG("%s: varuint32_read failed\n", __func__); + return -1; + } + + for (varuint32 i = 0; i < count; i++) + { + struct retval r; + + if (check_func_type(f, &r)) + { + LOG("%s: check_func_type failed\n", __func__); + return -1; + } + else if (fr && i == idx) + { + fr->retval = r; + return 0; + } + } + + const long end = ftell(f); + + if (end < 0) + { + LOG("%s: ftell(3): %s\n", __func__, strerror(errno)); + return -1; + } + + const unsigned long size = end - start; + + if (size != len) + { + LOG("%s: size exceeded (%lu expected, got %lu)\n", + __func__, len, size); + return -1; + } + + return 0; +} + +int section_type_check(const struct section *const s, struct nw_mod *const m, + const unsigned long len) +{ + FILE *const f = s->f; + + if (m->sections.type) + { + LOG("%s: ignoring duplicate section\n", __func__); + return fseek(f, len, SEEK_CUR); + } + + const long offset = ftell(f); + + if (offset < 0) + { + LOG("%s: ftell(3): %s\n", __func__, strerror(errno)); + return -1; + } + else if (run(f, len, 0, NULL)) + { + LOG("%s: check failed\n", __func__); + return -1; + } + + m->sections.type = offset; + return 0; +} + +int section_type_push(FILE *const f, const struct nw_mod *const m, + const varuint32 idx, struct nw_frame *const fr) +{ + const long offset = m->sections.type; + + if (offset <= 0) + { + LOG("%s: function section not found", __func__); + return -1; + } + else if (fseek(f, offset, SEEK_SET)) + { + LOG("%s: fseek(3): %s\n", __func__, strerror(errno)); + return -1; + } + + return run(f, 0, idx, fr); +} -- cgit v1.2.3