mirror of
https://github.com/nlohmann/json.git
synced 2026-10-23 14:28:54 +00:00
1.4: BSON writers share one write-pass UTF-8 sanitizer (#5891)
write_bson_entry_header and write_bson_string re-derived the error-handler policy differently. Both now use sanitize_utf8_for_bson_write, which treats strict like keep (the size pass already validated) and sanitizes replace/ignore into the bytes the size pass measured. No context plumbing is needed. Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
1 file changed
+31
-8
@@ -1550,14 +1550,15 @@ class binary_writer
|
||||
{
|
||||
oa.write_character(to_char_type(element_type));
|
||||
|
||||
if (error_handler == error_handler_t::keep || error_handler == error_handler_t::strict || is_valid_utf8(name))
|
||||
if (JSON_HEDLEY_LIKELY(error_handler == error_handler_t::keep || error_handler == error_handler_t::strict))
|
||||
{
|
||||
oa.write_characters(reinterpret_cast<const CharType*>(name.data()), name.size());
|
||||
}
|
||||
else
|
||||
{
|
||||
const string_t sanitized = sanitize_utf8(name, error_handler);
|
||||
oa.write_characters(reinterpret_cast<const CharType*>(sanitized.data()), sanitized.size());
|
||||
string_t storage;
|
||||
const string_t& written = sanitize_utf8_for_bson_write(name, storage);
|
||||
oa.write_characters(reinterpret_cast<const CharType*>(written.data()), written.size());
|
||||
}
|
||||
|
||||
// the terminating null byte is written explicitly rather than taken
|
||||
@@ -1633,11 +1634,8 @@ class binary_writer
|
||||
{
|
||||
write_bson_entry_header(name, 0x02);
|
||||
|
||||
const bool sanitize = error_handler != error_handler_t::keep
|
||||
&& error_handler != error_handler_t::strict
|
||||
&& !is_valid_utf8(value);
|
||||
const string_t sanitized = sanitize ? sanitize_utf8(value, error_handler) : string_t{};
|
||||
const string_t& written = sanitize ? sanitized : value;
|
||||
string_t storage;
|
||||
const string_t& written = sanitize_utf8_for_bson_write(value, storage);
|
||||
|
||||
write_number<std::int32_t>(to_bson_length(written.size() + 1ul), true);
|
||||
oa.write_characters(
|
||||
@@ -4902,6 +4900,31 @@ class binary_writer
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief the write-pass counterpart of @ref sanitize_utf8_for_write for BSON
|
||||
|
||||
The size pass (@ref calc_bson_entry_header_size, @ref
|
||||
calc_bson_string_size) has already validated @a s, and thrown for @ref
|
||||
error_handler_t::strict if it was ill-formed. Here, @ref
|
||||
error_handler_t::strict therefore behaves like @ref error_handler_t::keep,
|
||||
and @ref error_handler_t::replace / @ref error_handler_t::ignore produce
|
||||
exactly the bytes the size pass measured. Hence no context is needed.
|
||||
|
||||
@param[in] s the string (value or object key) to write
|
||||
@param[out] storage backing storage for a sanitized copy
|
||||
|
||||
@return a reference to @a s, or to @a storage once it holds a sanitized copy
|
||||
*/
|
||||
const string_t& sanitize_utf8_for_bson_write(const string_t& s, string_t& storage) const
|
||||
{
|
||||
if (error_handler == error_handler_t::keep || error_handler == error_handler_t::strict || is_valid_utf8(s))
|
||||
{
|
||||
return s; // NOLINT(bugprone-return-const-ref-from-parameter): callers pass lvalues that outlive the call
|
||||
}
|
||||
storage = sanitize_utf8(s, error_handler);
|
||||
return storage;
|
||||
}
|
||||
|
||||
/// deleted: anything but a string_t would bind a temporary that dies before the returned reference is used
|
||||
template < typename T, enable_if_t < !std::is_same<T, string_t>::value, int > = 0 >
|
||||
const string_t& sanitize_utf8_for_write(const T& /*s*/, const BasicJsonType& /*context*/, string_t& /*storage*/) const = delete; // NOLINT(hicpp-use-equals-delete,modernize-use-equals-delete): a private helper's guard, not part of the interface
|
||||
|
||||
Reference in new issue
Block a user