Fix memory max pages (#33)

* Fix memory max pages

* Get rid of calculate_memory_size.
This commit is contained in:
Sergey Pepyakin 2018-02-02 00:44:06 +03:00 committed by Nikolay Volf
parent fa82dee676
commit 106ac7afdb
1 changed files with 47 additions and 17 deletions

View File

@ -111,14 +111,18 @@ impl MemoryInstance {
fn new(limits: ResizableLimits) -> Result<Self, Error> { fn new(limits: ResizableLimits) -> Result<Self, Error> {
check_limits(&limits)?; check_limits(&limits)?;
let maximum_size = match limits.maximum() { let initial_pages = limits.initial();
Some(maximum_pages) if maximum_pages > LINEAR_MEMORY_MAX_PAGES => let maximum_pages = limits.maximum().unwrap_or(LINEAR_MEMORY_MAX_PAGES);
return Err(Error::Memory(format!("maximum memory size must be at most {} pages", LINEAR_MEMORY_MAX_PAGES))),
Some(maximum_pages) => maximum_pages.saturating_mul(LINEAR_MEMORY_PAGE_SIZE), if initial_pages > LINEAR_MEMORY_MAX_PAGES {
None => u32::MAX, return Err(Error::Memory(format!("initial memory size must be at most {} pages", LINEAR_MEMORY_MAX_PAGES)));
}; }
let initial_size = calculate_memory_size(0, limits.initial(), maximum_size) if maximum_pages > LINEAR_MEMORY_MAX_PAGES {
.ok_or_else(|| Error::Memory(format!("initial memory size must be at most {} pages", LINEAR_MEMORY_MAX_PAGES)))?; return Err(Error::Memory(format!("maximum memory size must be at most {} pages", LINEAR_MEMORY_MAX_PAGES)));
}
let maximum_size = maximum_pages.saturating_mul(LINEAR_MEMORY_PAGE_SIZE);
let initial_size = initial_pages.saturating_mul(LINEAR_MEMORY_PAGE_SIZE);
let memory = MemoryInstance { let memory = MemoryInstance {
limits: limits, limits: limits,
@ -274,23 +278,49 @@ impl MemoryInstance {
} }
fn calculate_memory_size(old_size: u32, additional_pages: u32, maximum_size: u32) -> Option<u32> { fn calculate_memory_size(old_size: u32, additional_pages: u32, maximum_size: u32) -> Option<u32> {
additional_pages let size = additional_pages
.checked_mul(LINEAR_MEMORY_PAGE_SIZE) .saturating_mul(LINEAR_MEMORY_PAGE_SIZE);
.and_then(|size| size.checked_add(old_size)) match size.checked_add(old_size) {
.and_then(|size| if size > maximum_size { Some(size) if size <= maximum_size => Some(size),
None _ => None,
} else { }
Some(size)
})
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::MemoryInstance; use super::{MemoryInstance, LINEAR_MEMORY_MAX_PAGES};
use Error; use Error;
use parity_wasm::elements::ResizableLimits; use parity_wasm::elements::ResizableLimits;
#[test]
fn alloc() {
let fixtures = &[
(0, None, true),
(0, Some(0), true),
(1, None, true),
(1, Some(1), true),
(0, Some(1), true),
(1, Some(0), false),
(0, Some(LINEAR_MEMORY_MAX_PAGES), true),
(LINEAR_MEMORY_MAX_PAGES, Some(LINEAR_MEMORY_MAX_PAGES), true),
(LINEAR_MEMORY_MAX_PAGES, Some(0), false),
(LINEAR_MEMORY_MAX_PAGES, None, true),
];
for &(initial, maybe_max, expected_ok) in fixtures {
let result = MemoryInstance::alloc(initial, maybe_max);
if result.is_ok() != expected_ok {
panic!(
"unexpected error, initial={}, max={:?}, expected={}, result={:?}",
initial,
maybe_max,
expected_ok,
result,
);
}
}
}
fn create_memory(initial_content: &[u8]) -> MemoryInstance { fn create_memory(initial_content: &[u8]) -> MemoryInstance {
let mem = MemoryInstance::new(ResizableLimits::new(1, Some(1))) let mem = MemoryInstance::new(ResizableLimits::new(1, Some(1)))
.expect("MemoryInstance created successfuly"); .expect("MemoryInstance created successfuly");