Skip to content

Commit

Permalink
Add support for environment variables in the adapter (fastly#400)
Browse files Browse the repository at this point in the history
This copies over the implementation of `environ_get` and
`environ_sizes_get` from the upstream adapter in wasmtime, and enables
the environment variable test for components.
  • Loading branch information
elliottt authored and GeeWee committed Jul 25, 2024
1 parent f26c74f commit 25bedc4
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 10 deletions.
15 changes: 10 additions & 5 deletions cli/tests/integration/env_vars.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
use crate::common::{Test, TestResult};
use crate::{
common::{Test, TestResult},
viceroy_test,
};

#[tokio::test]
async fn env_vars_are_set() -> TestResult {
let resp = Test::using_fixture("env-vars.wasm").against_empty().await?;
viceroy_test!(env_vars_are_set, |is_component| {
let resp = Test::using_fixture("env-vars.wasm")
.adapt_component(is_component)
.against_empty()
.await?;
assert!(resp.status().is_success());
Ok(())
}
});
74 changes: 69 additions & 5 deletions crates/adapter/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,8 @@ impl BumpAlloc {
extern "C" {
#[link_name = "get-arguments"]
fn wasi_cli_get_arguments(rval: *mut WasmStrList);
#[link_name = "get-environment"]
fn wasi_cli_get_environment(rval: *mut StrTupleList);
}

/// Read command-line argument data.
Expand Down Expand Up @@ -435,8 +437,37 @@ pub unsafe extern "C" fn args_sizes_get(argc: *mut Size, argv_buf_size: *mut Siz
/// Read environment variable data.
/// The sizes of the buffers should match that returned by `environ_sizes_get`.
#[no_mangle]
pub unsafe extern "C" fn environ_get(_environ: *mut *mut u8, _nviron_buf: *mut u8) -> Errno {
ERRNO_SUCCESS
pub unsafe extern "C" fn environ_get(environ: *mut *const u8, environ_buf: *mut u8) -> Errno {
State::with(|state| {
let alloc = ImportAlloc::SeparateStringsAndPointers {
strings: BumpAlloc {
base: environ_buf,
len: usize::MAX,
},
pointers: state.temporary_alloc(),
};
let (list, _) = state.with_import_alloc(alloc, || unsafe {
let mut list = StrTupleList {
base: std::ptr::null(),
len: 0,
};
wasi_cli_get_environment(&mut list);
list
});

// Fill in `environ` by walking over the returned `list`. Strings
// are guaranteed to be allocated next to each other with one
// extra byte at the end, so also insert the `=` between keys and
// the `\0` at the end of the env var.
for i in 0..list.len {
let s = list.base.add(i).read();
*environ.add(i) = s.key.ptr;
*s.key.ptr.add(s.key.len).cast_mut() = b'=';
*s.value.ptr.add(s.value.len).cast_mut() = 0;
}

Ok(())
})
}

/// Return environment variable data sizes.
Expand All @@ -445,10 +476,43 @@ pub unsafe extern "C" fn environ_sizes_get(
environc: *mut Size,
environ_buf_size: *mut Size,
) -> Errno {
*environc = 0;
*environ_buf_size = 0;
if !matches!(
get_allocation_state(),
AllocationState::StackAllocated | AllocationState::StateAllocated
) {
*environc = 0;
*environ_buf_size = 0;
return ERRNO_SUCCESS;
}

State::with(|state| {
let alloc = ImportAlloc::CountAndDiscardStrings {
strings_size: 0,
alloc: state.temporary_alloc(),
};
let (len, alloc) = state.with_import_alloc(alloc, || unsafe {
let mut list = StrTupleList {
base: std::ptr::null(),
len: 0,
};
wasi_cli_get_environment(&mut list);
list.len
});
match alloc {
ImportAlloc::CountAndDiscardStrings {
strings_size,
alloc: _,
} => {
*environc = len;
// Account for `=` between keys and a 0-byte at the end of
// each key.
*environ_buf_size = strings_size + 2 * len;
}
_ => unreachable!(),
}

return ERRNO_SUCCESS;
Ok(())
})
}

/// Return the resolution of a clock.
Expand Down
Binary file modified lib/data/viceroy-component-adapter.wasm
Binary file not shown.

0 comments on commit 25bedc4

Please sign in to comment.