Skip to content

Commit

Permalink
Fix handling *almost* aligned data globals
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
alexcrichton committed Mar 10, 2018
1 parent 0627c8f commit 6e75d47
Showing 1 changed file with 35 additions and 5 deletions.
40 changes: 35 additions & 5 deletions crates/wasm-bindgen-cli-support/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -148,8 +149,9 @@ fn extract_programs(module: &mut Module) -> Vec<shared::Program> {
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..],
Expand Down Expand Up @@ -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<u8>,
len: usize,
}

fn bytes_to_u32(a: &mut Vec<u8>) -> 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);
}
}

0 comments on commit 6e75d47

Please sign in to comment.