From 5891e3612478da77788b1aaeeaf0d5d6460f4146 Mon Sep 17 00:00:00 2001 From: Gaurav Chaudhary Date: Sat, 8 Aug 2026 17:28:22 +0530 Subject: [PATCH] wasm2c: reject contradictory imports instead of aborting Preflight ComputeUniqueImports() before codegen and return Result::Error when the same module/field name is imported with different external kinds, instead of hitting UNIMPLEMENTED/abort on valid-but-unlinkable modules. Fixes #2751 Signed-off-by: Gaurav Chaudhary --- src/c-writer.cc | 18 +++++++++++++----- test/wasm2c/contradictory-imports.txt | 9 +++++++++ 2 files changed, 22 insertions(+), 5 deletions(-) create mode 100644 test/wasm2c/contradictory-imports.txt diff --git a/src/c-writer.cc b/src/c-writer.cc index 74252fb59..425b8226f 100644 --- a/src/c-writer.cc +++ b/src/c-writer.cc @@ -378,7 +378,7 @@ class CWriter { void Write(const FuncTypeExpr&); void WriteTagDecls(); void WriteTags(); - void ComputeUniqueImports(); + Result ComputeUniqueImports(); void BeginInstance(); void WriteImports(); void WriteTailCallWeakImports(); @@ -1794,7 +1794,7 @@ void CWriter::WriteTags() { } } -void CWriter::ComputeUniqueImports() { +Result CWriter::ComputeUniqueImports() { using modname_name_pair = std::pair; std::map import_map; for (const Import* import : module_->imports) { @@ -1805,7 +1805,13 @@ void CWriter::ComputeUniqueImports() { modname_name_pair(import->module_name, import->field_name), import); if (!iterator_and_insertion_bool.second) { if (iterator_and_insertion_bool.first->second->kind() != import->kind()) { - UNIMPLEMENTED("contradictory import declaration"); + fprintf(stderr, + "error: contradictory import declaration: \"%s\".\"%s\" is " + "imported as both a %s and a %s\n", + import->module_name.c_str(), import->field_name.c_str(), + GetKindName(iterator_and_insertion_bool.first->second->kind()), + GetKindName(import->kind())); + return Result::Error; } else { fprintf(stderr, "warning: duplicate import declaration \"%s\" \"%s\"\n", import->module_name.c_str(), import->field_name.c_str()); @@ -1822,6 +1828,7 @@ void CWriter::ComputeUniqueImports() { for (const auto& node : import_map) { unique_imports_.push_back(node.second); } + return Result::Ok; } void CWriter::BeginInstance() { @@ -1830,8 +1837,6 @@ void CWriter::BeginInstance() { return; } - ComputeUniqueImports(); - // define names of per-instance imports for (const Import* import : module_->imports) { DefineImportName(import, import->module_name, import->field_name); @@ -6177,6 +6182,9 @@ void CWriter::WriteCSource() { Result CWriter::WriteModule(const Module& module) { WABT_USE(options_); module_ = &module; + + CHECK_RESULT(ComputeUniqueImports()); + WriteCHeader(); WriteCSource(); return result_; diff --git a/test/wasm2c/contradictory-imports.txt b/test/wasm2c/contradictory-imports.txt new file mode 100644 index 000000000..3fd520fa0 --- /dev/null +++ b/test/wasm2c/contradictory-imports.txt @@ -0,0 +1,9 @@ +;;; RUN: %(wat2wasm)s %(in_file)s -o %(temp_file)s.wasm +;;; RUN: %(wasm2c)s %(temp_file)s.wasm -o %(temp_file)s.c +;;; ERROR: 1 +(module + (import "e" "x" (func)) + (import "e" "x" (global i32))) +(;; STDERR ;;; +error: contradictory import declaration: "e"."x" is imported as both a func and a global +;;; STDERR ;;)