From dd3ed1ef869d380176beea899a74488e067d5898 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Fri, 16 Oct 2026 22:26:49 +0200 Subject: [PATCH] Check and sanitize strings out of line The string writers kept the string_t that holds a sanitized copy for the other error handlers in the function that also has the fast path for the default one, so that every string paid for its construction check, a stack frame with a stack protector under GCC, and the registers saved for the slow path. The slow path is now a function of its own that the fast path does not call. Instructions per call (Linux, GCC 13, thousands), to_ubjson: twitter 3867 -> 3274, 20000 small objects 20981 -> 17901; to_bjdata: twitter 3873 -> 3281, 20000 small objects 21001 -> 17921; to_msgpack: 20000 small objects 18342 -> 15922. Signed-off-by: Niels Lohmann --- .../nlohmann/detail/output/binary_writer.hpp | 25 +++++++++++++++++++ single_include/nlohmann/json.hpp | 25 +++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/include/nlohmann/detail/output/binary_writer.hpp b/include/nlohmann/detail/output/binary_writer.hpp index 8fe3ba98d..75a9b6f1e 100644 --- a/include/nlohmann/detail/output/binary_writer.hpp +++ b/include/nlohmann/detail/output/binary_writer.hpp @@ -2894,6 +2894,15 @@ class binary_writer } } + write_cbor_checked_string(value, context); + } + + /// @brief write a CBOR text string checked or sanitized by the error handler; + /// out of line, as the string_t for the sanitized copy would make + /// every call of @ref write_cbor_string set up a frame for it + JSON_HEDLEY_NEVER_INLINE + void write_cbor_checked_string(const string_t& value, const BasicJsonType& context) + { string_t storage; const string_t& sanitized = sanitize_utf8_for_write(value, context, storage); @@ -2946,6 +2955,14 @@ class binary_writer } } + write_msgpack_checked_string(value, context); + } + + /// @brief write a MessagePack str checked or sanitized by the error handler; + /// out of line, like @ref write_cbor_checked_string + JSON_HEDLEY_NEVER_INLINE + void write_msgpack_checked_string(const string_t& value, const BasicJsonType& context) + { string_t storage; const string_t& sanitized = sanitize_utf8_for_write(value, context, storage); @@ -3167,6 +3184,14 @@ class binary_writer return; } + write_ubjson_checked_text(value, context, add_marker, use_bjdata); + } + + /// @brief write a UBJSON/BJData string checked or sanitized by the error + /// handler; out of line, like @ref write_cbor_checked_string + JSON_HEDLEY_NEVER_INLINE + void write_ubjson_checked_text(const string_t& value, const BasicJsonType& context, const bool add_marker, const bool use_bjdata) + { string_t storage; const string_t& sanitized = sanitize_utf8_for_write(value, context, storage); if (add_marker) diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index bcf704525..bacedf9d5 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -27722,6 +27722,15 @@ class binary_writer } } + write_cbor_checked_string(value, context); + } + + /// @brief write a CBOR text string checked or sanitized by the error handler; + /// out of line, as the string_t for the sanitized copy would make + /// every call of @ref write_cbor_string set up a frame for it + JSON_HEDLEY_NEVER_INLINE + void write_cbor_checked_string(const string_t& value, const BasicJsonType& context) + { string_t storage; const string_t& sanitized = sanitize_utf8_for_write(value, context, storage); @@ -27774,6 +27783,14 @@ class binary_writer } } + write_msgpack_checked_string(value, context); + } + + /// @brief write a MessagePack str checked or sanitized by the error handler; + /// out of line, like @ref write_cbor_checked_string + JSON_HEDLEY_NEVER_INLINE + void write_msgpack_checked_string(const string_t& value, const BasicJsonType& context) + { string_t storage; const string_t& sanitized = sanitize_utf8_for_write(value, context, storage); @@ -27995,6 +28012,14 @@ class binary_writer return; } + write_ubjson_checked_text(value, context, add_marker, use_bjdata); + } + + /// @brief write a UBJSON/BJData string checked or sanitized by the error + /// handler; out of line, like @ref write_cbor_checked_string + JSON_HEDLEY_NEVER_INLINE + void write_ubjson_checked_text(const string_t& value, const BasicJsonType& context, const bool add_marker, const bool use_bjdata) + { string_t storage; const string_t& sanitized = sanitize_utf8_for_write(value, context, storage); if (add_marker)