Skip to content

Commit

Permalink
Handle overflow errors in Bytes -> Pages conversion
Browse files Browse the repository at this point in the history
  • Loading branch information
webmaster128 committed Dec 10, 2020
1 parent df3a211 commit afc879a
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 5 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
* [#1867](https://github.com/wasmerio/wasmer/pull/1867) Added `Metering::get_remaining_points` and `Metering::set_remaining_points`
* [#1881](https://github.com/wasmerio/wasmer/pull/1881) Added `UnsupportedTarget` error to `CompileError`
* [#1908](https://github.com/wasmerio/wasmer/pull/1908) Implemented `TryFrom<Value<T>>` for `i32`/`u32`/`i64`/`u64`/`f32`/`f64`
* [#1914](https://github.com/wasmerio/wasmer/pull/1914) Implemented `TryFrom<Bytes> for Pages` instead of `From<Bytes> for Pages` to properly handle overflow errors

### Changed

Expand Down
4 changes: 2 additions & 2 deletions lib/vm/src/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ impl Memory for LinearMemory {
unsafe {
let md_ptr = self.get_vm_memory_definition();
let md = md_ptr.as_ref();
Bytes::from(md.current_length).into()
Bytes::from(md.current_length).try_into().unwrap()
}
}

Expand Down Expand Up @@ -376,7 +376,7 @@ impl Memory for LinearMemory {
.checked_add(guard_bytes)
.ok_or_else(|| MemoryError::CouldNotGrow {
current: new_pages,
attempted_delta: Bytes(guard_bytes).into(),
attempted_delta: Bytes(guard_bytes).try_into().unwrap(),
})?;

let mut new_mmap =
Expand Down
46 changes: 43 additions & 3 deletions lib/wasmer-types/src/units.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::lib::std::convert::TryFrom;
use crate::lib::std::fmt;
use crate::lib::std::ops::{Add, Sub};
#[cfg(feature = "enable-serde")]
Expand Down Expand Up @@ -108,9 +109,16 @@ where
}
}

impl From<Bytes> for Pages {
fn from(bytes: Bytes) -> Self {
Self((bytes.0 / WASM_PAGE_SIZE) as u32)
const PAGES_EXCEED_UINT32: &'static str = "Number of pages exceeds uint32 range";

impl TryFrom<Bytes> for Pages {
type Error = &'static str;

fn try_from(bytes: Bytes) -> Result<Self, Self::Error> {
let pages: u32 = (bytes.0 / WASM_PAGE_SIZE)
.try_into()
.or(Err(PAGES_EXCEED_UINT32))?;
Ok(Self(pages))
}
}

Expand All @@ -133,3 +141,35 @@ where
Self(self.0 + rhs.into().0)
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn convert_bytes_to_pages() {
// rounds down
let pages = Pages::try_from(Bytes(0)).unwrap();
assert_eq!(pages, Pages(0));
let pages = Pages::try_from(Bytes(1)).unwrap();
assert_eq!(pages, Pages(0));
let pages = Pages::try_from(Bytes(WASM_PAGE_SIZE - 1)).unwrap();
assert_eq!(pages, Pages(0));
let pages = Pages::try_from(Bytes(WASM_PAGE_SIZE)).unwrap();
assert_eq!(pages, Pages(1));
let pages = Pages::try_from(Bytes(WASM_PAGE_SIZE + 1)).unwrap();
assert_eq!(pages, Pages(1));
let pages = Pages::try_from(Bytes(28 * WASM_PAGE_SIZE + 42)).unwrap();
assert_eq!(pages, Pages(28));
let pages = Pages::try_from(Bytes((u32::MAX as usize) * WASM_PAGE_SIZE)).unwrap();
assert_eq!(pages, Pages(u32::MAX));
let pages = Pages::try_from(Bytes((u32::MAX as usize) * WASM_PAGE_SIZE + 1)).unwrap();
assert_eq!(pages, Pages(u32::MAX));

// Errors when page count cannot be represented as u32
let result = Pages::try_from(Bytes((u32::MAX as usize + 1) * WASM_PAGE_SIZE));
assert_eq!(result.unwrap_err(), "Number of pages exceeds uint32 range");
let result = Pages::try_from(Bytes(usize::MAX));
assert_eq!(result.unwrap_err(), "Number of pages exceeds uint32 range");
}
}

0 comments on commit afc879a

Please sign in to comment.