/* * 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 retval *const out) { 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 (out && i == idx) { *out = 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 retval *const out) { #if 0 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, out); #endif return -1; }