2018-11-27 04:29:26 +00:00
|
|
|
use byteorder::{ByteOrder, LittleEndian};
|
2018-11-21 04:51:11 +00:00
|
|
|
use crate::webassembly::module::Module;
|
2018-11-26 21:11:01 +00:00
|
|
|
use crate::webassembly::Instance;
|
2018-11-27 04:29:26 +00:00
|
|
|
use libc::stat;
|
2018-12-06 11:32:53 +00:00
|
|
|
use std::ffi::{CStr, CString};
|
2018-11-26 21:15:49 +00:00
|
|
|
use std::os::raw::c_char;
|
2018-11-27 04:28:13 +00:00
|
|
|
use std::slice;
|
2018-12-06 15:20:02 +00:00
|
|
|
use std::mem::size_of;
|
2018-11-26 21:15:49 +00:00
|
|
|
|
2018-11-21 04:51:11 +00:00
|
|
|
/// We check if a provided module is an Emscripten generated one
|
|
|
|
pub fn is_emscripten_module(module: &Module) -> bool {
|
2018-12-06 02:01:52 +00:00
|
|
|
for (module, field) in &module.info.imported_funcs {
|
|
|
|
if field == "_emscripten_memcpy_big" && module == "env" {
|
2018-11-21 04:51:11 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-12-06 11:32:53 +00:00
|
|
|
pub unsafe fn copy_cstr_into_wasm(instance: &Instance, cstr: *const c_char) -> u32 {
|
2018-11-26 21:15:49 +00:00
|
|
|
let s = CStr::from_ptr(cstr).to_str().unwrap();
|
2018-11-28 21:25:08 +00:00
|
|
|
let space_offset = (instance.emscripten_data.as_ref().unwrap().malloc)(s.len() as _, instance);
|
2018-11-26 21:15:49 +00:00
|
|
|
let raw_memory = instance.memory_offset_addr(0, space_offset as _) as *mut u8;
|
2018-11-27 04:28:13 +00:00
|
|
|
let slice = slice::from_raw_parts_mut(raw_memory, s.len());
|
2018-11-26 21:15:49 +00:00
|
|
|
|
|
|
|
for (byte, loc) in s.bytes().zip(slice.iter_mut()) {
|
|
|
|
*loc = byte;
|
|
|
|
}
|
|
|
|
space_offset
|
|
|
|
}
|
|
|
|
|
2018-12-06 11:32:53 +00:00
|
|
|
pub unsafe fn copy_cstr_array_into_wasm(array_count: u32, array: *mut *mut c_char, instance: &Instance) -> u32 {
|
2018-12-06 15:20:02 +00:00
|
|
|
let array_offset = (instance.emscripten_data.as_ref().unwrap().malloc)((array_count as usize * size_of::<u32>()) as _, instance);
|
2018-12-06 11:32:53 +00:00
|
|
|
|
|
|
|
let array_addr = instance.memory_offset_addr(0, array_offset as _) as *mut u32;
|
|
|
|
for i in 0..array_count {
|
|
|
|
let offset = copy_cstr_into_wasm(
|
|
|
|
instance,
|
|
|
|
*array.offset(i as isize)
|
|
|
|
);
|
|
|
|
*array_addr.offset(i as isize) = offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
// let first_arg_addr = instance.memory_offset_addr(0, *array_addr.offset(0) as _) as *const i8;
|
|
|
|
// debug!("###### argv[0] = {:?}", CStr::from_ptr(first_arg_addr));
|
|
|
|
|
|
|
|
array_offset
|
|
|
|
}
|
|
|
|
|
2018-11-27 04:29:26 +00:00
|
|
|
pub unsafe fn copy_terminated_array_of_cstrs(
|
|
|
|
_instance: &mut Instance,
|
|
|
|
cstrs: *mut *mut c_char,
|
|
|
|
) -> u32 {
|
2018-11-26 21:15:49 +00:00
|
|
|
let total_num = {
|
|
|
|
let mut ptr = cstrs;
|
|
|
|
let mut counter = 0;
|
|
|
|
while !(*ptr).is_null() {
|
|
|
|
counter += 1;
|
|
|
|
ptr = ptr.add(1);
|
|
|
|
}
|
|
|
|
counter
|
|
|
|
};
|
2018-11-27 04:29:26 +00:00
|
|
|
debug!(
|
|
|
|
"emscripten::copy_terminated_array_of_cstrs::total_num: {}",
|
|
|
|
total_num
|
|
|
|
);
|
2018-11-26 21:15:49 +00:00
|
|
|
0
|
|
|
|
}
|
|
|
|
|
2018-11-27 03:48:19 +00:00
|
|
|
pub unsafe fn copy_stat_into_wasm(instance: &mut Instance, buf: u32, stat: &stat) {
|
|
|
|
let buf_ptr = instance.memory_offset_addr(0, buf as _) as *mut u8;
|
2018-11-27 04:28:13 +00:00
|
|
|
let buf = slice::from_raw_parts_mut(buf_ptr, 76);
|
2018-11-27 04:29:26 +00:00
|
|
|
|
2018-11-27 03:48:19 +00:00
|
|
|
LittleEndian::write_u32(&mut buf[..], stat.st_dev as _);
|
|
|
|
LittleEndian::write_u32(&mut buf[4..], 0);
|
|
|
|
LittleEndian::write_u32(&mut buf[8..], stat.st_ino as _);
|
|
|
|
LittleEndian::write_u32(&mut buf[12..], stat.st_mode as _);
|
|
|
|
LittleEndian::write_u32(&mut buf[16..], stat.st_nlink as _);
|
|
|
|
LittleEndian::write_u32(&mut buf[20..], stat.st_uid);
|
|
|
|
LittleEndian::write_u32(&mut buf[24..], stat.st_gid);
|
|
|
|
LittleEndian::write_u32(&mut buf[28..], stat.st_rdev as _);
|
|
|
|
LittleEndian::write_u32(&mut buf[32..], 0);
|
|
|
|
LittleEndian::write_u32(&mut buf[36..], stat.st_size as _);
|
|
|
|
LittleEndian::write_u32(&mut buf[40..], 4096);
|
|
|
|
LittleEndian::write_u32(&mut buf[44..], stat.st_blocks as _);
|
|
|
|
LittleEndian::write_u32(&mut buf[48..], stat.st_atime as _);
|
|
|
|
LittleEndian::write_u32(&mut buf[52..], 0);
|
|
|
|
LittleEndian::write_u32(&mut buf[56..], stat.st_mtime as _);
|
|
|
|
LittleEndian::write_u32(&mut buf[60..], 0);
|
|
|
|
LittleEndian::write_u32(&mut buf[64..], stat.st_ctime as _);
|
|
|
|
LittleEndian::write_u32(&mut buf[68..], 0);
|
|
|
|
LittleEndian::write_u32(&mut buf[72..], stat.st_ino as _);
|
|
|
|
}
|
|
|
|
|
2018-11-21 04:51:11 +00:00
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::super::generate_emscripten_env;
|
2018-11-22 04:59:23 +00:00
|
|
|
use super::is_emscripten_module;
|
|
|
|
use crate::webassembly::instantiate;
|
2018-11-21 04:51:11 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn should_detect_emscripten_files() {
|
|
|
|
let wasm_bytes = include_wast2wasm_bytes!("tests/is_emscripten_true.wast");
|
|
|
|
let import_object = generate_emscripten_env();
|
|
|
|
let result_object = instantiate(wasm_bytes, import_object).expect("Not compiled properly");
|
|
|
|
assert!(is_emscripten_module(&result_object.module));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn should_detect_non_emscripten_files() {
|
|
|
|
let wasm_bytes = include_wast2wasm_bytes!("tests/is_emscripten_false.wast");
|
|
|
|
let import_object = generate_emscripten_env();
|
|
|
|
let result_object = instantiate(wasm_bytes, import_object).expect("Not compiled properly");
|
|
|
|
assert!(!is_emscripten_module(&result_object.module));
|
|
|
|
}
|
2018-11-22 04:59:23 +00:00
|
|
|
}
|