mirror of
https://github.com/nlohmann/json.git
synced 2026-10-09 07:57:13 +00:00
Keep converted object keys alive while writing UBJSON and BJData
Since #5746, write_ubjson and write_ubjson_iterative pass each object key to sanitize_utf8_for_write and keep the returned reference. When object_t::key_type is not string_t but converts to it, the argument is a temporary that is destroyed at the end of the statement, and the function returns a reference to it in every case but a sanitized copy, so the key bytes are read from a dead object (AddressSanitizer: stack-use-after-scope). Default json and ordered_json are unaffected. Bind the key to a named object_key_string_t first: a reference when key_type is string_t, so no copy is added there, and a converted copy otherwise. A deleted overload of sanitize_utf8_for_write for anything other than string_t turns a recurrence into a compile error. Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
3 files changed
+194
-4
No files matched your search
@@ -21590,6 +21590,12 @@ template<typename BasicJsonType, typename CharType, typename OutputSinkType = ou
|
||||
class binary_writer
|
||||
{
|
||||
using string_t = typename BasicJsonType::string_t;
|
||||
|
||||
/// an object key as string_t: a reference when object_t::key_type already is
|
||||
/// string_t, otherwise a converted copy that outlives sanitize_utf8_for_write's result
|
||||
using object_key_string_t = typename std::conditional <
|
||||
std::is_same<typename BasicJsonType::object_t::key_type, string_t>::value,
|
||||
const string_t&, string_t >::type;
|
||||
using binary_t = typename BasicJsonType::binary_t;
|
||||
using number_float_t = typename BasicJsonType::number_float_t;
|
||||
|
||||
@@ -22324,8 +22330,10 @@ class binary_writer
|
||||
|
||||
for (const auto& el : *j.m_data.m_value.object)
|
||||
{
|
||||
// a converted key must outlive the reference returned by sanitize_utf8_for_write
|
||||
const object_key_string_t key_string = el.first;
|
||||
string_t storage;
|
||||
const string_t& key = sanitize_utf8_for_write(el.first, j, storage);
|
||||
const string_t& key = sanitize_utf8_for_write(key_string, j, storage);
|
||||
write_number_with_ubjson_prefix(key.size(), true, use_bjdata);
|
||||
oa.write_characters(
|
||||
reinterpret_cast<const CharType*>(key.data()),
|
||||
@@ -22871,8 +22879,10 @@ class binary_writer
|
||||
continue;
|
||||
}
|
||||
|
||||
// a converted key must outlive the reference returned by sanitize_utf8_for_write
|
||||
const object_key_string_t key_string = current.object_it->first;
|
||||
string_t storage;
|
||||
const string_t& key = sanitize_utf8_for_write(current.object_it->first, j, storage);
|
||||
const string_t& key = sanitize_utf8_for_write(key_string, j, storage);
|
||||
write_number_with_ubjson_prefix(key.size(), true, use_bjdata);
|
||||
oa.write_characters(
|
||||
reinterpret_cast<const CharType*>(key.data()),
|
||||
@@ -24235,6 +24245,11 @@ class binary_writer
|
||||
itself in every case but a sanitized `replace`/`ignore` one, so @a
|
||||
storage must outlive the returned reference only then.
|
||||
|
||||
@a s must be an lvalue that outlives the returned reference. An object key
|
||||
whose `key_type` is not @ref string_t must therefore first be converted
|
||||
into a named string_t (see @ref object_key_string_t); the deleted overload
|
||||
below enforces this at compile time.
|
||||
|
||||
@param[in] s the string (value or object key) to write
|
||||
@param[in] context the value @a s belongs to (for diagnostics)
|
||||
@param[out] storage backing storage for a sanitized copy
|
||||
@@ -24264,6 +24279,10 @@ class binary_writer
|
||||
}
|
||||
}
|
||||
|
||||
/// 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;
|
||||
|
||||
/*!
|
||||
@brief write an integer in the shortest encoding
|
||||
|
||||
|
||||
Reference in new issue
Block a user