Skip to content

Commit

Permalink
[release/4.x] Cherry pick: JS FFI exception safety update (#5747) (#5783
Browse files Browse the repository at this point in the history
)
  • Loading branch information
achamayou authored Oct 26, 2023
1 parent 045f177 commit 6dce06f
Show file tree
Hide file tree
Showing 14 changed files with 736 additions and 464 deletions.
2 changes: 1 addition & 1 deletion .daily_canary
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
-^- _X_ ___
(- -) (= =) | Y & +--?
( V ) / . \ | +---=---'
/--x-m- /--n-n---xXx--/--yY------>>>----<<<>>
/--x-m- /--n-n---xXx--/--yY------>>>----<<<>>]]
35 changes: 17 additions & 18 deletions src/apps/js_generic/js_generic_base.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ namespace ccfapp
jwt_ident->key_issuer.data(), jwt_ident->key_issuer.size()));
jwt.set("header", ctx.parse_json(jwt_ident->header));
jwt.set("payload", ctx.parse_json(jwt_ident->payload));
caller.set("jwt", jwt);
caller.set("jwt", std::move(jwt));

return caller;
}
Expand Down Expand Up @@ -104,7 +104,7 @@ namespace ccfapp
"content",
ctx.new_array_buffer_copy(
user_cose_ident->content.data(), user_cose_ident->content.size()));
caller.set("cose", cose);
caller.set("cose", std::move(cose));
}

if (policy_name == nullptr)
Expand Down Expand Up @@ -170,39 +170,39 @@ namespace ccfapp
header_name,
ctx.new_string_len(header_value.c_str(), header_value.size()));
}
request.set("headers", headers);
request.set("headers", std::move(headers));

const auto& request_query = endpoint_ctx.rpc_ctx->get_request_query();
auto query_str =
ctx.new_string_len(request_query.c_str(), request_query.size());
request.set("query", query_str);
request.set("query", std::move(query_str));

const auto& request_path = endpoint_ctx.rpc_ctx->get_request_path();
auto path_str =
ctx.new_string_len(request_path.c_str(), request_path.size());
request.set("path", path_str);
request.set("path", std::move(path_str));

const auto& request_method = endpoint_ctx.rpc_ctx->get_request_verb();
auto method_str = ctx.new_string(request_method.c_str());
request.set("method", method_str);
request.set("method", std::move(method_str));

const auto host_it = r_headers.find(http::headers::HOST);
if (host_it != r_headers.end())
{
const auto& request_hostname = host_it->second;
auto hostname_str =
ctx.new_string_len(request_hostname.c_str(), request_hostname.size());
request.set("hostname", hostname_str);
request.set("hostname", std::move(hostname_str));
}
else
{
request.set("hostname", JS_NULL);
request.set_null("hostname");
}

const auto request_route = endpoint->full_uri_path;
auto route_str =
ctx.new_string_len(request_route.c_str(), request_route.size());
request.set("route", route_str);
request.set("route", std::move(route_str));

auto request_url = request_path;
if (!request_query.empty())
Expand All @@ -211,7 +211,7 @@ namespace ccfapp
}
auto url_str =
ctx.new_string_len(request_url.c_str(), request_url.size());
request.set("url", url_str);
request.set("url", std::move(url_str));

auto params = ctx.new_obj();
for (auto& [param_name, param_value] :
Expand All @@ -221,12 +221,12 @@ namespace ccfapp
param_name,
ctx.new_string_len(param_value.c_str(), param_value.size()));
}
request.set("params", params);
request.set("params", std::move(params));

const auto& request_body = endpoint_ctx.rpc_ctx->get_request_body();
auto body_ = ctx.new_obj_class(js::body_class_id);
JS_SetOpaque(body_, (void*)&request_body);
request.set("body", body_);
request.set("body", std::move(body_));

request.set("caller", create_caller_obj(endpoint_ctx, ctx));

Expand Down Expand Up @@ -486,22 +486,21 @@ namespace ccfapp
// Response headers
{
auto response_headers_js = val["headers"];
if (JS_IsObject(response_headers_js))
if (response_headers_js.is_obj())
{
js::JSWrappedPropertyEnum prop_enum(ctx, response_headers_js);
for (size_t i = 0; i < prop_enum.size(); i++)
{
auto prop_name = prop_enum[i];
auto prop_name_str = ctx.to_str(prop_name);
if (!prop_name_str)
auto prop_name = ctx.to_str(prop_enum[i]);
if (!prop_name)
{
endpoint_ctx.rpc_ctx->set_error(
HTTP_STATUS_INTERNAL_SERVER_ERROR,
ccf::errors::InternalError,
"Invalid endpoint function return value (header type).");
return;
}
auto prop_val = response_headers_js.get_property(prop_name);
auto prop_val = response_headers_js[*prop_name];
auto prop_val_str = ctx.to_str(prop_val);
if (!prop_val_str)
{
Expand All @@ -512,7 +511,7 @@ namespace ccfapp
return;
}
endpoint_ctx.rpc_ctx->set_response_header(
*prop_name_str, *prop_val_str);
*prop_name, *prop_val_str);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/crypto/openssl/entropy.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ namespace crypto
static bool gen(uint64_t& v);

public:
Entropy_OpenSSL() {}
Entropy_OpenSSL() = default;

std::vector<uint8_t> random(size_t len) override
{
Expand Down
52 changes: 39 additions & 13 deletions src/js/consensus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,28 +11,37 @@ namespace ccf::js
JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv)
{
if (argc != 0)
{
return JS_ThrowTypeError(
ctx, "Passed %d arguments, but expected 0", argc);
}

auto endpoint_registry = static_cast<ccf::BaseEndpointRegistry*>(
JS_GetOpaque(this_val, consensus_class_id));
if (endpoint_registry == nullptr)
{
return JS_ThrowInternalError(
ctx, "Failed to get endpoint registry object");
}

ccf::View view;
ccf::SeqNo seqno;
auto result = endpoint_registry->get_last_committed_txid_v1(view, seqno);
if (result != ccf::ApiResult::OK)
{
return JS_ThrowInternalError(
ctx,
"Failed to get last committed txid: %s",
ccf::api_result_to_str(result));
}

auto obj = JS_NewObject(ctx);
JS_SetPropertyStr(ctx, obj, "view", JS_NewFloat64(ctx, view));
JS_SetPropertyStr(ctx, obj, "seqno", JS_NewFloat64(ctx, seqno));
return obj;
js::Context& jsctx = *(js::Context*)JS_GetContextOpaque(ctx);

auto obj = jsctx.new_obj();
JS_CHECK_EXC(obj);
JS_CHECK_SET(obj.set_int64("view", view));
JS_CHECK_SET(obj.set_int64("seqno", seqno));
return obj.take();
}

static JSValue js_consensus_get_status_for_txid(
Expand All @@ -45,31 +54,39 @@ namespace ccf::js
int64_t view;
int64_t seqno;
if (JS_ToInt64(ctx, &view, argv[0]) < 0)
return JS_EXCEPTION;
{
return ccf::js::constants::Exception;
}
if (JS_ToInt64(ctx, &seqno, argv[1]) < 0)
return JS_EXCEPTION;
{
return ccf::js::constants::Exception;
}
if (view < 0 || seqno < 0)
{
return JS_ThrowRangeError(
ctx, "Invalid view or seqno: cannot be negative");
}

auto endpoint_registry = static_cast<ccf::BaseEndpointRegistry*>(
JS_GetOpaque(this_val, consensus_class_id));
if (endpoint_registry == nullptr)
{
return JS_ThrowInternalError(
ctx, "Failed to get endpoint registry object");
}

ccf::TxStatus status;
auto result =
endpoint_registry->get_status_for_txid_v1(view, seqno, status);
if (result != ccf::ApiResult::OK)
{
return JS_ThrowInternalError(
ctx,
"Failed to get status for txid: %s",
ccf::api_result_to_str(result));
}
auto status_str = ccf::tx_status_to_str(status);

auto status_js = JS_NewString(ctx, status_str);
return status_js;
return JS_NewString(ctx, status_str);
}

static JSValue js_consensus_get_view_for_seqno(
Expand All @@ -81,28 +98,37 @@ namespace ccf::js

int64_t seqno;
if (JS_ToInt64(ctx, &seqno, argv[0]) < 0)
return JS_EXCEPTION;
{
return ccf::js::constants::Exception;
}
if (seqno < 0)
{
return JS_ThrowRangeError(ctx, "Invalid seqno: cannot be negative");
}

auto endpoint_registry = static_cast<ccf::BaseEndpointRegistry*>(
JS_GetOpaque(this_val, consensus_class_id));
if (endpoint_registry == nullptr)
{
return JS_ThrowInternalError(
ctx, "Failed to get endpoint registry object");
}

ccf::View view;
auto result = endpoint_registry->get_view_for_seqno_v1(seqno, view);
if (result == ccf::ApiResult::NotFound)
return JS_NULL;
{
return ccf::js::constants::Null;
}
if (result != ccf::ApiResult::OK)
{
return JS_ThrowInternalError(
ctx,
"Failed to get view for seqno: %s",
ccf::api_result_to_str(result));
}

auto view_js = JS_NewFloat64(ctx, view);
return view_js;
return JS_NewFloat64(ctx, view);
}

#pragma clang diagnostic pop
Expand Down
32 changes: 5 additions & 27 deletions src/js/conv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,13 @@ namespace ccf::js
}

auto str = jsctx.to_str(argv[0]);

if (!str)
{
js_dump_error(ctx);
return JS_EXCEPTION;
return ccf::js::constants::Exception;
}

auto buf = jsctx.new_array_buffer_copy((uint8_t*)str->c_str(), str->size());

if (JS_IsException(buf))
{
js_dump_error(ctx);
return JS_EXCEPTION;
}
JS_CHECK_EXC(buf);

return buf.take();
}
Expand All @@ -63,12 +56,7 @@ namespace ccf::js
}

auto str = jsctx.new_string_len((char*)buf, buf_size);

if (JS_IsException(str))
{
js::js_dump_error(ctx);
return JS_EXCEPTION;
}
JS_CHECK_EXC(str);

return str.take();
}
Expand All @@ -85,12 +73,7 @@ namespace ccf::js
}

auto str = jsctx.json_stringify(JSWrappedValue(ctx, argv[0]));

if (JS_IsException(str))
{
js::js_dump_error(ctx);
return str.take();
}
JS_CHECK_EXC(str);

return js_str_to_buf(ctx, JS_NULL, 1, &str.val);
}
Expand Down Expand Up @@ -120,12 +103,7 @@ namespace ccf::js

auto obj =
jsctx.parse_json((char*)buf_null_terminated.data(), buf_size, "<json>");

if (JS_IsException(obj))
{
js::js_dump_error(ctx);
return JS_EXCEPTION;
}
JS_CHECK_EXC(obj);

return obj.take();
}
Expand Down
Loading

0 comments on commit 6dce06f

Please sign in to comment.