From a6a22c0dd9a8f9ced88b233c1cb0a5f6ccb4b771 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 11 Apr 2024 14:23:33 -0500 Subject: [PATCH] Handle out-of-bounds component sections (#8323) (#8339) * Handle out-of-bounds component sections Fixes https://github.com/bytecodealliance/wasmtime/issues/8322 * Add a test that trancated component binaries don't cause panics Co-authored-by: Nick Fitzgerald --- crates/environ/src/component/translate.rs | 14 +++++++- tests/all/component_model/aot.rs | 43 +++++++++++++++++++++++ 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/crates/environ/src/component/translate.rs b/crates/environ/src/component/translate.rs index 3eb37bfcc2..60927b9ef6 100644 --- a/crates/environ/src/component/translate.rs +++ b/crates/environ/src/component/translate.rs @@ -4,6 +4,7 @@ use crate::{ EntityIndex, ModuleEnvironment, ModuleTranslation, ModuleTypesBuilder, PrimaryMap, SignatureIndex, Tunables, TypeConvert, WasmHeapType, WasmType, }; +use anyhow::anyhow; use anyhow::{bail, Result}; use indexmap::IndexMap; use std::collections::HashMap; @@ -533,7 +534,18 @@ impl<'a, 'data> Translator<'a, 'data> { self.validator, self.types.module_types_builder(), ) - .translate(parser, &component[range.start..range.end])?; + .translate( + parser, + component.get(range.start..range.end).ok_or_else(|| { + anyhow!( + "section range {}..{} is out of bounds (bound = {})", + range.start, + range.end, + component.len() + ) + .context("wasm component contains an invalid module section") + })?, + )?; let static_idx = self.static_modules.push(translation); self.result .initializers diff --git a/tests/all/component_model/aot.rs b/tests/all/component_model/aot.rs index 5fc5c8890a..8b38ae1515 100644 --- a/tests/all/component_model/aot.rs +++ b/tests/all/component_model/aot.rs @@ -133,3 +133,46 @@ fn detect_precompiled() -> Result<()> { ); Ok(()) } + +#[test] +#[cfg_attr(miri, ignore)] +fn truncated_component_binaries_dont_panic() -> Result<()> { + let engine = super::engine(); + + let binary = wat::parse_str( + r#" + (component + (import "a" (core module $m0 + (import "" "" (func)) + )) + + (core module $m1 + (func (export "")) + ) + (core instance $i1 (instantiate (module $m1))) + (func $f (canon lift (core func $i1 "f"))) + + (component $c1 + (import "f" (func)) + (core module $m2 + (func (export "g")) + ) + (core instance $i2 (instantiate $m2)) + (func (export "g") + (canon lift (core func $i2 "g")) + ) + ) + (instance $i3 (instantiate $c1 (with "f" (func $f)))) + (func (export "g") (alias export $i3 "g")) + ) + "#, + )?; + + // Check that if we feed each truncation of the component binary into + // `Component::new` we don't get any panics. + for i in 1..binary.len() - 1 { + let _ = Component::from_binary(&engine, &binary[0..i]); + } + + Ok(()) +}