CVE-2024-38375: Insufficient Information (NVD-CWE-noinfo)
value: @fastly/js-compute is a JavaScript SDK and runtime for building Fastly Compute applications. The implementation of several functions were determined to include a use-after-free bug. This bug could allow for unintended data loss if the result of the preceding functions were sent anywhere else, and often results in a guest trap causing services to return a 500. This bug has been fixed in version 3.16.0 of the `@fastly/js-compute` package.
CWE description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
Published: 2024-06-26T19:15Z
Repository: https://github.com/fastly/js-compute-runtime
Language: C++
Files changed: runtime/fastly/host-api/component/fastly_world_adapter.cpp, runtime/js-compute-runtime/host_interface/component/fastly_world_adapter.cpp
Commit date: 2024-06-20 20:12:33 -0700
Commit message: fix: Fix uses of cabi_realloc that were discarding their results (#811)

Fix issues in some host calls where a buffer length error was being handled by reallocating to the new buffer size, but was discarding the new buffer's pointer. This should also fix flaky tests in CI.
Diff: diff --git a/runtime/fastly/host-api/component/fastly_world_adapter.cpp b/runtime/fastly/host-api/component/fastly_world_adapter.cpp
index 9111ee3b..823b832a 100644
--- a/runtime/fastly/host-api/component/fastly_world_adapter.cpp
+++ b/runtime/fastly/host-api/component/fastly_world_adapter.cpp
@@ -208,11 +208,11 @@ bool fastly_compute_at_edge_http_req_downstream_tls_cipher_openssl_name(
   auto default_size = 128;
   ret->ptr = static_cast<uint8_t *>(cabi_malloc(default_size, 4));
   auto status = fastly::req_downstream_tls_cipher_openssl_name(reinterpret_cast<char *>(ret->ptr),
                                                                default_size, &ret->len);
   if (status == FASTLY_COMPUTE_AT_EDGE_TYPES_ERROR_BUFFER_LEN) {
-    cabi_realloc(ret->ptr, default_size, 4, ret->len);
+    ret->ptr = static_cast<uint8_t *>(cabi_realloc(ret->ptr, default_size, 4, ret->len));
     status = fastly::req_downstream_tls_cipher_openssl_name(reinterpret_cast<char *>(ret->ptr),
                                                             ret->len, &ret->len);
   }
   return convert_result(status, err);
 }
@@ -222,11 +222,11 @@ bool fastly_compute_at_edge_http_req_downstream_tls_protocol(
   auto default_size = 32;
   ret->ptr = static_cast<uint8_t *>(cabi_malloc(default_size, 4));
   auto status = fastly::req_downstream_tls_protocol(reinterpret_cast<char *>(ret->ptr),
                                                     default_size, &ret->len);
   if (status == FASTLY_COMPUTE_AT_EDGE_TYPES_ERROR_BUFFER_LEN) {
-    cabi_realloc(ret->ptr, default_size, 4, ret->len);
+    ret->ptr = static_cast<uint8_t *>(cabi_realloc(ret->ptr, default_size, 4, ret->len));
     status = fastly::req_downstream_tls_protocol(reinterpret_cast<char *>(ret->ptr), ret->len,
                                                  &ret->len);
   }
   return convert_result(status, err);
 }
@@ -236,11 +236,11 @@ bool fastly_compute_at_edge_http_req_downstream_tls_raw_client_certificate(
   auto default_size = 4096;
   ret->ptr = static_cast<uint8_t *>(cabi_malloc(default_size, 4));
   auto status =
       fastly::req_downstream_tls_raw_client_certificate(ret->ptr, default_size, &ret->len);
   if (status == FASTLY_COMPUTE_AT_EDGE_TYPES_ERROR_BUFFER_LEN) {
-    cabi_realloc(ret->ptr, default_size, 4, ret->len);
+    ret->ptr = static_cast<uint8_t *>(cabi_realloc(ret->ptr, default_size, 4, ret->len));
     status = fastly::req_downstream_tls_raw_client_certificate(ret->ptr, ret->len, &ret->len);
   }
   return convert_result(status, err);
 }
 
@@ -248,22 +248,22 @@ bool fastly_compute_at_edge_http_req_downstream_tls_ja3_md5(
     fastly_world_list_u8_t *ret, fastly_compute_at_edge_types_error_t *err) {
   auto default_size = 16;
   ret->ptr = static_cast<uint8_t *>(cabi_malloc(default_size, 4));
   auto status = fastly::req_downstream_tls_ja3_md5(ret->ptr, &ret->len);
   if (status == FASTLY_COMPUTE_AT_EDGE_TYPES_ERROR_BUFFER_LEN) {
-    cabi_realloc(ret->ptr, default_size, 4, ret->len);
+    ret->ptr = static_cast<uint8_t *>(cabi_realloc(ret->ptr, default_size, 4, ret->len));
     status = fastly::req_downstream_tls_ja3_md5(ret->ptr, &ret->len);
   }
   return convert_result(status, err);
 }
 bool fastly_compute_at_edge_http_req_downstream_tls_client_hello(
     fastly_world_list_u8_t *ret, fastly_compute_at_edge_types_error_t *err) {
   auto default_size = 512;
   ret->ptr = static_cast<uint8_t *>(cabi_malloc(default_size, 4));
   auto status = fastly::req_downstream_tls_client_hello(ret->ptr, default_size, &ret->len);
   if (status == FASTLY_COMPUTE_AT_EDGE_TYPES_ERROR_BUFFER_LEN) {
-    cabi_realloc(ret->ptr, default_size, 4, ret->len);
+    ret->ptr = static_cast<uint8_t *>(cabi_realloc(ret->ptr, default_size, 4, ret->len));
     status = fastly::req_downstream_tls_client_hello(ret->ptr, ret->len, &ret->len);
   }
   return convert_result(status, err);
 }
 
@@ -1241,11 +1241,11 @@ bool fastly_compute_at_edge_cache_get_user_metadata(fastly_compute_at_edge_cache
   size_t default_size = 16 * 1024;
   ret->ptr = static_cast<uint8_t *>(cabi_malloc(default_size, 4));
   auto status = fastly::cache_get_user_metadata(handle, reinterpret_cast<char *>(ret->ptr),
                                                 default_size, &ret->len);
   if (status == FASTLY_COMPUTE_AT_EDGE_TYPES_ERROR_BUFFER_LEN) {
-    cabi_realloc(ret->ptr, default_size, 4, ret->len);
+    ret->ptr = static_cast<uint8_t *>(cabi_realloc(ret->ptr, default_size, 4, ret->len));
     status = fastly::cache_get_user_metadata(handle, reinterpret_cast<char *>(ret->ptr), ret->len,
                                              &ret->len);
   }
   return convert_result(status, err);
 }
@@ -1385,12 +1385,12 @@ bool fastly_compute_at_edge_device_detection_lookup(
   ret->ptr = static_cast<uint8_t *>(cabi_malloc(default_size, 4));
   auto status =
       fastly::device_detection_lookup(reinterpret_cast<char *>(user_agent->ptr), user_agent->len,
                                       reinterpret_cast<char *>(ret->ptr), default_size, &ret->len);
   if (status == FASTLY_COMPUTE_AT_EDGE_TYPES_ERROR_BUFFER_LEN) {
-    cabi_realloc(ret->ptr, default_size, 4, ret->len);
+    ret->ptr = static_cast<uint8_t *>(cabi_realloc(ret->ptr, default_size, 4, ret->len));
     status =
         fastly::device_detection_lookup(reinterpret_cast<char *>(user_agent->ptr), user_agent->len,
                                         reinterpret_cast<char *>(ret->ptr), ret->len, &ret->len);
   }
   return convert_result(status, err);
-}
\ No newline at end of file
+}
diff --git a/runtime/js-compute-runtime/host_interface/component/fastly_world_adapter.cpp b/runtime/js-compute-runtime/host_interface/component/fastly_world_adapter.cpp
index 9111ee3b..823b832a 100644
--- a/runtime/js-compute-runtime/host_interface/component/fastly_world_adapter.cpp
+++ b/runtime/js-compute-runtime/host_interface/component/fastly_world_adapter.cpp
@@ -208,11 +208,11 @@ bool fastly_compute_at_edge_http_req_downstream_tls_cipher_openssl_name(
   auto default_size = 128;
   ret->ptr = static_cast<uint8_t *>(cabi_malloc(default_size, 4));
   auto status = fastly::req_downstream_tls_cipher_openssl_name(reinterpret_cast<char *>(ret->ptr),
                                                                default_size, &ret->len);
   if (status == FASTLY_COMPUTE_AT_EDGE_TYPES_ERROR_BUFFER_LEN) {
-    cabi_realloc(ret->ptr, default_size, 4, ret->len);
+    ret->ptr = static_cast<uint8_t *>(cabi_realloc(ret->ptr, default_size, 4, ret->len));
     status = fastly::req_downstream_tls_cipher_openssl_name(reinterpret_cast<char *>(ret->ptr),
                                                             ret->len, &ret->len);
   }
   return convert_result(status, err);
 }
@@ -222,11 +222,11 @@ bool fastly_compute_at_edge_http_req_downstream_tls_protocol(
   auto default_size = 32;
   ret->ptr = static_cast<uint8_t *>(cabi_malloc(default_size, 4));
   auto status = fastly::req_downstream_tls_protocol(reinterpret_cast<char *>(ret->ptr),
                                                     default_size, &ret->len);
   if (status == FASTLY_COMPUTE_AT_EDGE_TYPES_ERROR_BUFFER_LEN) {
-    cabi_realloc(ret->ptr, default_size, 4, ret->len);
+    ret->ptr = static_cast<uint8_t *>(cabi_realloc(ret->ptr, default_size, 4, ret->len));
     status = fastly::req_downstream_tls_protocol(reinterpret_cast<char *>(ret->ptr), ret->len,
                                                  &ret->len);
   }
   return convert_result(status, err);
 }
@@ -236,11 +236,11 @@ bool fastly_compute_at_edge_http_req_downstream_tls_raw_client_certificate(
   auto default_size = 4096;
   ret->ptr = static_cast<uint8_t *>(cabi_malloc(default_size, 4));
   auto status =
       fastly::req_downstream_tls_raw_client_certificate(ret->ptr, default_size, &ret->len);
   if (status == FASTLY_COMPUTE_AT_EDGE_TYPES_ERROR_BUFFER_LEN) {
-    cabi_realloc(ret->ptr, default_size, 4, ret->len);
+    ret->ptr = static_cast<uint8_t *>(cabi_realloc(ret->ptr, default_size, 4, ret->len));
     status = fastly::req_downstream_tls_raw_client_certificate(ret->ptr, ret->len, &ret->len);
   }
   return convert_result(status, err);
 }
 
@@ -248,22 +248,22 @@ bool fastly_compute_at_edge_http_req_downstream_tls_ja3_md5(
     fastly_world_list_u8_t *ret, fastly_compute_at_edge_types_error_t *err) {
   auto default_size = 16;
   ret->ptr = static_cast<uint8_t *>(cabi_malloc(default_size, 4));
   auto status = fastly::req_downstream_tls_ja3_md5(ret->ptr, &ret->len);
   if (status == FASTLY_COMPUTE_AT_EDGE_TYPES_ERROR_BUFFER_LEN) {
-    cabi_realloc(ret->ptr, default_size, 4, ret->len);
+    ret->ptr = static_cast<uint8_t *>(cabi_realloc(ret->ptr, default_size, 4, ret->len));
     status = fastly::req_downstream_tls_ja3_md5(ret->ptr, &ret->len);
   }
   return convert_result(status, err);
 }
 bool fastly_compute_at_edge_http_req_downstream_tls_client_hello(
     fastly_world_list_u8_t *ret, fastly_compute_at_edge_types_error_t *err) {
   auto default_size = 512;
   ret->ptr = static_cast<uint8_t *>(cabi_malloc(default_size, 4));
   auto status = fastly::req_downstream_tls_client_hello(ret->ptr, default_size, &ret->len);
   if (status == FASTLY_COMPUTE_AT_EDGE_TYPES_ERROR_BUFFER_LEN) {
-    cabi_realloc(ret->ptr, default_size, 4, ret->len);
+    ret->ptr = static_cast<uint8_t *>(cabi_realloc(ret->ptr, default_size, 4, ret->len));
     status = fastly::req_downstream_tls_client_hello(ret->ptr, ret->len, &ret->len);
   }
   return convert_result(status, err);
 }
 
@@ -1241,11 +1241,11 @@ bool fastly_compute_at_edge_cache_get_user_metadata(fastly_compute_at_edge_cache
   size_t default_size = 16 * 1024;
   ret->ptr = static_cast<uint8_t *>(cabi_malloc(default_size, 4));
   auto status = fastly::cache_get_user_metadata(handle, reinterpret_cast<char *>(ret->ptr),
                                                 default_size, &ret->len);
   if (status == FASTLY_COMPUTE_AT_EDGE_TYPES_ERROR_BUFFER_LEN) {
-    cabi_realloc(ret->ptr, default_size, 4, ret->len);
+    ret->ptr = static_cast<uint8_t *>(cabi_realloc(ret->ptr, default_size, 4, ret->len));
     status = fastly::cache_get_user_metadata(handle, reinterpret_cast<char *>(ret->ptr), ret->len,
                                              &ret->len);
   }
   return convert_result(status, err);
 }
@@ -1385,12 +1385,12 @@ bool fastly_compute_at_edge_device_detection_lookup(
   ret->ptr = static_cast<uint8_t *>(cabi_malloc(default_size, 4));
   auto status =
       fastly::device_detection_lookup(reinterpret_cast<char *>(user_agent->ptr), user_agent->len,
                                       reinterpret_cast<char *>(ret->ptr), default_size, &ret->len);
   if (status == FASTLY_COMPUTE_AT_EDGE_TYPES_ERROR_BUFFER_LEN) {
-    cabi_realloc(ret->ptr, default_size, 4, ret->len);
+    ret->ptr = static_cast<uint8_t *>(cabi_realloc(ret->ptr, default_size, 4, ret->len));
     status =
         fastly::device_detection_lookup(reinterpret_cast<char *>(user_agent->ptr), user_agent->len,
                                         reinterpret_cast<char *>(ret->ptr), ret->len, &ret->len);
   }
   return convert_result(status, err);
-}
\ No newline at end of file
+}

Vulnerable code:     cabi_realloc(ret->ptr, default_size, 4, ret->len);
    cabi_realloc(ret->ptr, default_size, 4, ret->len);
    cabi_realloc(ret->ptr, default_size, 4, ret->len);
    cabi_realloc(ret->ptr, default_size, 4, ret->len);
    cabi_realloc(ret->ptr, default_size, 4, ret->len);
    cabi_realloc(ret->ptr, default_size, 4, ret->len);
    cabi_realloc(ret->ptr, default_size, 4, ret->len);
}
    cabi_realloc(ret->ptr, default_size, 4, ret->len);
    cabi_realloc(ret->ptr, default_size, 4, ret->len);
    cabi_realloc(ret->ptr, default_size, 4, ret->len);
    cabi_realloc(ret->ptr, default_size, 4, ret->len);
    cabi_realloc(ret->ptr, default_size, 4, ret->len);
    cabi_realloc(ret->ptr, default_size, 4, ret->len);
    cabi_realloc(ret->ptr, default_size, 4, ret->len);
}
Fixed code:     ret->ptr = static_cast<uint8_t *>(cabi_realloc(ret->ptr, default_size, 4, ret->len));
    ret->ptr = static_cast<uint8_t *>(cabi_realloc(ret->ptr, default_size, 4, ret->len));
    ret->ptr = static_cast<uint8_t *>(cabi_realloc(ret->ptr, default_size, 4, ret->len));
    ret->ptr = static_cast<uint8_t *>(cabi_realloc(ret->ptr, default_size, 4, ret->len));
    ret->ptr = static_cast<uint8_t *>(cabi_realloc(ret->ptr, default_size, 4, ret->len));
    ret->ptr = static_cast<uint8_t *>(cabi_realloc(ret->ptr, default_size, 4, ret->len));
    ret->ptr = static_cast<uint8_t *>(cabi_realloc(ret->ptr, default_size, 4, ret->len));
}
    ret->ptr = static_cast<uint8_t *>(cabi_realloc(ret->ptr, default_size, 4, ret->len));
    ret->ptr = static_cast<uint8_t *>(cabi_realloc(ret->ptr, default_size, 4, ret->len));
    ret->ptr = static_cast<uint8_t *>(cabi_realloc(ret->ptr, default_size, 4, ret->len));
    ret->ptr = static_cast<uint8_t *>(cabi_realloc(ret->ptr, default_size, 4, ret->len));
    ret->ptr = static_cast<uint8_t *>(cabi_realloc(ret->ptr, default_size, 4, ret->len));
    ret->ptr = static_cast<uint8_t *>(cabi_realloc(ret->ptr, default_size, 4, ret->len));
    ret->ptr = static_cast<uint8_t *>(cabi_realloc(ret->ptr, default_size, 4, ret->len));
}