diff --git a/src/ir.cc b/src/ir.cc index c6d2b0a2ef..06af03eda6 100644 --- a/src/ir.cc +++ b/src/ir.cc @@ -605,8 +605,13 @@ void MakeTypeBindingReverseMapping( out_reverse_mapping->clear(); out_reverse_mapping->resize(num_types); for (const auto& [name, binding] : bindings) { - assert(static_cast(binding.index) < out_reverse_mapping->size()); - (*out_reverse_mapping)[binding.index] = name; + // A binding index can come straight from the name section's local + // subsection, which is not otherwise range-checked against the function's + // local count, so skip entries that fall outside the mapping instead of + // writing past it. + if (static_cast(binding.index) < out_reverse_mapping->size()) { + (*out_reverse_mapping)[binding.index] = name; + } } } diff --git a/test/binary/bad-name-section-local-index.txt b/test/binary/bad-name-section-local-index.txt new file mode 100644 index 0000000000..51c293832c --- /dev/null +++ b/test/binary/bad-name-section-local-index.txt @@ -0,0 +1,34 @@ +;;; TOOL: run-gen-wasm +;; The name section's local subsection can carry a local index that is out of +;; range for the function it names. The reader accepts such an entry, so +;; MakeTypeBindingReverseMapping used to write past the reverse-mapping vector +;; (heap overflow in a release build, assert in a debug build). The out of range +;; name is now dropped and wasm2wat prints the module unchanged. +magic +version +section(TYPE) { + count[1] + function params[1] i32 results[0] +} +section(FUNCTION) { + count[1] + type[0] +} +section(CODE) { + count[1] + func { locals[0] } +} +section("name") { + section(NAME_LOCALS) { + func_count[1] + index[0] + local_count[1] + index[5] ;; function has a single param (index 0), so 5 is invalid + str("BAD") + } +} +(;; STDOUT ;;; +(module + (type (;0;) (func (param i32))) + (func (;0;) (type 0) (param i32))) +;;; STDOUT ;;)