698: Fix issue with emscripten memory out of range r=bjfish a=bjfish

Fixes #678 

Co-authored-by: Brandon Fish <brandon.j.fish@gmail.com>
This commit is contained in:
bors[bot] 2019-08-19 15:15:12 +00:00 committed by GitHub
commit b1255179e0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 38 additions and 15 deletions

View File

@ -405,11 +405,18 @@ fn store_module_arguments(ctx: &mut Ctx, args: Vec<&str>) -> (u32, u32) {
(argc as u32 - 1, argv_offset) (argc as u32 - 1, argv_offset)
} }
pub fn emscripten_set_up_memory(memory: &Memory, globals: &EmscriptenGlobalsData) { pub fn emscripten_set_up_memory(
memory: &Memory,
globals: &EmscriptenGlobalsData,
) -> Result<(), String> {
let dynamictop_ptr = globals.dynamictop_ptr; let dynamictop_ptr = globals.dynamictop_ptr;
let dynamic_base = globals.dynamic_base; let dynamic_base = globals.dynamic_base;
if (dynamictop_ptr / 4) as usize >= memory.view::<u32>().len() {
return Err("dynamictop_ptr beyond memory len".to_string());
}
memory.view::<u32>()[(dynamictop_ptr / 4) as usize].set(dynamic_base); memory.view::<u32>()[(dynamictop_ptr / 4) as usize].set(dynamic_base);
Ok(())
} }
pub struct EmscriptenGlobalsData { pub struct EmscriptenGlobalsData {
@ -489,7 +496,7 @@ impl EmscriptenGlobals {
static_top += 16; static_top += 16;
let (dynamic_base, dynamictop_ptr) = let (dynamic_base, dynamictop_ptr) =
get_emscripten_metadata(&module).unwrap_or_else(|| { get_emscripten_metadata(&module)?.unwrap_or_else(|| {
let dynamictop_ptr = static_alloc(&mut static_top, 4); let dynamictop_ptr = static_alloc(&mut static_top, 4);
( (
align_memory(align_memory(static_top) + TOTAL_STACK), align_memory(align_memory(static_top) + TOTAL_STACK),
@ -513,7 +520,7 @@ impl EmscriptenGlobals {
} }
}; };
emscripten_set_up_memory(&memory, &data); emscripten_set_up_memory(&memory, &data)?;
let mut null_func_names = vec![]; let mut null_func_names = vec![];
for ( for (

View File

@ -53,15 +53,23 @@ pub fn get_emscripten_memory_size(module: &Module) -> Result<(Pages, Option<Page
/// Assumes values start from the end in this order: /// Assumes values start from the end in this order:
/// Last export: Dynamic Base /// Last export: Dynamic Base
/// Second-to-Last export: Dynamic top pointer /// Second-to-Last export: Dynamic top pointer
pub fn get_emscripten_metadata(module: &Module) -> Option<(u32, u32)> { pub fn get_emscripten_metadata(module: &Module) -> Result<Option<(u32, u32)>, String> {
let max_idx = &module.info().globals.iter().map(|(k, _)| k).max()?; let max_idx = match module.info().globals.iter().map(|(k, _)| k).max() {
let snd_max_idx = &module Some(x) => x,
None => return Ok(None),
};
let snd_max_idx = match module
.info() .info()
.globals .globals
.iter() .iter()
.map(|(k, _)| k) .map(|(k, _)| k)
.filter(|k| k != max_idx) .filter(|k| *k != max_idx)
.max()?; .max()
{
Some(x) => x,
None => return Ok(None),
};
use wasmer_runtime_core::types::{GlobalInit, Initializer::Const, Value::I32}; use wasmer_runtime_core::types::{GlobalInit, Initializer::Const, Value::I32};
if let ( if let (
@ -74,15 +82,23 @@ pub fn get_emscripten_metadata(module: &Module) -> Option<(u32, u32)> {
.. ..
}, },
) = ( ) = (
&module.info().globals[*max_idx], &module.info().globals[max_idx],
&module.info().globals[*snd_max_idx], &module.info().globals[snd_max_idx],
) { ) {
Some(( let dynamic_base = (*dynamic_base as u32).checked_sub(32).ok_or(format!(
align_memory(*dynamic_base as u32 - 32), "emscripten unexpected dynamic_base {}",
align_memory(*dynamictop_ptr as u32 - 32), *dynamic_base as u32
)) ))?;
let dynamictop_ptr = (*dynamictop_ptr as u32).checked_sub(32).ok_or(format!(
"emscripten unexpected dynamictop_ptr {}",
*dynamictop_ptr as u32
))?;
Ok(Some((
align_memory(dynamic_base),
align_memory(dynamictop_ptr),
)))
} else { } else {
None Ok(None)
} }
} }