From 21a8ff3b3c92b44d9f4c6133f3302e58ee9b4462 Mon Sep 17 00:00:00 2001 From: "Adam C. Foltzer" Date: Thu, 23 Apr 2020 17:30:00 -0700 Subject: [PATCH] don't allow multiple `run_start()`s per instantiation/reset --- .../lucet-runtime-internals/src/c_api.rs | 2 ++ .../lucet-runtime-internals/src/error.rs | 3 +++ .../lucet-runtime-internals/src/instance.rs | 6 ++++++ lucet-runtime/lucet-runtime-tests/src/start.rs | 16 ++++++++++++++++ lucet-runtime/src/c_api.rs | 1 + 5 files changed, 28 insertions(+) diff --git a/lucet-runtime/lucet-runtime-internals/src/c_api.rs b/lucet-runtime/lucet-runtime-internals/src/c_api.rs index 9f9701684..e192d6bb5 100644 --- a/lucet-runtime/lucet-runtime-internals/src/c_api.rs +++ b/lucet-runtime/lucet-runtime-internals/src/c_api.rs @@ -79,6 +79,7 @@ pub enum lucet_error { InstanceNotReturned, InstanceNotYielded, InstanceNeedsStart, + StartAlreadyRun, StartYielded, Internal, Unsupported, @@ -106,6 +107,7 @@ impl From<&Error> for lucet_error { Error::InstanceNotReturned => lucet_error::InstanceNotReturned, Error::InstanceNotYielded => lucet_error::InstanceNotYielded, Error::InstanceNeedsStart => lucet_error::InstanceNeedsStart, + Error::StartAlreadyRun => lucet_error::StartAlreadyRun, Error::StartYielded => lucet_error::StartYielded, Error::InternalError(_) => lucet_error::Internal, Error::Unsupported(_) => lucet_error::Unsupported, diff --git a/lucet-runtime/lucet-runtime-internals/src/error.rs b/lucet-runtime/lucet-runtime-internals/src/error.rs index c878a1e80..2d10271b1 100644 --- a/lucet-runtime/lucet-runtime-internals/src/error.rs +++ b/lucet-runtime/lucet-runtime-internals/src/error.rs @@ -58,6 +58,9 @@ pub enum Error { #[error("`Instance::run_start()` must be run before running other exported functions")] InstanceNeedsStart, + #[error("`Instance::run_start()` called multiple times after a single instantiation or reset")] + StartAlreadyRun, + #[error("Start function yielded")] StartYielded, diff --git a/lucet-runtime/lucet-runtime-internals/src/instance.rs b/lucet-runtime/lucet-runtime-internals/src/instance.rs index 151983f30..9588db0bd 100644 --- a/lucet-runtime/lucet-runtime-internals/src/instance.rs +++ b/lucet-runtime/lucet-runtime-internals/src/instance.rs @@ -541,6 +541,9 @@ impl Instance { /// return `Error::StartYielded` if the start function attempts to yield. This should not arise /// as long as the start function does not attempt to use any imported functions. /// + /// This also returns `Error::StartAlreadyRun` if the start function has already run since the + /// instance was created or last reset. + /// /// # Safety /// /// The foreign code safety caveat of [`Instance::run()`][run] @@ -550,6 +553,9 @@ impl Instance { /// [start]: https://webassembly.github.io/spec/core/syntax/modules.html#syntax-start pub fn run_start(&mut self) -> Result<(), Error> { if let Some(start) = self.module.get_start_func()? { + if !self.is_not_started() { + return Err(Error::StartAlreadyRun); + } let res = self.run_func(start, &[])?; if res.is_yielded() { return Err(Error::StartYielded); diff --git a/lucet-runtime/lucet-runtime-tests/src/start.rs b/lucet-runtime/lucet-runtime-tests/src/start.rs index 91e94c331..fe0e8d135 100644 --- a/lucet-runtime/lucet-runtime-tests/src/start.rs +++ b/lucet-runtime/lucet-runtime-tests/src/start.rs @@ -69,6 +69,22 @@ macro_rules! start_tests { } } + #[test] + fn no_start_without_reset() { + let module = test_module_wasm("start", "start_and_call.wat") + .expect("module compiled and loaded"); + let region = TestRegion::create(1, &Limits::default()).expect("region can be created"); + let mut inst = region + .new_instance(module) + .expect("instance can be created"); + + inst.run_start().expect("start section runs"); + match inst.run_start().unwrap_err() { + Error::StartAlreadyRun => (), + e => panic!("unexpected error: {}", e), + } + } + #[test] fn start_and_reset() { let module = test_module_wasm("start", "start_and_call.wat") diff --git a/lucet-runtime/src/c_api.rs b/lucet-runtime/src/c_api.rs index e4affef76..2428636f9 100644 --- a/lucet-runtime/src/c_api.rs +++ b/lucet-runtime/src/c_api.rs @@ -49,6 +49,7 @@ pub extern "C" fn lucet_error_name(e: c_int) -> *const c_char { InstanceNotReturned => "lucet_error_instance_not_returned\0".as_ptr() as _, InstanceNotYielded => "lucet_error_instance_not_yielded\0".as_ptr() as _, InstanceNeedsStart => "lucet_error_instance_needs_start\0".as_ptr() as _, + StartAlreadyRun => "lucet_error_start_already_run\0".as_ptr() as _, StartYielded => "lucet_error_start_yielded\0".as_ptr() as _, Internal => "lucet_error_internal\0".as_ptr() as _, Unsupported => "lucet_error_unsupported\0".as_ptr() as _,