From 6e75d4777c9dddfe74abfddcdd6d4d2c764b8493 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 9 Mar 2018 16:09:07 -0800 Subject: [PATCH] Fix handling *almost* aligned data globals Looks like LLD implicitly pads data values with zeros at the end rather than explicitly listing them, this means that we need to read out the last byte, even if it's not 4-byte aligned, as it could still represent a wasm-bindgen-generated 32-bit value. --- crates/wasm-bindgen-cli-support/src/lib.rs | 40 +++++++++++++++++++--- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/crates/wasm-bindgen-cli-support/src/lib.rs b/crates/wasm-bindgen-cli-support/src/lib.rs index 73ce47c5..995fbdd0 100644 --- a/crates/wasm-bindgen-cli-support/src/lib.rs +++ b/crates/wasm-bindgen-cli-support/src/lib.rs @@ -6,6 +6,7 @@ extern crate wasm_gc; use std::char; use std::fs::File; use std::io::Write; +use std::ops::Deref; use std::path::{Path, PathBuf}; use std::slice; @@ -148,8 +149,9 @@ fn extract_programs(module: &mut Module) -> Vec { None => return ret, }; - for entry in data.entries() { - let mut value = bytes_to_u32(entry.value()); + for entry in data.entries_mut() { + let value = bytes_to_u32(entry.value_mut()); + let mut value = &*value; loop { match value.iter().position(|i| i.0 == 0x30d97887) { Some(i) => value = &value[i + 1..], @@ -204,8 +206,36 @@ to open an issue at https://github.com/alexcrichton/wasm-bindgen/issues! #[repr(packed)] struct Unaligned(u32); -fn bytes_to_u32(a: &[u8]) -> &[Unaligned] { - unsafe { - slice::from_raw_parts(a.as_ptr() as *const Unaligned, a.len() / 4) +struct FutzWithAlign<'a> { + data: &'a mut Vec, + len: usize, +} + +fn bytes_to_u32(a: &mut Vec) -> FutzWithAlign { + let prev_len = a.len(); + // Data implicitly contains zeros after it and it looks like LLD exploits + // this. Pad our view into the vector with zeros to make sure that we read + // off everything when we iterate. After we're done iterating though we put + // this back as we found it, hence the newtype wrapper w/ a dtor. + while a.len() % 4 != 0 { + a.push(0); + } + FutzWithAlign { data: a, len: prev_len } +} + +impl<'a> Deref for FutzWithAlign<'a> { + type Target = [Unaligned]; + + fn deref(&self) -> &[Unaligned] { + unsafe { + slice::from_raw_parts(self.data.as_ptr() as *const Unaligned, + self.data.len() / 4) + } + } +} + +impl<'a> Drop for FutzWithAlign<'a> { + fn drop(&mut self) { + self.data.truncate(self.len); } }