Skip to content

Commit

Permalink
Fix buffer-len handling in the component adapter (#381)
Browse files Browse the repository at this point in the history
* Add a single test that uses the component adapter

* Fix the adapter's handling of BufferLen errors

* Fix the response test to not use invalid buffers for long headers
  • Loading branch information
elliottt authored Jun 11, 2024
1 parent 2925fe0 commit a1f1332
Show file tree
Hide file tree
Showing 13 changed files with 156 additions and 160 deletions.
12 changes: 10 additions & 2 deletions cli/tests/integration/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ pub struct Test {
log_stderr: bool,
via_hyper: bool,
unknown_import_behavior: UnknownImportBehavior,
adapt_component: bool,
}

impl Test {
Expand All @@ -80,6 +81,7 @@ impl Test {
log_stderr: false,
via_hyper: false,
unknown_import_behavior: Default::default(),
adapt_component: false,
}
}

Expand All @@ -100,6 +102,7 @@ impl Test {
log_stderr: false,
via_hyper: false,
unknown_import_behavior: Default::default(),
adapt_component: false,
}
}

Expand Down Expand Up @@ -234,6 +237,12 @@ impl Test {
}
}

/// Automatically adapt the wasm to a component before running.
pub fn adapt_component(mut self) -> Self {
self.adapt_component = true;
self
}

/// Pass the given requests through this test, returning the associated responses.
///
/// A `Test` can be used repeatedly against different requests, either individually (as with
Expand Down Expand Up @@ -276,14 +285,13 @@ impl Test {
self.backends.start_servers().await;
}

let adapt_core_wasm = false;
let ctx = ExecuteCtx::new(
&self.module_path,
ProfilingStrategy::None,
HashSet::new(),
None,
self.unknown_import_behavior,
adapt_core_wasm,
self.adapt_component,
)?
.with_backends(self.backends.backend_configs().await)
.with_dictionaries(self.dictionaries.clone())
Expand Down
10 changes: 10 additions & 0 deletions cli/tests/integration/response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,13 @@ async fn response_works() -> TestResult {
assert_eq!(resp.status(), StatusCode::OK);
Ok(())
}

#[tokio::test(flavor = "multi_thread")]
async fn response_works_component() -> TestResult {
let resp = Test::using_fixture("response.wasm")
.adapt_component()
.against_empty()
.await?;
assert_eq!(resp.status(), StatusCode::OK);
Ok(())
}
2 changes: 1 addition & 1 deletion crates/adapter/src/fastly/cache.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use super::{convert_result, BodyHandle, FastlyStatus, RequestHandle};
use crate::{alloc_result, with_buffer, TrappingUnwrap};
use crate::{alloc_result, TrappingUnwrap};

pub type CacheHandle = u32;

Expand Down
27 changes: 8 additions & 19 deletions crates/adapter/src/fastly/config_store.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use super::FastlyStatus;
use crate::{bindings::fastly::api::config_store, with_buffer, TrappingUnwrap};
use crate::{alloc_result_opt, bindings::fastly::api::config_store, TrappingUnwrap};
use core::slice;

pub type ConfigStoreHandle = u32;
Expand Down Expand Up @@ -32,22 +32,11 @@ pub fn get(
nwritten: *mut usize,
) -> FastlyStatus {
let key = unsafe { slice::from_raw_parts(key, key_len) };
with_buffer!(
value,
value_max_len,
{
config_store::get(
store_handle,
key,
u64::try_from(value_max_len).trapping_unwrap(),
)
},
|res| {
let res = res.ok_or(FastlyStatus::NONE)?;
unsafe {
*nwritten = res.len();
}
std::mem::forget(res)
}
)
alloc_result_opt!(value, value_max_len, nwritten, {
config_store::get(
store_handle,
key,
u64::try_from(value_max_len).trapping_unwrap(),
)
})
}
156 changes: 46 additions & 110 deletions crates/adapter/src/fastly/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// wrappers around these definitions.

use super::{convert_result, FastlyStatus};
use crate::{alloc_result, with_buffer, TrappingUnwrap};
use crate::{alloc_result, alloc_result_opt, handle_buffer_len, with_buffer, TrappingUnwrap};

impl From<crate::bindings::fastly::api::http_types::HttpVersion> for u32 {
fn from(value: crate::bindings::fastly::api::http_types::HttpVersion) -> Self {
Expand Down Expand Up @@ -420,7 +420,7 @@ pub mod fastly_http_body {
)
},
|res| {
let (written, end) = match res {
let (written, end) = match handle_buffer_len!(res, nwritten) {
Some((bytes, next)) => {
let written = bytes.len();
let end = match next {
Expand Down Expand Up @@ -453,24 +453,13 @@ pub mod fastly_http_body {
nwritten: *mut usize,
) -> FastlyStatus {
let name = unsafe { slice::from_raw_parts(name, name_len) };
with_buffer!(
value,
value_max_len,
{
http_body::trailer_value_get(
body_handle,
name,
u64::try_from(value_max_len).trapping_unwrap(),
)
},
|res| {
let res = res.ok_or(FastlyStatus::NONE)?;
unsafe {
*nwritten = res.len();
}
std::mem::forget(res);
}
)
alloc_result_opt!(value, value_max_len, nwritten, {
http_body::trailer_value_get(
body_handle,
name,
u64::try_from(value_max_len).trapping_unwrap(),
)
})
}

#[export_name = "fastly_http_body#trailer_values_get"]
Expand All @@ -497,7 +486,7 @@ pub mod fastly_http_body {
)
},
|res| {
let (written, end) = match res {
let (written, end) = match handle_buffer_len!(res, nwritten) {
Some((bytes, next)) => {
let written = bytes.len();
let end = match next {
Expand Down Expand Up @@ -1093,7 +1082,7 @@ pub mod fastly_http_req {
)
},
|res| {
let (written, end) = match res {
let (written, end) = match handle_buffer_len!(res, nwritten) {
Some((bytes, next)) => {
let written = bytes.len();
let end = match next {
Expand Down Expand Up @@ -1149,7 +1138,7 @@ pub mod fastly_http_req {
)
},
|res| {
let (written, end) = match res {
let (written, end) = match handle_buffer_len!(res, nwritten) {
Some((bytes, next)) => {
let written = bytes.len();
let end = match next {
Expand Down Expand Up @@ -1195,7 +1184,7 @@ pub mod fastly_http_req {
)
},
|res| {
let (written, end) = match res {
let (written, end) = match handle_buffer_len!(res, nwritten) {
Some((bytes, next)) => {
let written = bytes.len();
let end = match next {
Expand Down Expand Up @@ -1243,24 +1232,13 @@ pub mod fastly_http_req {
nwritten: *mut usize,
) -> FastlyStatus {
let name = unsafe { slice::from_raw_parts(name, name_len) };
with_buffer!(
value,
value_max_len,
{
fastly::api::http_req::header_value_get(
req_handle,
name,
u64::try_from(value_max_len).trapping_unwrap(),
)
},
|res| {
let res = res.ok_or(FastlyStatus::NONE)?;
unsafe {
*nwritten = res.len();
}
std::mem::forget(res);
}
)
alloc_result_opt!(value, value_max_len, nwritten, {
fastly::api::http_req::header_value_get(
req_handle,
name,
u64::try_from(value_max_len).trapping_unwrap(),
)
})
}

#[export_name = "fastly_http_req#header_remove"]
Expand Down Expand Up @@ -1748,7 +1726,7 @@ pub mod fastly_http_resp {
)
},
|res| {
let (written, end) = match res {
let (written, end) = match handle_buffer_len!(res, nwritten) {
Some((bytes, next)) => {
let written = bytes.len();
let end = match next {
Expand Down Expand Up @@ -1781,24 +1759,13 @@ pub mod fastly_http_resp {
nwritten: *mut usize,
) -> FastlyStatus {
let name = unsafe { slice::from_raw_parts(name, name_len) };
with_buffer!(
value,
value_max_len,
{
http_resp::header_value_get(
resp_handle,
name,
u64::try_from(value_max_len).trapping_unwrap(),
)
},
|res| {
let res = res.ok_or(FastlyStatus::NONE)?;
unsafe {
*nwritten = res.len();
}
std::mem::forget(res);
}
)
alloc_result_opt!(value, value_max_len, nwritten, {
http_resp::header_value_get(
resp_handle,
name,
u64::try_from(value_max_len).trapping_unwrap(),
)
})
}

#[export_name = "fastly_http_resp#header_values_get"]
Expand All @@ -1825,7 +1792,7 @@ pub mod fastly_http_resp {
)
},
|res| {
let (written, end) = match res {
let (written, end) = match handle_buffer_len!(res, nwritten) {
Some((bytes, next)) => {
let written = bytes.len();
let end = match next {
Expand Down Expand Up @@ -2017,24 +1984,13 @@ pub mod fastly_dictionary {
nwritten: *mut usize,
) -> FastlyStatus {
let key = unsafe { slice::from_raw_parts(key, key_len) };
with_buffer!(
value,
value_max_len,
{
dictionary::get(
dict_handle,
key,
u64::try_from(value_max_len).trapping_unwrap(),
)
},
|res| {
let res = res.ok_or(FastlyStatus::NONE)?;
unsafe {
*nwritten = res.len();
}
std::mem::forget(res)
}
)
alloc_result_opt!(value, value_max_len, nwritten, {
dictionary::get(
dict_handle,
key,
u64::try_from(value_max_len).trapping_unwrap(),
)
})
}
}

Expand Down Expand Up @@ -2405,23 +2361,12 @@ pub mod fastly_secret_store {
plaintext_max_len: usize,
nwritten_out: *mut usize,
) -> FastlyStatus {
with_buffer!(
plaintext_buf,
plaintext_max_len,
{
secret_store::plaintext(
secret_handle,
u64::try_from(plaintext_max_len).trapping_unwrap(),
)
},
|res| {
let res = res.ok_or(FastlyStatus::NONE)?;
unsafe {
*nwritten_out = res.len();
}
std::mem::forget(res);
}
)
alloc_result_opt!(plaintext_buf, plaintext_max_len, nwritten_out, {
secret_store::plaintext(
secret_handle,
u64::try_from(plaintext_max_len).trapping_unwrap(),
)
})
}

#[export_name = "fastly_secret_store#from_bytes"]
Expand Down Expand Up @@ -2564,18 +2509,9 @@ pub mod fastly_backend {
nwritten: *mut usize,
) -> FastlyStatus {
let backend = unsafe { slice::from_raw_parts(backend_ptr, backend_len) };
with_buffer!(
value,
value_max_len,
{ backend::get_override_host(backend, u64::try_from(value_max_len).trapping_unwrap()) },
|res| {
let res = res.ok_or(FastlyStatus::NONE)?;
unsafe {
*nwritten = res.len();
}
std::mem::forget(res);
}
)
alloc_result_opt!(value, value_max_len, nwritten, {
backend::get_override_host(backend, u64::try_from(value_max_len).trapping_unwrap())
})
}

#[export_name = "fastly_backend#get_port"]
Expand Down Expand Up @@ -2796,7 +2732,7 @@ pub mod fastly_purge {
)
},
|res| {
if let Some(res) = res {
if let Some(res) = res? {
unsafe {
*(*options).ret_buf_nwritten_out = res.len();
}
Expand Down
2 changes: 1 addition & 1 deletion crates/adapter/src/fastly/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ impl From<crate::bindings::fastly::api::types::Error> for FastlyStatus {
Error::GenericError => 1,
Error::InvalidArgument => Self::INVALID_ARGUMENT.0,
Error::BadHandle => 3,
Error::BufferLen => 4,
Error::BufferLen(_) => 4,
Error::Unsupported => 5,
Error::BadAlign => 6,
Error::HttpInvalid => 7,
Expand Down
Loading

0 comments on commit a1f1332

Please sign in to comment.