diff --git a/runtime/fastly/host-api/fastly.h b/runtime/fastly/host-api/fastly.h index b0d0cb28c6..01998a9595 100644 --- a/runtime/fastly/host-api/fastly.h +++ b/runtime/fastly/host-api/fastly.h @@ -47,8 +47,8 @@ typedef fastly_host_http_response fastly_world_tuple2_handle_handle; #define HEADER_MAX_LEN 69000 #define METHOD_MAX_LEN 1024 #define URI_MAX_LEN 8192 -#define CONFIG_STORE_ENTRY_MAX_LEN 8000 -#define DICTIONARY_ENTRY_MAX_LEN CONFIG_STORE_ENTRY_MAX_LEN +#define CONFIG_STORE_INITIAL_BUF_LEN 512 +#define DICTIONARY_ENTRY_MAX_LEN 8000 // Ensure that all the things we want to use the hostcall buffer for actually // fit into the buffer. diff --git a/runtime/fastly/host-api/host_api.cpp b/runtime/fastly/host-api/host_api.cpp index ab33543bfc..3f701162b7 100644 --- a/runtime/fastly/host-api/host_api.cpp +++ b/runtime/fastly/host-api/host_api.cpp @@ -1619,6 +1619,8 @@ Result> HttpReq::http_req_downstream_tls_cipher_openss auto status = fastly::req_downstream_tls_cipher_openssl_name(reinterpret_cast(ret.ptr), default_size, &ret.len); if (status == FASTLY_HOST_ERROR_BUFFER_LEN) { + // NB(@zkat): ERROR_BUFFER_LEN sets the expected length of the buffer to + // &ret.len, so we use that to inform our resize. ret.ptr = static_cast(cabi_realloc(ret.ptr, default_size, 4, ret.len)); status = fastly::req_downstream_tls_cipher_openssl_name(reinterpret_cast(ret.ptr), ret.len, &ret.len); @@ -1650,6 +1652,8 @@ Result> HttpReq::http_req_downstream_tls_protocol() { auto status = fastly::req_downstream_tls_protocol(reinterpret_cast(ret.ptr), default_size, &ret.len); if (status == FASTLY_HOST_ERROR_BUFFER_LEN) { + // NB(@zkat): ERROR_BUFFER_LEN sets the expected length of the buffer to + // &ret.len, so we use that to inform our resize. ret.ptr = static_cast(cabi_realloc(ret.ptr, default_size, 4, ret.len)); status = fastly::req_downstream_tls_protocol(reinterpret_cast(ret.ptr), ret.len, &ret.len); @@ -1679,6 +1683,8 @@ Result> HttpReq::http_req_downstream_tls_client_hello() ret.ptr = static_cast(cabi_malloc(default_size, 4)); auto status = fastly::req_downstream_tls_client_hello(ret.ptr, default_size, &ret.len); if (status == FASTLY_HOST_ERROR_BUFFER_LEN) { + // NB(@zkat): ERROR_BUFFER_LEN sets the expected length of the buffer to + // &ret.len, so we use that to inform our resize. ret.ptr = static_cast(cabi_realloc(ret.ptr, default_size, 4, ret.len)); status = fastly::req_downstream_tls_client_hello(ret.ptr, ret.len, &ret.len); } @@ -1708,6 +1714,8 @@ Result> HttpReq::http_req_downstream_tls_raw_client_cer ret.ptr = static_cast(cabi_malloc(default_size, 4)); auto status = fastly::req_downstream_tls_raw_client_certificate(ret.ptr, default_size, &ret.len); if (status == FASTLY_HOST_ERROR_BUFFER_LEN) { + // NB(@zkat): ERROR_BUFFER_LEN sets the expected length of the buffer to + // &ret.len, so we use that to inform our resize. ret.ptr = static_cast(cabi_realloc(ret.ptr, default_size, 4, ret.len)); status = fastly::req_downstream_tls_raw_client_certificate(ret.ptr, ret.len, &ret.len); } @@ -1736,6 +1744,8 @@ Result> HttpReq::http_req_downstream_tls_ja3_md5() { ret.ptr = static_cast(cabi_malloc(default_size, 4)); auto status = fastly::req_downstream_tls_ja3_md5(ret.ptr, &ret.len); if (status == FASTLY_HOST_ERROR_BUFFER_LEN) { + // NB(@zkat): ERROR_BUFFER_LEN sets the expected length of the buffer to + // &ret.len, so we use that to inform our resize. ret.ptr = static_cast(cabi_realloc(ret.ptr, default_size, 4, ret.len)); status = fastly::req_downstream_tls_ja3_md5(ret.ptr, &ret.len); } @@ -2686,17 +2696,39 @@ Result ConfigStore::open(std::string_view name) { } Result> ConfigStore::get(std::string_view name) { + return this->get(name, CONFIG_STORE_INITIAL_BUF_LEN); +} + +Result> ConfigStore::get(std::string_view name, + uint32_t initial_buf_len) { TRACE_CALL() Result> res; + uint32_t buf_len{initial_buf_len}; auto name_str = string_view_to_world_string(name); fastly::fastly_world_string ret; fastly::fastly_host_error err; - ret.ptr = static_cast(cabi_malloc(CONFIG_STORE_ENTRY_MAX_LEN, 1)); - if (!convert_result(fastly::config_store_get(this->handle, reinterpret_cast(name_str.ptr), - name_str.len, reinterpret_cast(ret.ptr), - CONFIG_STORE_ENTRY_MAX_LEN, &ret.len), - &err)) { + + ret.ptr = static_cast(cabi_malloc(buf_len, 1)); + + bool succeeded{convert_result( + fastly::config_store_get(this->handle, reinterpret_cast(name_str.ptr), name_str.len, + reinterpret_cast(ret.ptr), buf_len, &ret.len), + &err)}; + + if (!succeeded && err == FASTLY_HOST_ERROR_BUFFER_LEN) { + // NB(@zkat): ERROR_BUFFER_LEN sets the expected length of the buffer to + // &ret.len, so we use that to inform our resize. + buf_len = ret.len; + ret.len = 0; + ret.ptr = static_cast(cabi_realloc(ret.ptr, initial_buf_len, 1, buf_len)); + succeeded = convert_result( + fastly::config_store_get(this->handle, reinterpret_cast(name_str.ptr), name_str.len, + reinterpret_cast(ret.ptr), buf_len, &ret.len), + &err); + } + + if (!succeeded) { cabi_free(ret.ptr); if (error_is_optional_none(err)) { res.emplace(std::nullopt); @@ -2704,7 +2736,7 @@ Result> ConfigStore::get(std::string_view name) { res.emplace_err(err); } } else { - ret.ptr = static_cast(cabi_realloc(ret.ptr, CONFIG_STORE_ENTRY_MAX_LEN, 1, ret.len)); + ret.ptr = static_cast(cabi_realloc(ret.ptr, buf_len, 1, ret.len)); res.emplace(make_host_string(ret)); } @@ -2842,16 +2874,35 @@ FastlyAsyncTask::Handle ObjectStorePendingDelete::async_handle() const { } Result> Secret::plaintext() const { + return this->plaintext(CONFIG_STORE_INITIAL_BUF_LEN); +} + +Result> Secret::plaintext(uint32_t initial_buf_len) const { TRACE_CALL() Result> res; + uint32_t buf_len{initial_buf_len}; fastly::fastly_world_list_u8 ret; fastly::fastly_host_error err; - ret.ptr = static_cast(JS_malloc(CONTEXT, DICTIONARY_ENTRY_MAX_LEN)); - if (!convert_result(fastly::secret_store_plaintext(this->handle, - reinterpret_cast(ret.ptr), - DICTIONARY_ENTRY_MAX_LEN, &ret.len), - &err)) { + ret.ptr = static_cast(JS_malloc(CONTEXT, buf_len)); + bool succeeded{ + convert_result(fastly::secret_store_plaintext(this->handle, reinterpret_cast(ret.ptr), + buf_len, &ret.len), + &err)}; + + if (!succeeded && err == FASTLY_HOST_ERROR_BUFFER_LEN) { + // NB(@zkat): ERROR_BUFFER_LEN sets the expected length of the buffer to + // &ret.len, so we use that to inform our resize. + buf_len = ret.len; + ret.len = 0; + ret.ptr = static_cast(JS_realloc(CONTEXT, ret.ptr, initial_buf_len, buf_len)); + succeeded = + convert_result(fastly::secret_store_plaintext( + this->handle, reinterpret_cast(ret.ptr), buf_len, &ret.len), + &err); + } + + if (!succeeded) { if (error_is_optional_none(err)) { res.emplace(std::nullopt); } else { @@ -2859,8 +2910,7 @@ Result> Secret::plaintext() const { res.emplace_err(err); } } else { - ret.ptr = - static_cast(JS_realloc(CONTEXT, ret.ptr, DICTIONARY_ENTRY_MAX_LEN, ret.len)); + ret.ptr = static_cast(JS_realloc(CONTEXT, ret.ptr, buf_len, ret.len)); res.emplace(make_host_bytes(ret.ptr, ret.len)); } @@ -3363,6 +3413,8 @@ Result CacheHandle::get_user_metadata() { auto status = fastly::cache_get_user_metadata(handle, reinterpret_cast(ret.ptr), default_size, &ret.len); if (status == FASTLY_HOST_ERROR_BUFFER_LEN) { + // NB(@zkat): ERROR_BUFFER_LEN sets the expected length of the buffer to + // &ret.len, so we use that to inform our resize. ret.ptr = static_cast(cabi_realloc(ret.ptr, default_size, 4, ret.len)); status = fastly::cache_get_user_metadata(handle, reinterpret_cast(ret.ptr), ret.len, &ret.len); @@ -4102,6 +4154,8 @@ Result DeviceDetection::lookup(std::string_view user_agent) { reinterpret_cast(user_agent_str.ptr), user_agent_str.len, reinterpret_cast(ret.ptr), default_size, &ret.len); if (status == FASTLY_HOST_ERROR_BUFFER_LEN) { + // NB(@zkat): ERROR_BUFFER_LEN sets the expected length of the buffer to + // &ret.len, so we use that to inform our resize. ret.ptr = static_cast(cabi_realloc(ret.ptr, default_size, 4, ret.len)); status = fastly::device_detection_lookup(reinterpret_cast(user_agent_str.ptr), user_agent_str.len, reinterpret_cast(ret.ptr), diff --git a/runtime/fastly/host-api/host_api_fastly.h b/runtime/fastly/host-api/host_api_fastly.h index ad444c67d0..4dc5eac32c 100644 --- a/runtime/fastly/host-api/host_api_fastly.h +++ b/runtime/fastly/host-api/host_api_fastly.h @@ -846,6 +846,7 @@ class ConfigStore final { static Result open(std::string_view name); Result> get(std::string_view name); + Result> get(std::string_view name, uint32_t initial_buf_len); }; class ObjectStorePendingLookup final { @@ -918,6 +919,7 @@ class Secret final { explicit Secret(Handle handle) : handle{handle} {} Result> plaintext() const; + Result> plaintext(uint32_t initial_buf_len) const; }; class SecretStore final {