Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion include/glaze/rpc/repe/repe.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -554,7 +554,17 @@ namespace glz::repe
}
auto start = b;

glz::parse<Opts.format>::template op<Opts>(std::forward<Value>(value), ctx, b, e);
// The body is a view into the request span, so nothing is guaranteed to follow it.
// A null_terminated read drops its end checks and scans for the '\0' sentinel that
// only a std::string body would supply, so read the view as unterminated input and
// clear the end_reached a value finishing at the span end reports, matching what
// finalize_read_context does for glz::read.
static constexpr auto BodyOpts = opt_false<Opts, &opts::null_terminated>;

glz::parse<Opts.format>::template op<BodyOpts>(std::forward<Value>(value), ctx, b, e);
if (ctx.error == error_code::end_reached && ctx.depth == 0) {
ctx.error = error_code::none;
}

if (bool(ctx.error)) {
error_ctx ec{size_t(b - start), ctx.error, ctx.custom_error_message};
Expand Down
50 changes: 50 additions & 0 deletions tests/networking_tests/registry_view_test/registry_view_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include <cstring>
#include <string>
#include <vector>

#include "glaze/rpc/registry.hpp"
#include "ut/ut.hpp"
Expand Down Expand Up @@ -289,4 +290,53 @@ suite registry_span_call_tests = [] {
};
};

struct vec2
{
int x{};
int y{};
};

struct object_api
{
vec2 position{};
};

suite span_call_unterminated_buffer_tests = [] {
// make_request hands back a std::string, whose data()[size()] is a '\0' the reader
// can stop on. Off the wire the body ends where the buffer ends, so copy the message
// into an exactly sized vector to reproduce that.
auto exact_buffer = [](std::string_view message) { return std::vector<char>(message.begin(), message.end()); };

"scalar_body_ending_at_buffer_end"_test = [&] {
glz::registry<> registry;
test_api api{};
registry.on(api);

const auto request = exact_buffer(make_request("/value", "7"));
std::string response_buf;
registry.call(std::span<const char>{request.data(), request.size()}, response_buf);

expect(api.value == 7) << "Scalar body should be applied";
auto result = glz::repe::parse_request({response_buf.data(), response_buf.size()});
expect(bool(result)) << "Response should be parseable";
expect(result.request.error() == glz::error_code::none) << "No error expected";
};

"object_body_ending_at_buffer_end"_test = [&] {
glz::registry<> registry;
object_api api{};
registry.on(api);

const auto request = exact_buffer(make_request("/position", R"({"x":3,"y":4})"));
std::string response_buf;
registry.call(std::span<const char>{request.data(), request.size()}, response_buf);

expect(api.position.x == 3) << "Object body should be applied";
expect(api.position.y == 4) << "Object body should be applied";
auto result = glz::repe::parse_request({response_buf.data(), response_buf.size()});
expect(bool(result)) << "Response should be parseable";
expect(result.request.error() == glz::error_code::none) << "No error expected";
};
};

int main() { return 0; }
Loading