Skip to content

Register target features in custom section when using xforms #3967

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 27, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Return an error on invalid section
  • Loading branch information
daxpedda committed May 26, 2024
commit 7bfa18ec9b752f3c0b0fd970cce0af12b58c82d5
5 changes: 3 additions & 2 deletions crates/externref-xform/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
//! goal at least is to have valid wasm modules coming in that don't use
//! `externref` and valid wasm modules going out which use `externref` at the fringes.

use anyhow::{anyhow, bail, Error};
use anyhow::{anyhow, bail, Context as _, Error};
use std::cmp;
use std::collections::{BTreeMap, HashMap, HashSet};
use std::mem;
Expand Down Expand Up @@ -102,7 +102,8 @@ impl Context {
/// we're appending entries.
pub fn prepare(&mut self, module: &mut Module) -> Result<(), Error> {
// Insert reference types to the target features section.
wasm_bindgen_wasm_conventions::insert_target_feature(module, "reference-types");
wasm_bindgen_wasm_conventions::insert_target_feature(module, "reference-types")
.context("failed to parse `target_features` custom section")?;

// Figure out what the maximum index of functions pointers are. We'll
// be adding new entries to the function table later (maybe) so
Expand Down
5 changes: 4 additions & 1 deletion crates/multi-value-xform/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@

#![deny(missing_docs, missing_debug_implementations)]

use anyhow::Context;

/// Run the transformation.
///
/// See the module-level docs for details on the transformation.
Expand All @@ -118,7 +120,8 @@ pub fn run(
to_xform: &[(walrus::FunctionId, usize, Vec<walrus::ValType>)],
) -> Result<Vec<walrus::FunctionId>, anyhow::Error> {
// Insert multi-value to the target features section.
wasm_bindgen_wasm_conventions::insert_target_feature(module, "multivalue");
wasm_bindgen_wasm_conventions::insert_target_feature(module, "multivalue")
.context("failed to parse `target_features` custom section")?;

let mut wrappers = Vec::new();
for (func, return_pointer_index, results) in to_xform {
Expand Down
23 changes: 14 additions & 9 deletions crates/wasm-conventions/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

use std::io::Cursor;

use anyhow::{anyhow, bail, Result};
use anyhow::{anyhow, bail, Context, Result};
use walrus::{
ir::Value, ElementId, FunctionBuilder, FunctionId, FunctionKind, GlobalId, GlobalKind,
InitExpr, MemoryId, Module, RawCustomSection, ValType,
Expand Down Expand Up @@ -152,9 +152,9 @@ pub fn get_or_insert_start_builder(module: &mut Module) -> &mut FunctionBuilder
.builder_mut()
}

pub fn insert_target_feature(module: &mut Module, new_feature: &str) {
pub fn insert_target_feature(module: &mut Module, new_feature: &str) -> Result<()> {
// Taken from <https://github.com/bytecodealliance/wasm-tools/blob/f1898f46bb9d96f0f09682415cb6ccfd6a4dca79/crates/wasmparser/src/limits.rs#L27>.
assert!(new_feature.len() <= 100_000);
anyhow::ensure!(new_feature.len() <= 100_000, "feature name too long");

// Try to find an existing section.
let section = module
Expand All @@ -164,19 +164,22 @@ pub fn insert_target_feature(module: &mut Module, new_feature: &str) {

// If one exists, check if the target feature is already present.
let section = if let Some((_, section)) = section {
let section: &mut RawCustomSection = section.as_any_mut().downcast_mut().unwrap();
let section: &mut RawCustomSection = section
.as_any_mut()
.downcast_mut()
.context("failed to read section")?;
let mut reader = BinaryReader::new(&section.data);
// The first integer contains the target feature count.
let count = reader.read_var_u32().unwrap();
let count = reader.read_var_u32()?;

// Try to find if the target feature is already present.
for _ in 0..count {
// First byte is the prefix.
let prefix_index = reader.current_position();
let prefix = reader.read_u8().unwrap() as u8;
let prefix = reader.read_u8()? as u8;
// Read the feature.
let length = reader.read_var_u32().unwrap();
let feature = reader.read_bytes(length as usize).unwrap();
let length = reader.read_var_u32()?;
let feature = reader.read_bytes(length as usize)?;

// If we found the target feature, we are done here.
if feature == new_feature.as_bytes() {
Expand All @@ -185,7 +188,7 @@ pub fn insert_target_feature(module: &mut Module, new_feature: &str) {
section.data[prefix_index] = b'+';
}

return;
return Ok(());
}
}

Expand Down Expand Up @@ -214,4 +217,6 @@ pub fn insert_target_feature(module: &mut Module, new_feature: &str) {
leb128::write::unsigned(&mut section.data, new_feature.len() as u64).unwrap();
// Lastly the target feature string is inserted.
section.data.extend(new_feature.as_bytes());

Ok(())
}