From d002c5e598ea5796bd76004f7d0fd450f1463cf5 Mon Sep 17 00:00:00 2001 From: Juan Cruz Viotti Date: Sat, 24 Oct 2026 14:30:47 -0300 Subject: [PATCH 1/2] Separate JSON Pointer fragment tokens before decoding them Signed-off-by: Juan Cruz Viotti --- .../include/sourcemeta/core/jsonpointer.h | 6 +- src/core/jsonpointer/jsonpointer.cc | 65 ++++--- src/core/jsonschema/frame.cc | 43 +++-- .../jsonpointer_fragment_to_pointer_test.cc | 55 +++++- test/jsonschema/jsonschema_frame_test.cc | 161 ++++++++++++++++++ 5 files changed, 291 insertions(+), 39 deletions(-) diff --git a/src/core/jsonpointer/include/sourcemeta/core/jsonpointer.h b/src/core/jsonpointer/include/sourcemeta/core/jsonpointer.h index 20c92a82c0..72700b7f3e 100644 --- a/src/core/jsonpointer/include/sourcemeta/core/jsonpointer.h +++ b/src/core/jsonpointer/include/sourcemeta/core/jsonpointer.h @@ -409,9 +409,9 @@ auto to_pointer( -> Pointer; /// @ingroup jsonpointer -/// Parse the URI fragment representation of a JSON Pointer, percent-decoding -/// the fragment data before interpretation as mandated by RFC 3986, Section -/// 2.4 and RFC 6901, Section 6. The result is not set if the URI has no +/// Parse the URI fragment representation of a JSON Pointer. A percent-encoded +/// slash is data within a reference token rather than a separator, as RFC +/// 3986, Section 2.4 requires. The result is not set if the URI has no /// fragment or if its fragment is not a valid JSON Pointer. For example: /// /// ```cpp diff --git a/src/core/jsonpointer/jsonpointer.cc b/src/core/jsonpointer/jsonpointer.cc index 67470cbf09..7c6a68b552 100644 --- a/src/core/jsonpointer/jsonpointer.cc +++ b/src/core/jsonpointer/jsonpointer.cc @@ -11,7 +11,6 @@ #include "stringify.h" #include // assert -#include // std::size_t #include // std::cbegin, std::cend, std::prev, std::advance #include // std::allocator #include // std::optional, std::nullopt @@ -24,6 +23,19 @@ namespace { +// A slash that comes out of an escape is data within the reference token it +// falls in, which is the escape that RFC 6901 Section 3 gives it +auto append_reference_token(sourcemeta::core::JSON::String &output, + const std::string_view token) -> void { + for (const auto character : sourcemeta::core::URI::unescape(token)) { + if (character == '/') { + output.append("~1"); + } else { + output.push_back(character); + } + } +} + template