mirror of
https://github.com/nlohmann/json.git
synced 2026-09-28 10:40:30 +00:00
Compare commits
17
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
38528b4a38 | ||
|
|
9cbe62efb0 | ||
|
|
471c7678cf | ||
|
|
4fabfb27f7 | ||
|
|
71b4eaf743 | ||
|
|
2790175d79 | ||
|
|
cc9fafa0e1 | ||
|
|
8d6d1264a7 | ||
|
|
d75f9ab161 | ||
|
|
c3774be4e2 | ||
|
|
91365ca3b2 | ||
|
|
605cc6c81d | ||
|
|
f012b85d06 | ||
|
|
243b6e20e3 | ||
|
|
0a0d5623be | ||
|
|
22c9ce3f21 | ||
|
|
0d2240ad1e |
@@ -31,6 +31,45 @@ jobs:
|
||||
- name: Build
|
||||
run: cmake --build build --target ci_test_gcc
|
||||
|
||||
ci_meson_install:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Get latest CMake and ninja
|
||||
uses: lukka/get-cmake@fffaaafeea488556c2c12dad60690008bc1caacb # v4.4.2
|
||||
- name: Install Meson
|
||||
run: pip install meson
|
||||
- name: Install with Meson
|
||||
run: |
|
||||
meson setup build-meson --prefix=${{ github.workspace }}/install
|
||||
meson install -C build-meson
|
||||
- name: Use the installed package with find_package
|
||||
run: |
|
||||
cmake -S tests/cmake_import/project -B build-import -DCMAKE_PREFIX_PATH=${{ github.workspace }}/install
|
||||
cmake --build build-import
|
||||
- name: Install with Meson and non-default options
|
||||
run: |
|
||||
meson setup build-meson-options --prefix=${{ github.workspace }}/install-options -DMultipleHeaders=true -DDiagnostics=true -DGlobalUDLs=false
|
||||
meson install -C build-meson-options
|
||||
- name: Check that the options reach the installed files
|
||||
run: |
|
||||
test -d install-options/include/nlohmann/detail
|
||||
cflags=$(PKG_CONFIG_PATH=${{ github.workspace }}/install-options/share/pkgconfig pkg-config --cflags nlohmann_json)
|
||||
echo "$cflags"
|
||||
echo "$cflags" | grep -q -- '-DJSON_DIAGNOSTICS=1'
|
||||
echo "$cflags" | grep -q -- '-DJSON_USE_GLOBAL_UDLS=0'
|
||||
grep -q 'JSON_USE_GLOBAL_UDLS=0;JSON_DIAGNOSTICS=1' install-options/share/cmake/nlohmann_json/nlohmann_jsonTargets.cmake
|
||||
cmake -S tests/cmake_import/project -B build-import-options -DCMAKE_PREFIX_PATH=${{ github.workspace }}/install-options
|
||||
cmake --build build-import-options
|
||||
- name: Install with Meson and the include directory outside the prefix
|
||||
run: |
|
||||
meson setup build-meson-split --prefix=${{ github.workspace }}/install-split --includedir=${{ github.workspace }}/install-split-dev/include
|
||||
meson install -C build-meson-split
|
||||
cmake -S tests/cmake_import/project -B build-import-split -DCMAKE_PREFIX_PATH=${{ github.workspace }}/install-split
|
||||
cmake --build build-import-split
|
||||
|
||||
ci_infer:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
+24
-1
@@ -168,7 +168,30 @@ if (MSVC)
|
||||
)
|
||||
endif()
|
||||
|
||||
# Install a pkg-config file, so other tools can find this.
|
||||
# Install a pkg-config file, so other tools can find this. It carries the same
|
||||
# compile definitions as the target above.
|
||||
set(NLOHMANN_JSON_PKGCONFIG_CFLAGS "")
|
||||
if (NOT JSON_GlobalUDLs)
|
||||
string(APPEND NLOHMANN_JSON_PKGCONFIG_CFLAGS " -DJSON_USE_GLOBAL_UDLS=0")
|
||||
endif()
|
||||
if (NOT JSON_ImplicitConversions)
|
||||
string(APPEND NLOHMANN_JSON_PKGCONFIG_CFLAGS " -DJSON_USE_IMPLICIT_CONVERSIONS=0")
|
||||
endif()
|
||||
if (JSON_DisableEnumSerialization)
|
||||
string(APPEND NLOHMANN_JSON_PKGCONFIG_CFLAGS " -DJSON_DISABLE_ENUM_SERIALIZATION=1")
|
||||
endif()
|
||||
if (JSON_Diagnostics)
|
||||
string(APPEND NLOHMANN_JSON_PKGCONFIG_CFLAGS " -DJSON_DIAGNOSTICS=1")
|
||||
endif()
|
||||
if (JSON_Diagnostic_Positions)
|
||||
string(APPEND NLOHMANN_JSON_PKGCONFIG_CFLAGS " -DJSON_DIAGNOSTIC_POSITIONS=1")
|
||||
endif()
|
||||
if (JSON_LegacyDiscardedValueComparison)
|
||||
string(APPEND NLOHMANN_JSON_PKGCONFIG_CFLAGS " -DJSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON=1")
|
||||
endif()
|
||||
if (JSON_StrictNulHandling)
|
||||
string(APPEND NLOHMANN_JSON_PKGCONFIG_CFLAGS " -DJSON_STRICT_NUL_HANDLING=1")
|
||||
endif()
|
||||
configure_file(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/pkg-config.pc.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc"
|
||||
|
||||
@@ -260,9 +260,29 @@ make BUILD.bazel
|
||||
|
||||
The "Check amalgamation" workflow fails if the file is out of date.
|
||||
|
||||
### `meson.build`
|
||||
### `meson.build` and `meson_options.txt`
|
||||
|
||||
The build definition for the [Meson](https://mesonbuild.com) build system.
|
||||
Meson build definitions suitable for use as a subproject ("wrap" in Meson terminology).
|
||||
|
||||
Projects wishing to use the wrap can execute:
|
||||
```sh
|
||||
meson wrap install nlohmann_json
|
||||
```
|
||||
|
||||
Which allows Meson to build from source when a system provided dependency isn't available.
|
||||
|
||||
To build directly:
|
||||
```sh
|
||||
meson setup builddir
|
||||
ninja -C builddir
|
||||
```
|
||||
|
||||
`meson_options.txt` defines the options, which mirror the CMake options that change the library's target (for example,
|
||||
`-DDiagnostics=true`). Meson requires this file next to `meson.build`, so it is also part of `include.zip`.
|
||||
|
||||
When installing, `meson.build` installs the headers, a pkg-config file, and the CMake package config files, so that
|
||||
`find_package(nlohmann_json)` works. As Meson cannot generate `nlohmann_jsonTargets.cmake` itself, it is created from
|
||||
the template `cmake/nlohmann_jsonTargets.cmake.in`, which is only used by Meson.
|
||||
|
||||
### `Package.swift`
|
||||
|
||||
|
||||
@@ -222,7 +222,7 @@ json.tar.xz:
|
||||
# We use `-X` to make the resulting ZIP file reproducible, see
|
||||
# <https://content.pivotal.io/blog/barriers-to-deterministic-reproducible-zip-files>.
|
||||
include.zip: BUILD.bazel
|
||||
zip -9 --recurse-paths -X include.zip $(SRCS) $(AMALGAMATED_FILE) $(AMALGAMATED_FWD_FILE) BUILD.bazel MODULE.bazel meson.build LICENSE.MIT
|
||||
zip -9 --recurse-paths -X include.zip $(SRCS) $(AMALGAMATED_FILE) $(AMALGAMATED_FWD_FILE) BUILD.bazel MODULE.bazel meson.build meson_options.txt LICENSE.MIT
|
||||
|
||||
# Create the files for a release and add signatures and hashes.
|
||||
release: include.zip json.tar.xz
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
# Imported target for installations made with Meson (see meson.build).
|
||||
#
|
||||
# CMake installations generate this file with install(EXPORT ...). Meson cannot
|
||||
# do that, but as the library is header-only, the target only needs an include
|
||||
# directory, the C++ standard, and the compile definitions of the options that
|
||||
# differ from their defaults. Paths are computed relative to this file so that
|
||||
# the installation can be relocated (e.g., into a sysroot), unless includedir or
|
||||
# datadir is outside the prefix.
|
||||
|
||||
if(TARGET @PROJECT_NAME@::@NLOHMANN_JSON_TARGET_NAME@)
|
||||
return()
|
||||
endif()
|
||||
|
||||
get_filename_component(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_DIR}/@NLOHMANN_JSON_CONFIG_TO_PREFIX@" ABSOLUTE)
|
||||
|
||||
add_library(@PROJECT_NAME@::@NLOHMANN_JSON_TARGET_NAME@ INTERFACE IMPORTED)
|
||||
set_target_properties(@PROJECT_NAME@::@NLOHMANN_JSON_TARGET_NAME@ PROPERTIES
|
||||
INTERFACE_INCLUDE_DIRECTORIES "@NLOHMANN_JSON_INCLUDE_DIR@"
|
||||
)
|
||||
if(CMAKE_VERSION VERSION_LESS 3.8)
|
||||
set_target_properties(@PROJECT_NAME@::@NLOHMANN_JSON_TARGET_NAME@ PROPERTIES
|
||||
INTERFACE_COMPILE_FEATURES cxx_range_for
|
||||
)
|
||||
else()
|
||||
set_target_properties(@PROJECT_NAME@::@NLOHMANN_JSON_TARGET_NAME@ PROPERTIES
|
||||
INTERFACE_COMPILE_FEATURES cxx_std_11
|
||||
)
|
||||
endif()
|
||||
|
||||
set(_NLOHMANN_JSON_COMPILE_DEFINITIONS "@NLOHMANN_JSON_COMPILE_DEFINITIONS@")
|
||||
if(_NLOHMANN_JSON_COMPILE_DEFINITIONS)
|
||||
set_target_properties(@PROJECT_NAME@::@NLOHMANN_JSON_TARGET_NAME@ PROPERTIES
|
||||
INTERFACE_COMPILE_DEFINITIONS "${_NLOHMANN_JSON_COMPILE_DEFINITIONS}"
|
||||
)
|
||||
endif()
|
||||
|
||||
unset(_NLOHMANN_JSON_COMPILE_DEFINITIONS)
|
||||
unset(_IMPORT_PREFIX)
|
||||
@@ -4,4 +4,4 @@ includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@
|
||||
Name: @PROJECT_NAME@
|
||||
Description: JSON for Modern C++
|
||||
Version: @PROJECT_VERSION@
|
||||
Cflags: -I${includedir}
|
||||
Cflags: -I${includedir}@NLOHMANN_JSON_PKGCONFIG_CFLAGS@
|
||||
|
||||
@@ -80,8 +80,8 @@ Strong guarantee: if an exception is thrown, there are no changes in the JSON va
|
||||
the end of the file was not reached when `strict` was set to true
|
||||
- Throws [parse_error.112](../../home/exceptions.md#jsonexceptionparse_error112) if unsupported features from CBOR were
|
||||
used in the given input or if the input is not valid CBOR
|
||||
- Throws [parse_error.113](../../home/exceptions.md#jsonexceptionparse_error113) if a map key is not a string (keys of other
|
||||
types are not supported, as JSON object keys are always strings) or a string is malformed
|
||||
- Throws [parse_error.113](../../home/exceptions.md#jsonexceptionparse_error113) if a string was expected as a map key,
|
||||
but not found
|
||||
|
||||
## Complexity
|
||||
|
||||
|
||||
@@ -73,8 +73,8 @@ Strong guarantee: if an exception is thrown, there are no changes in the JSON va
|
||||
the end of the file was not reached when `strict` was set to true
|
||||
- Throws [parse_error.112](../../home/exceptions.md#jsonexceptionparse_error112) if unsupported features from
|
||||
MessagePack were used in the given input or if the input is not valid MessagePack
|
||||
- Throws [parse_error.113](../../home/exceptions.md#jsonexceptionparse_error113) if a map key is not a string (keys of other
|
||||
types are not supported, as JSON object keys are always strings) or a string is malformed
|
||||
- Throws [parse_error.113](../../home/exceptions.md#jsonexceptionparse_error113) if a string was expected as a map key,
|
||||
but not found
|
||||
|
||||
## Complexity
|
||||
|
||||
|
||||
@@ -174,20 +174,7 @@ The library maps CBOR types to JSON value types as follows:
|
||||
|
||||
!!! warning "Object keys"
|
||||
|
||||
CBOR allows map keys of any type, whereas JSON only allows strings as keys in object values. Therefore, CBOR maps
|
||||
with keys other than text strings (major type 3) are rejected with a
|
||||
[`parse_error.113`](../../home/exceptions.md#jsonexceptionparse_error113) exception (or, with `allow_exceptions` set
|
||||
to `false`, a discarded value) naming the type of the key that was found, for instance:
|
||||
|
||||
```
|
||||
[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing CBOR object key: only string keys are supported, but found an unsigned integer; last byte: 0x01
|
||||
```
|
||||
|
||||
This applies to the [SAX interface](../parsing/sax_interface.md) as well, as the key is read before it is passed
|
||||
on. This is a deliberate restriction of the library's JSON value model, not an oversight: formats built on CBOR
|
||||
maps with integer keys, such as COSE ([RFC 9052](https://www.rfc-editor.org/rfc/rfc9052.html)) or CWT
|
||||
([RFC 8392](https://www.rfc-editor.org/rfc/rfc8392.html)), cannot be read with this library and need a
|
||||
general-purpose CBOR library instead.
|
||||
CBOR allows map keys of any type, whereas JSON only allows strings as keys in object values. Therefore, CBOR maps with keys other than UTF-8 strings are rejected.
|
||||
|
||||
!!! warning "UTF-8 validation of text strings"
|
||||
|
||||
|
||||
@@ -138,21 +138,6 @@ The library maps MessagePack types to JSON value types as follows:
|
||||
|
||||
Any MessagePack output created by `to_msgpack` can be successfully parsed by `from_msgpack`.
|
||||
|
||||
!!! warning "Object keys"
|
||||
|
||||
MessagePack allows map keys of any type, whereas JSON only allows strings as keys in object values. Like the
|
||||
JSON-compatible [profile](https://github.com/msgpack/msgpack/blob/master/spec.md#profile) sketched in the
|
||||
MessagePack specification, this library restricts map keys to `str` values. Maps with keys of any other type are
|
||||
rejected with a [`parse_error.113`](../../home/exceptions.md#jsonexceptionparse_error113) exception (or, with
|
||||
`allow_exceptions` set to `false`, a discarded value) naming the type of the key that was found, for instance:
|
||||
|
||||
```
|
||||
[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing MessagePack object key: only string keys are supported, but found nil; last byte: 0xC0
|
||||
```
|
||||
|
||||
This applies to the [SAX interface](../parsing/sax_interface.md) as well, as the key is read before it is passed
|
||||
on. Such input needs a general-purpose MessagePack library instead.
|
||||
|
||||
!!! warning "UTF-8 validation of string values"
|
||||
|
||||
The MessagePack specification requires `str` values (`fixstr`, `str 8`, `str 16`, `str 32`) to be valid UTF-8.
|
||||
|
||||
@@ -343,20 +343,13 @@ A string could not be read from a [binary format](../features/binary_formats/ind
|
||||
string was read where one was required (for instance as a map key), the string's length specification is invalid, or
|
||||
the string's bytes are not valid UTF-8.
|
||||
|
||||
CBOR and MessagePack allow map keys of any type, but JSON object keys are always strings. Maps with keys of any other
|
||||
type (for instance integers or `null`) are therefore not supported; see the notes on
|
||||
[CBOR](../features/binary_formats/cbor.md) and [MessagePack](../features/binary_formats/messagepack.md).
|
||||
|
||||
!!! failure "Example messages"
|
||||
|
||||
```
|
||||
[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing CBOR object key: only string keys are supported, but found an unsigned integer; last byte: 0x01
|
||||
[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing CBOR string: expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0xFF
|
||||
```
|
||||
```
|
||||
[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing MessagePack object key: only string keys are supported, but found nil; last byte: 0xC0
|
||||
```
|
||||
```
|
||||
[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing CBOR string: expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x7C
|
||||
[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing MessagePack string: expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0xFF
|
||||
```
|
||||
```
|
||||
[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing UBJSON char: byte after 'C' must be in range 0x00..0x7F; last byte: 0x82
|
||||
|
||||
@@ -121,10 +121,23 @@ meson wrap install nlohmann_json
|
||||
Please see the Meson project for any issues regarding the packaging.
|
||||
|
||||
The provided `meson.build` can also be used as an alternative to CMake for installing `nlohmann_json` system-wide in
|
||||
which case a pkg-config file is installed. To use it, have your build system require the `nlohmann_json`
|
||||
pkg-config dependency. In Meson, it is preferred to use the
|
||||
[`dependency()`](https://mesonbuild.com/Reference-manual.html#dependency) object with a subproject fallback, rather than
|
||||
using the subproject directly.
|
||||
which case a pkg-config file and the CMake package config files are installed. To use it, have your build system require
|
||||
the `nlohmann_json` pkg-config dependency, or use [`find_package(nlohmann_json)`](cmake.md#external) in CMake. In Meson,
|
||||
it is preferred to use the [`dependency()`](https://mesonbuild.com/Reference-manual.html#dependency) object with a
|
||||
subproject fallback, rather than using the subproject directly.
|
||||
|
||||
The options that change the library's configuration are available in Meson as well, named like the
|
||||
[CMake options](cmake.md#cmake-options) without the `JSON_` prefix: `MultipleHeaders`, `GlobalUDLs`,
|
||||
`ImplicitConversions`, `DisableEnumSerialization`, `Diagnostics`, `Diagnostic_Positions`,
|
||||
`LegacyDiscardedValueComparison`, and `StrictNulHandling`. They have the same defaults as in CMake, except that
|
||||
`MultipleHeaders` is `false`. Set them with `-D` when setting up the build, or with the subproject name as prefix when
|
||||
the library is used as a subproject:
|
||||
|
||||
```shell
|
||||
meson setup build -Dnlohmann_json:Diagnostics=true
|
||||
```
|
||||
|
||||
The resulting compile definitions are part of the Meson dependency, the pkg-config file, and the CMake target.
|
||||
|
||||
??? example "Example: Wrap"
|
||||
|
||||
|
||||
@@ -1324,80 +1324,6 @@ class binary_reader
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief reads a CBOR object key
|
||||
|
||||
RFC 8949 allows any data item as a map key, but only strings have a
|
||||
counterpart in JSON. A key of any other type is rejected with a message
|
||||
naming that type, rather than the one @ref get_cbor_string gives for a
|
||||
malformed string.
|
||||
|
||||
@param[out] result created key
|
||||
|
||||
@return whether key creation completed
|
||||
*/
|
||||
bool get_cbor_object_key(string_t& result)
|
||||
{
|
||||
// EOF and major type 3 (text string) are left to get_cbor_string
|
||||
if (current == char_traits<char_type>::eof() || (static_cast<unsigned int>(current) & 0xE0u) == 0x60u)
|
||||
{
|
||||
return get_cbor_string(result);
|
||||
}
|
||||
|
||||
const char* found = nullptr;
|
||||
switch (static_cast<unsigned int>(current) >> 5u)
|
||||
{
|
||||
case 0:
|
||||
found = "an unsigned integer";
|
||||
break;
|
||||
case 1:
|
||||
found = "a negative integer";
|
||||
break;
|
||||
case 2:
|
||||
found = "a byte string";
|
||||
break;
|
||||
case 4:
|
||||
found = "an array";
|
||||
break;
|
||||
case 5:
|
||||
found = "a map";
|
||||
break;
|
||||
case 6:
|
||||
found = "a tag";
|
||||
break;
|
||||
default: // major type 7
|
||||
switch (current)
|
||||
{
|
||||
case 0xF4:
|
||||
case 0xF5:
|
||||
found = "a boolean";
|
||||
break;
|
||||
case 0xF6:
|
||||
found = "null";
|
||||
break;
|
||||
case 0xF7:
|
||||
found = "undefined";
|
||||
break;
|
||||
case 0xF9:
|
||||
case 0xFA:
|
||||
case 0xFB:
|
||||
found = "a floating-point number";
|
||||
break;
|
||||
case 0xFF:
|
||||
found = "a break stop code";
|
||||
break;
|
||||
default:
|
||||
found = "a simple value";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
auto last_token = get_token_string();
|
||||
return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
|
||||
exception_message(input_format_t::cbor, concat("only string keys are supported, but found ", found, "; last byte: 0x", last_token), "object key"), nullptr));
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief reads a definite-length CBOR byte array
|
||||
|
||||
@@ -1642,7 +1568,7 @@ class binary_reader
|
||||
if (top.is_object)
|
||||
{
|
||||
key.clear();
|
||||
if (JSON_HEDLEY_UNLIKELY(!get_cbor_object_key(key) || !sax->key(key)))
|
||||
if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -2143,98 +2069,6 @@ class binary_reader
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief reads a MessagePack object key
|
||||
|
||||
The MessagePack specification allows any type as a map key, but only
|
||||
strings have a counterpart in JSON. A key of any other type is rejected
|
||||
with a message naming that type, rather than the one @ref
|
||||
get_msgpack_string gives for a malformed string.
|
||||
|
||||
@param[out] result created key
|
||||
|
||||
@return whether key creation completed
|
||||
*/
|
||||
bool get_msgpack_object_key(string_t& result)
|
||||
{
|
||||
const char* found = nullptr;
|
||||
switch (current)
|
||||
{
|
||||
case 0xC0:
|
||||
found = "nil";
|
||||
break;
|
||||
case 0xC2:
|
||||
case 0xC3:
|
||||
found = "a boolean";
|
||||
break;
|
||||
case 0xCA:
|
||||
case 0xCB:
|
||||
found = "a float";
|
||||
break;
|
||||
case 0xC4:
|
||||
case 0xC5:
|
||||
case 0xC6:
|
||||
found = "a bin";
|
||||
break;
|
||||
case 0xC7:
|
||||
case 0xC8:
|
||||
case 0xC9:
|
||||
case 0xD4:
|
||||
case 0xD5:
|
||||
case 0xD6:
|
||||
case 0xD7:
|
||||
case 0xD8:
|
||||
found = "an ext";
|
||||
break;
|
||||
case 0xCC:
|
||||
case 0xCD:
|
||||
case 0xCE:
|
||||
case 0xCF:
|
||||
case 0xD0:
|
||||
case 0xD1:
|
||||
case 0xD2:
|
||||
case 0xD3:
|
||||
found = "an integer";
|
||||
break;
|
||||
case 0xDC:
|
||||
case 0xDD:
|
||||
found = "an array";
|
||||
break;
|
||||
case 0xDE:
|
||||
case 0xDF:
|
||||
found = "a map";
|
||||
break;
|
||||
default:
|
||||
// fixint, fixmap, and fixarray; strings, EOF, and the unused
|
||||
// byte 0xC1 are left to get_msgpack_string
|
||||
if (current == char_traits<char_type>::eof())
|
||||
{
|
||||
return get_msgpack_string(result);
|
||||
}
|
||||
if (current <= 0x7F || current >= 0xE0)
|
||||
{
|
||||
found = "an integer";
|
||||
}
|
||||
else if (current <= 0x8F)
|
||||
{
|
||||
found = "a map";
|
||||
}
|
||||
else if (current <= 0x9F)
|
||||
{
|
||||
found = "an array";
|
||||
}
|
||||
else
|
||||
{
|
||||
return get_msgpack_string(result);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
auto last_token = get_token_string();
|
||||
return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
|
||||
exception_message(input_format_t::msgpack, concat("only string keys are supported, but found ", found, "; last byte: 0x", last_token), "object key"), nullptr));
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief reads a MessagePack byte array
|
||||
|
||||
@@ -2397,7 +2231,7 @@ class binary_reader
|
||||
{
|
||||
get();
|
||||
key.clear();
|
||||
if (JSON_HEDLEY_UNLIKELY(!get_msgpack_object_key(key) || !sax->key(key)))
|
||||
if (JSON_HEDLEY_UNLIKELY(!get_msgpack_string(key) || !sax->key(key)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
+96
-8
@@ -2,23 +2,111 @@ project('nlohmann_json',
|
||||
'cpp',
|
||||
version : '3.12.0',
|
||||
license : 'MIT',
|
||||
meson_version : '>= 0.64',
|
||||
default_options: ['cpp_std=c++11'],
|
||||
)
|
||||
|
||||
if get_option('MultipleHeaders')
|
||||
incdir = 'include'
|
||||
else
|
||||
incdir = 'single_include'
|
||||
endif
|
||||
|
||||
# The same compile definitions as the CMake target (see target_compile_definitions
|
||||
# in CMakeLists.txt): only an option that differs from its default adds one.
|
||||
json_defines = []
|
||||
if not get_option('GlobalUDLs')
|
||||
json_defines += 'JSON_USE_GLOBAL_UDLS=0'
|
||||
endif
|
||||
if not get_option('ImplicitConversions')
|
||||
json_defines += 'JSON_USE_IMPLICIT_CONVERSIONS=0'
|
||||
endif
|
||||
if get_option('DisableEnumSerialization')
|
||||
json_defines += 'JSON_DISABLE_ENUM_SERIALIZATION=1'
|
||||
endif
|
||||
if get_option('Diagnostics')
|
||||
json_defines += 'JSON_DIAGNOSTICS=1'
|
||||
endif
|
||||
if get_option('Diagnostic_Positions')
|
||||
json_defines += 'JSON_DIAGNOSTIC_POSITIONS=1'
|
||||
endif
|
||||
if get_option('LegacyDiscardedValueComparison')
|
||||
json_defines += 'JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON=1'
|
||||
endif
|
||||
if get_option('StrictNulHandling')
|
||||
json_defines += 'JSON_STRICT_NUL_HANDLING=1'
|
||||
endif
|
||||
|
||||
cpp_args = []
|
||||
foreach define : json_defines
|
||||
cpp_args += '-D' + define
|
||||
endforeach
|
||||
|
||||
nlohmann_json_dep = declare_dependency(
|
||||
include_directories: include_directories('single_include')
|
||||
compile_args: cpp_args,
|
||||
include_directories: include_directories(incdir)
|
||||
)
|
||||
meson.override_dependency('nlohmann_json', nlohmann_json_dep)
|
||||
|
||||
# The multi-header version under the name earlier versions of this file used
|
||||
nlohmann_json_multiple_headers = declare_dependency(
|
||||
compile_args: cpp_args,
|
||||
include_directories: include_directories('include')
|
||||
)
|
||||
|
||||
if not meson.is_subproject()
|
||||
install_headers('single_include/nlohmann/json.hpp', subdir: 'nlohmann')
|
||||
install_headers('single_include/nlohmann/json_fwd.hpp', subdir: 'nlohmann')
|
||||
install_subdir(
|
||||
incdir / 'nlohmann',
|
||||
install_dir: get_option('includedir'),
|
||||
install_tag: 'devel',
|
||||
)
|
||||
|
||||
pkgc = import('pkgconfig')
|
||||
pkgc.generate(name: 'nlohmann_json',
|
||||
version: meson.project_version(),
|
||||
description: 'JSON for Modern C++'
|
||||
)
|
||||
pkgc = import('pkgconfig')
|
||||
pkgc.generate(name: 'nlohmann_json',
|
||||
version: meson.project_version(),
|
||||
description: 'JSON for Modern C++',
|
||||
extra_cflags: cpp_args,
|
||||
install_dir: get_option('datadir') / 'pkgconfig',
|
||||
)
|
||||
|
||||
# CMake package config files, so that find_package(nlohmann_json) works. The
|
||||
# include directory is given relative to the config files, so that the
|
||||
# installation can be relocated. This is not possible if includedir or datadir
|
||||
# is an absolute path outside the prefix (e.g., with the separate outputs of
|
||||
# Nix); then the absolute include directory is used, as CMake does.
|
||||
fs = import('fs')
|
||||
cmake_install_dir = get_option('datadir') / 'cmake' / meson.project_name()
|
||||
cmake_to_prefix = []
|
||||
if fs.is_absolute(get_option('includedir')) or fs.is_absolute(cmake_install_dir)
|
||||
cmake_include_dir = (get_option('prefix') / get_option('includedir')).replace('\\', '/')
|
||||
else
|
||||
foreach component : cmake_install_dir.split('/')
|
||||
cmake_to_prefix += '..'
|
||||
endforeach
|
||||
cmake_include_dir = '${_IMPORT_PREFIX}/' + get_option('includedir')
|
||||
endif
|
||||
|
||||
cmake_conf = configuration_data()
|
||||
cmake_conf.set('PROJECT_NAME', meson.project_name())
|
||||
cmake_conf.set('PROJECT_VERSION', meson.project_version())
|
||||
cmake_conf.set('PROJECT_VERSION_MAJOR', meson.project_version().split('.')[0])
|
||||
cmake_conf.set('NLOHMANN_JSON_TARGET_NAME', meson.project_name())
|
||||
cmake_conf.set('NLOHMANN_JSON_TARGETS_EXPORT_NAME', meson.project_name() + 'Targets')
|
||||
cmake_conf.set('NLOHMANN_JSON_INCLUDE_DIR', cmake_include_dir)
|
||||
cmake_conf.set('NLOHMANN_JSON_CONFIG_TO_PREFIX', '/'.join(cmake_to_prefix))
|
||||
cmake_conf.set('NLOHMANN_JSON_COMPILE_DEFINITIONS', ';'.join(json_defines))
|
||||
|
||||
foreach cmake_file : [
|
||||
['cmake/config.cmake.in', 'nlohmann_jsonConfig.cmake'],
|
||||
['cmake/nlohmann_jsonConfigVersion.cmake.in', 'nlohmann_jsonConfigVersion.cmake'],
|
||||
['cmake/nlohmann_jsonTargets.cmake.in', 'nlohmann_jsonTargets.cmake'],
|
||||
]
|
||||
configure_file(
|
||||
input: cmake_file[0],
|
||||
output: cmake_file[1],
|
||||
configuration: cmake_conf,
|
||||
format: 'cmake@',
|
||||
install_dir: cmake_install_dir,
|
||||
)
|
||||
endforeach
|
||||
endif
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
option(
|
||||
'MultipleHeaders',
|
||||
type: 'boolean',
|
||||
value: false,
|
||||
description: 'Use non-amalgamated version of the library',
|
||||
)
|
||||
option(
|
||||
'GlobalUDLs',
|
||||
type: 'boolean',
|
||||
value: true,
|
||||
description: 'Place user-defined string literals in the global namespace',
|
||||
)
|
||||
option(
|
||||
'ImplicitConversions',
|
||||
type: 'boolean',
|
||||
value: true,
|
||||
description: 'Enable implicit conversions',
|
||||
)
|
||||
option(
|
||||
'DisableEnumSerialization',
|
||||
type: 'boolean',
|
||||
value: false,
|
||||
description: 'Disable default integer enum serialization',
|
||||
)
|
||||
option(
|
||||
'Diagnostics',
|
||||
type: 'boolean',
|
||||
value: false,
|
||||
description: 'Use extended diagnostic messages',
|
||||
)
|
||||
option(
|
||||
'Diagnostic_Positions',
|
||||
type: 'boolean',
|
||||
value: false,
|
||||
description: 'Enable diagnostic positions',
|
||||
)
|
||||
option(
|
||||
'LegacyDiscardedValueComparison',
|
||||
type: 'boolean',
|
||||
value: false,
|
||||
description: 'Enable legacy discarded value comparison',
|
||||
)
|
||||
option(
|
||||
'StrictNulHandling',
|
||||
type: 'boolean',
|
||||
value: false,
|
||||
description: 'Enable strict NUL-byte handling',
|
||||
)
|
||||
@@ -14059,80 +14059,6 @@ class binary_reader
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief reads a CBOR object key
|
||||
|
||||
RFC 8949 allows any data item as a map key, but only strings have a
|
||||
counterpart in JSON. A key of any other type is rejected with a message
|
||||
naming that type, rather than the one @ref get_cbor_string gives for a
|
||||
malformed string.
|
||||
|
||||
@param[out] result created key
|
||||
|
||||
@return whether key creation completed
|
||||
*/
|
||||
bool get_cbor_object_key(string_t& result)
|
||||
{
|
||||
// EOF and major type 3 (text string) are left to get_cbor_string
|
||||
if (current == char_traits<char_type>::eof() || (static_cast<unsigned int>(current) & 0xE0u) == 0x60u)
|
||||
{
|
||||
return get_cbor_string(result);
|
||||
}
|
||||
|
||||
const char* found = nullptr;
|
||||
switch (static_cast<unsigned int>(current) >> 5u)
|
||||
{
|
||||
case 0:
|
||||
found = "an unsigned integer";
|
||||
break;
|
||||
case 1:
|
||||
found = "a negative integer";
|
||||
break;
|
||||
case 2:
|
||||
found = "a byte string";
|
||||
break;
|
||||
case 4:
|
||||
found = "an array";
|
||||
break;
|
||||
case 5:
|
||||
found = "a map";
|
||||
break;
|
||||
case 6:
|
||||
found = "a tag";
|
||||
break;
|
||||
default: // major type 7
|
||||
switch (current)
|
||||
{
|
||||
case 0xF4:
|
||||
case 0xF5:
|
||||
found = "a boolean";
|
||||
break;
|
||||
case 0xF6:
|
||||
found = "null";
|
||||
break;
|
||||
case 0xF7:
|
||||
found = "undefined";
|
||||
break;
|
||||
case 0xF9:
|
||||
case 0xFA:
|
||||
case 0xFB:
|
||||
found = "a floating-point number";
|
||||
break;
|
||||
case 0xFF:
|
||||
found = "a break stop code";
|
||||
break;
|
||||
default:
|
||||
found = "a simple value";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
auto last_token = get_token_string();
|
||||
return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
|
||||
exception_message(input_format_t::cbor, concat("only string keys are supported, but found ", found, "; last byte: 0x", last_token), "object key"), nullptr));
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief reads a definite-length CBOR byte array
|
||||
|
||||
@@ -14377,7 +14303,7 @@ class binary_reader
|
||||
if (top.is_object)
|
||||
{
|
||||
key.clear();
|
||||
if (JSON_HEDLEY_UNLIKELY(!get_cbor_object_key(key) || !sax->key(key)))
|
||||
if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -14878,98 +14804,6 @@ class binary_reader
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief reads a MessagePack object key
|
||||
|
||||
The MessagePack specification allows any type as a map key, but only
|
||||
strings have a counterpart in JSON. A key of any other type is rejected
|
||||
with a message naming that type, rather than the one @ref
|
||||
get_msgpack_string gives for a malformed string.
|
||||
|
||||
@param[out] result created key
|
||||
|
||||
@return whether key creation completed
|
||||
*/
|
||||
bool get_msgpack_object_key(string_t& result)
|
||||
{
|
||||
const char* found = nullptr;
|
||||
switch (current)
|
||||
{
|
||||
case 0xC0:
|
||||
found = "nil";
|
||||
break;
|
||||
case 0xC2:
|
||||
case 0xC3:
|
||||
found = "a boolean";
|
||||
break;
|
||||
case 0xCA:
|
||||
case 0xCB:
|
||||
found = "a float";
|
||||
break;
|
||||
case 0xC4:
|
||||
case 0xC5:
|
||||
case 0xC6:
|
||||
found = "a bin";
|
||||
break;
|
||||
case 0xC7:
|
||||
case 0xC8:
|
||||
case 0xC9:
|
||||
case 0xD4:
|
||||
case 0xD5:
|
||||
case 0xD6:
|
||||
case 0xD7:
|
||||
case 0xD8:
|
||||
found = "an ext";
|
||||
break;
|
||||
case 0xCC:
|
||||
case 0xCD:
|
||||
case 0xCE:
|
||||
case 0xCF:
|
||||
case 0xD0:
|
||||
case 0xD1:
|
||||
case 0xD2:
|
||||
case 0xD3:
|
||||
found = "an integer";
|
||||
break;
|
||||
case 0xDC:
|
||||
case 0xDD:
|
||||
found = "an array";
|
||||
break;
|
||||
case 0xDE:
|
||||
case 0xDF:
|
||||
found = "a map";
|
||||
break;
|
||||
default:
|
||||
// fixint, fixmap, and fixarray; strings, EOF, and the unused
|
||||
// byte 0xC1 are left to get_msgpack_string
|
||||
if (current == char_traits<char_type>::eof())
|
||||
{
|
||||
return get_msgpack_string(result);
|
||||
}
|
||||
if (current <= 0x7F || current >= 0xE0)
|
||||
{
|
||||
found = "an integer";
|
||||
}
|
||||
else if (current <= 0x8F)
|
||||
{
|
||||
found = "a map";
|
||||
}
|
||||
else if (current <= 0x9F)
|
||||
{
|
||||
found = "an array";
|
||||
}
|
||||
else
|
||||
{
|
||||
return get_msgpack_string(result);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
auto last_token = get_token_string();
|
||||
return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
|
||||
exception_message(input_format_t::msgpack, concat("only string keys are supported, but found ", found, "; last byte: 0x", last_token), "object key"), nullptr));
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief reads a MessagePack byte array
|
||||
|
||||
@@ -15132,7 +14966,7 @@ class binary_reader
|
||||
{
|
||||
get();
|
||||
key.clear();
|
||||
if (JSON_HEDLEY_UNLIKELY(!get_msgpack_object_key(key) || !sax->key(key)))
|
||||
if (JSON_HEDLEY_UNLIKELY(!get_msgpack_string(key) || !sax->key(key)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
+2
-43
@@ -1830,51 +1830,10 @@ TEST_CASE("CBOR")
|
||||
SECTION("invalid string in map")
|
||||
{
|
||||
json _;
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_cbor(std::vector<uint8_t>({0xa1, 0xff, 0x01})), "[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing CBOR object key: only string keys are supported, but found a break stop code; last byte: 0xFF", json::parse_error&);
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_cbor(std::vector<uint8_t>({0xa1, 0xff, 0x01})), "[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing CBOR string: expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0xFF", json::parse_error&);
|
||||
CHECK(json::from_cbor(std::vector<uint8_t>({0xa1, 0xff, 0x01}), true, false).is_discarded());
|
||||
}
|
||||
|
||||
SECTION("non-string key (see #2766 and #3381)")
|
||||
{
|
||||
// only text strings map to JSON object keys; any other key is
|
||||
// rejected with a message naming its type
|
||||
const std::vector<std::pair<std::vector<std::uint8_t>, std::string>> cases =
|
||||
{
|
||||
{{0xA1, 0x01, 0x01}, "an unsigned integer; last byte: 0x01"},
|
||||
{{0xA1, 0x20, 0x01}, "a negative integer; last byte: 0x20"},
|
||||
{{0xA1, 0x41, 0x61, 0x01}, "a byte string; last byte: 0x41"},
|
||||
{{0xA1, 0x80, 0x01}, "an array; last byte: 0x80"},
|
||||
{{0xA1, 0xA0, 0x01}, "a map; last byte: 0xA0"},
|
||||
{{0xA1, 0xC0, 0x61, 0x61, 0x01}, "a tag; last byte: 0xC0"},
|
||||
{{0xA1, 0xF4, 0x01}, "a boolean; last byte: 0xF4"},
|
||||
{{0xA1, 0xF5, 0x01}, "a boolean; last byte: 0xF5"},
|
||||
{{0xA1, 0xF6, 0x01}, "null; last byte: 0xF6"},
|
||||
{{0xA1, 0xF7, 0x01}, "undefined; last byte: 0xF7"},
|
||||
{{0xA1, 0xF9, 0x3C, 0x00, 0x01}, "a floating-point number; last byte: 0xF9"},
|
||||
{{0xA1, 0xFA, 0x3F, 0x80, 0x00, 0x00, 0x01}, "a floating-point number; last byte: 0xFA"},
|
||||
{{0xA1, 0xFB, 0x3F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, "a floating-point number; last byte: 0xFB"},
|
||||
{{0xA1, 0xE0, 0x01}, "a simple value; last byte: 0xE0"},
|
||||
{{0xA1, 0xF8, 0x20, 0x01}, "a simple value; last byte: 0xF8"},
|
||||
// indefinite-length map
|
||||
{{0xBF, 0x01, 0x01, 0xFF}, "an unsigned integer; last byte: 0x01"},
|
||||
};
|
||||
|
||||
for (const auto& c : cases)
|
||||
{
|
||||
CAPTURE(c.first)
|
||||
const std::string expected = "[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing CBOR object key: only string keys are supported, but found " + c.second;
|
||||
json _;
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_cbor(c.first), expected.c_str(), json::parse_error&);
|
||||
CHECK(json::from_cbor(c.first, true, false).is_discarded());
|
||||
}
|
||||
|
||||
// a key of major type 3 with a reserved length is still reported as
|
||||
// a malformed string, and a missing key as the end of input
|
||||
json _;
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_cbor(std::vector<uint8_t>({0xA1})), "[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing CBOR string: unexpected end of input", json::parse_error&);
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_cbor(std::vector<uint8_t>({0xA1, 0x7C, 0x01})), "[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing CBOR string: expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x7C", json::parse_error&);
|
||||
}
|
||||
|
||||
SECTION("invalid UTF-8 in string (see #5529)")
|
||||
{
|
||||
// a two-character text string (major type 3) whose bytes are not
|
||||
@@ -2325,7 +2284,7 @@ TEST_CASE("CBOR indefinite-length strings do not recurse per chunk")
|
||||
SECTION("a break marker outside an indefinite-length string is not a string")
|
||||
{
|
||||
// 0xFF only closes a string that was opened; on its own it is not one
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_cbor(std::vector<uint8_t>({0xA1, 0xFF, 0x01})), "[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing CBOR object key: only string keys are supported, but found a break stop code; last byte: 0xFF", json::parse_error&);
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_cbor(std::vector<uint8_t>({0xA1, 0xFF, 0x01})), "[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing CBOR string: expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0xFF", json::parse_error&);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1551,69 +1551,10 @@ TEST_CASE("MessagePack")
|
||||
SECTION("invalid string in map")
|
||||
{
|
||||
json _;
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_msgpack(std::vector<uint8_t>({0x81, 0xff, 0x01})), "[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing MessagePack object key: only string keys are supported, but found an integer; last byte: 0xFF", json::parse_error&);
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_msgpack(std::vector<uint8_t>({0x81, 0xff, 0x01})), "[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing MessagePack string: expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0xFF", json::parse_error&);
|
||||
CHECK(json::from_msgpack(std::vector<uint8_t>({0x81, 0xff, 0x01}), true, false).is_discarded());
|
||||
}
|
||||
|
||||
SECTION("non-string key (see #3381)")
|
||||
{
|
||||
// only strings map to JSON object keys; any other key is rejected
|
||||
// with a message naming its type
|
||||
const std::vector<std::pair<std::vector<std::uint8_t>, std::string>> cases =
|
||||
{
|
||||
{{0x81, 0xC0, 0x01}, "nil; last byte: 0xC0"},
|
||||
{{0x81, 0xC2, 0x01}, "a boolean; last byte: 0xC2"},
|
||||
{{0x81, 0xC3, 0x01}, "a boolean; last byte: 0xC3"},
|
||||
{{0x81, 0xCA, 0x3F, 0x80, 0x00, 0x00, 0x01}, "a float; last byte: 0xCA"},
|
||||
{{0x81, 0xCB, 0x3F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, "a float; last byte: 0xCB"},
|
||||
{{0x81, 0xC4, 0x00, 0x01}, "a bin; last byte: 0xC4"},
|
||||
{{0x81, 0xC5, 0x00, 0x00, 0x01}, "a bin; last byte: 0xC5"},
|
||||
{{0x81, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x01}, "a bin; last byte: 0xC6"},
|
||||
{{0x81, 0xC7, 0x00, 0x01, 0x01}, "an ext; last byte: 0xC7"},
|
||||
{{0x81, 0xC8, 0x00, 0x00, 0x01, 0x01}, "an ext; last byte: 0xC8"},
|
||||
{{0x81, 0xC9, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01}, "an ext; last byte: 0xC9"},
|
||||
{{0x81, 0xD4, 0x01, 0x00, 0x01}, "an ext; last byte: 0xD4"},
|
||||
{{0x81, 0xD5, 0x01, 0x00, 0x00, 0x01}, "an ext; last byte: 0xD5"},
|
||||
{{0x81, 0xD6, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01}, "an ext; last byte: 0xD6"},
|
||||
{{0x81, 0xD7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, "an ext; last byte: 0xD7"},
|
||||
{{0x81, 0xD8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, "an ext; last byte: 0xD8"},
|
||||
{{0x81, 0xCC, 0x01, 0x01}, "an integer; last byte: 0xCC"},
|
||||
{{0x81, 0xCD, 0x00, 0x01, 0x01}, "an integer; last byte: 0xCD"},
|
||||
{{0x81, 0xCE, 0x00, 0x00, 0x00, 0x01, 0x01}, "an integer; last byte: 0xCE"},
|
||||
{{0x81, 0xCF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01}, "an integer; last byte: 0xCF"},
|
||||
{{0x81, 0xD0, 0x01, 0x01}, "an integer; last byte: 0xD0"},
|
||||
{{0x81, 0xD1, 0x00, 0x01, 0x01}, "an integer; last byte: 0xD1"},
|
||||
{{0x81, 0xD2, 0x00, 0x00, 0x00, 0x01, 0x01}, "an integer; last byte: 0xD2"},
|
||||
{{0x81, 0xD3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01}, "an integer; last byte: 0xD3"},
|
||||
{{0x81, 0x00, 0x01}, "an integer; last byte: 0x00"},
|
||||
{{0x81, 0x7F, 0x01}, "an integer; last byte: 0x7F"},
|
||||
{{0x81, 0xE0, 0x01}, "an integer; last byte: 0xE0"},
|
||||
{{0x81, 0x80, 0x01}, "a map; last byte: 0x80"},
|
||||
{{0x81, 0x8F, 0x01}, "a map; last byte: 0x8F"},
|
||||
{{0x81, 0xDE, 0x00, 0x00, 0x01}, "a map; last byte: 0xDE"},
|
||||
{{0x81, 0xDF, 0x00, 0x00, 0x00, 0x00, 0x01}, "a map; last byte: 0xDF"},
|
||||
{{0x81, 0x90, 0x01}, "an array; last byte: 0x90"},
|
||||
{{0x81, 0x9F, 0x01}, "an array; last byte: 0x9F"},
|
||||
{{0x81, 0xDC, 0x00, 0x00, 0x01}, "an array; last byte: 0xDC"},
|
||||
{{0x81, 0xDD, 0x00, 0x00, 0x00, 0x00, 0x01}, "an array; last byte: 0xDD"},
|
||||
};
|
||||
|
||||
for (const auto& c : cases)
|
||||
{
|
||||
CAPTURE(c.first)
|
||||
const std::string expected = "[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing MessagePack object key: only string keys are supported, but found " + c.second;
|
||||
json _;
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_msgpack(c.first), expected.c_str(), json::parse_error&);
|
||||
CHECK(json::from_msgpack(c.first, true, false).is_discarded());
|
||||
}
|
||||
|
||||
json _;
|
||||
// the unused byte 0xC1 is still reported as a malformed string
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_msgpack(std::vector<uint8_t>({0x81, 0xC1, 0x01})), "[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing MessagePack string: expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0xC1", json::parse_error&);
|
||||
// a missing key is still reported as the end of input
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_msgpack(std::vector<uint8_t>({0x81})), "[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing MessagePack string: unexpected end of input", json::parse_error&);
|
||||
}
|
||||
|
||||
SECTION("invalid UTF-8 in string (see #5529)")
|
||||
{
|
||||
// a fixstr of length 2 (0xA0 | 2) whose bytes are not valid UTF-8
|
||||
|
||||
@@ -1018,7 +1018,7 @@ TEST_CASE("regression tests 1")
|
||||
};
|
||||
|
||||
json _;
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_cbor(vec), "[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing CBOR object key: only string keys are supported, but found an array; last byte: 0x98", json::parse_error&);
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_cbor(vec), "[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing CBOR string: expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x98", json::parse_error&);
|
||||
|
||||
// related test case: nonempty UTF-8 string (indefinite length)
|
||||
std::vector<uint8_t> const vec1 {0x7f, 0x61, 0x61};
|
||||
@@ -1065,7 +1065,7 @@ TEST_CASE("regression tests 1")
|
||||
};
|
||||
|
||||
json _;
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_cbor(vec1), "[json.exception.parse_error.113] parse error at byte 13: syntax error while parsing CBOR object key: only string keys are supported, but found a map; last byte: 0xB4", json::parse_error&);
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_cbor(vec1), "[json.exception.parse_error.113] parse error at byte 13: syntax error while parsing CBOR string: expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0xB4", json::parse_error&);
|
||||
|
||||
// related test case: double-precision
|
||||
std::vector<uint8_t> const vec2
|
||||
@@ -1077,7 +1077,7 @@ TEST_CASE("regression tests 1")
|
||||
0x96, 0x96, 0xb4, 0xb4, 0xfa, 0x94, 0x94, 0x61,
|
||||
0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0xfb
|
||||
};
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_cbor(vec2), "[json.exception.parse_error.113] parse error at byte 13: syntax error while parsing CBOR object key: only string keys are supported, but found a map; last byte: 0xB4", json::parse_error&);
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_cbor(vec2), "[json.exception.parse_error.113] parse error at byte 13: syntax error while parsing CBOR string: expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0xB4", json::parse_error&);
|
||||
}
|
||||
|
||||
SECTION("issue #452 - Heap-buffer-overflow (OSS-Fuzz issue 585)")
|
||||
|
||||
Reference in New Issue
Block a user