/* * 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 #include static int check_string(FILE *const f) { varuint32 len; if (varuint32_read(f, &len)) { LOG("%s: varuint32_read failed\n", __func__); return -1; } for (varuint32 i = 0; i < len; i++) { uint8_t byte; if (!fread(&byte, sizeof byte, 1, f)) { LOG("%s: fread(3) failed, feof=%d, ferror=%d\n", __func__, feof(f), ferror(f)); return -1; } } return 0; } static int check_kind(FILE *const f) { uint8_t kind; if (!fread(&kind, sizeof kind, 1, f)) { LOG("%s: fread(3) failed: feof=%d, ferror=%d\n", __func__, feof(f), ferror(f)); return -1; } return 0; } static int check_index(FILE *const f) { varuint32 index; if (varuint32_read(f, &index)) { LOG("%s: varuint32_read failed\n", __func__); return -1; } return 0; } static int check_export_entry(FILE *const f) { if (check_string(f)) { LOG("%s: check_string failed\n", __func__); return -1; } else if (check_kind(f)) { LOG("%s: check_kind failed\n", __func__); return -1; } else if (check_index(f)) { LOG("%s: check_index failed\n", __func__); return -1; } return 0; } static int check(FILE *const f, const unsigned long len) { 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++) if (check_export_entry(f)) { LOG("%s: check_export_entry failed\n", __func__); return -1; } 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_export_check(const struct section *const s, struct nw_mod *const m, const unsigned long len) { FILE *const f = s->f; if (m->sections.export) { 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 (check(f, len)) { LOG("%s: check failed\n", __func__); return -1; } m->sections.export = offset; return 0; }