Minor release with several breaking changes, marked BREAKING and ABI BREAKING below: read them before upgrading. Binaries must be rebuilt against the new headers, since cbor_incref and cbor_decref are no longer exported. Also includes the cbor_stream_decode security fixes released in 0.14.1.
- BREAKING: Preallocate definite arrays and maps in
cbor_loadonly as far as the input can hold their items (#418, based on #456 by nabbi)- Headers can declare up to 2^64 − 1 items, which
cbor_loadused to preallocate before reading any, so 5 bytes of input could request gigabytes. Declarations aboveCBOR_MAX_UNCHECKED_DECLARED_SIZE(new CMake option, 16 by default) are now preallocated only as far as the rest of the input can hold their items, and grow if more arrive. Valid input is preallocated as before - Inputs declaring more items than can be allocated now fail with the error found further on, usually
CBOR_ERR_NOTENOUGHDATA, and its position, instead ofCBOR_ERR_MEMERRORor an out-of-memory kill. Clients that read more data onCBOR_ERR_NOTENOUGHDATAwill keep reading on such inputs and need their own input size limit - Maps of 2^63 pairs or more on 64-bit platforms, and arrays of 2^32 items or more and maps of 2^31 pairs or more on 32-bit platforms, still fail with
CBOR_ERR_MEMERRORafter the header, since their item count does not fit insize_t - No public API change. The internal
struct _cbor_decoder_contextandstruct _cbor_stack_recordchange layout. Their headers are installed, and code that uses them with the exportedcbor_builder_*callbacks and_cbor_stack_push(asexamples/cjson2cbor.cdoes) must be rebuilt - Removed the test-only
SANE_MALLOCCMake option; the tests it enabled no longer depend on howmallochandles huge requests
- Headers can declare up to 2^64 − 1 items, which
- Make
_cbor_builder_appendand_cbor_decref_freeiterative socbor_loadandcbor_decrefrun in constant native stack space regardless of nesting depth (reported by PwnToday in #464)- Previously, completing deeply nested definite arrays, definite maps, or tags up to
CBOR_MAX_STACK_SIZE(2048) recursed on the call stack in_cbor_builder_append, and deallocating deep item trees recursed in_cbor_decref_free, overflowing constrained thread stacks or unoptimized/ASan stacks
- Previously, completing deeply nested definite arrays, definite maps, or tags up to
- Add
CBOR_TAG_*macro constants incbor/tags.hfor the 15 tag numbers defined in RFC 8949 Section 3.4, Table 5 (#166) - Document that item arguments must be valid and non-
NULLunless stated otherwise, and assert it in Debug builds (#457) - BREAKING: Stop exporting the internal
_cbor_map_add_keyand_cbor_map_add_value(#458); usecbor_map_addinstead - Stop linking the math library
- Declare copyright and license information in SPDX form, following the REUSE specification (#430)
- Source headers now carry
SPDX-FileCopyrightTextandSPDX-License-Identifiertags; data, documentation, and configuration files are covered byREUSE.toml; license texts are inLICENSES/ - libcbor remains MIT-licensed. Third-party parts are now labeled explicitly: the vendored CBOR WG test vectors (BSD-2-Clause),
FindCMocka.cmake(BSD-3-Clause),LibFindMacros.cmakeandoss-fuzz/build.sh(Apache-2.0), andJoinPaths.cmake(MIT OR CC0-1.0)
- Source headers now carry
- Reimplement half-precision float decoding without the RFC 7049 reference code
- The previous implementation was the BSD-2-Clause reference decoder from RFC 7049 Appendix D. The new one builds the single-precision bit pattern directly
- Allow building the library and examples without a C++ compiler when tests are disabled (by fhgffy)
- Requires CMake 3.12 or newer. Older CMake versions and
WITH_TESTS=ONstill need a C++ compiler
- Requires CMake 3.12 or newer. Older CMake versions and
- BREAKING:
cbor_encode_singleandcbor_encode_doublenow preserve NaN sign and payload bits- Previously, every NaN was encoded as the canonical quiet NaN (
0x7FC00000/0x7FF8000000000000), discarding the sign and payload. The bit pattern is now copied verbatim, matchingcbor_encode_halfsince 0.14.0 (#412) and making decode/encode round trips of NaNs lossless at all three widths - As with half-floats, signaling NaN payloads are preserved on a best-effort basis: some CPUs (x87) set the quiet bit when the value passes through a register
- Clients that relied on NaNs normalizing to the canonical encoding will see different output
- Previously, every NaN was encoded as the canonical quiet NaN (
- Run the CBOR Working Group test vectors as part of the test suite
- The
.cborcontainers from https://github.com/cbor-wg/cbor-test-vectors (BSD-2-Clause) are vendored intest/data/cbor-test-vectors; 1381 vectors, of which 3 known deviations (validity checks) are listed as expected failures intest/cbor_test_vectors_test.c, plus 12 signaling NaNs whose payload survives the round trip only on FPUs that do not quiet them
- The
- BREAKING: Decoders now accept all well-formed simple values
- Previously,
cbor_loadandcbor_stream_decoderejected the unassigned simple values 0 to 19 (0xE0to0xF3) and 32 to 255 (0xF8 0x20to0xF8 0xFF) withCBOR_ERR_MALFORMATED/CBOR_DECODER_ERROR, even though RFC 8949 Section 3.3 defines them as well-formed andcbor_build_ctrlcould already produce them. They are now decoded into ctrl items readable throughcbor_ctrl_value.0xF8followed by a byte below0x20remains a well-formedness error as specified - New
simple_valuemember appended tostruct cbor_callbacksand a matchingcbor_null_simple_value_callbackno-op. Like all other members, it must be set: existing callback sets that do not initialize it (e.g. designated initializers that predate the member) will dereferenceNULLon such input. Usecbor_null_simple_value_callbackto ignore these values, or start fromcbor_empty_callbacks - Discovered by running the CBOR Working Group test vectors (
rfc8949-appendixA/mt7-simple)
- Previously,
- BREAKING: Do not allocate zero-byte buffers for empty items, fixing creation and decoding failures on platforms and custom allocators where
malloc(0)returnsNULL(by afonsojanu, reported by hglee in #427)- Affected
cbor_new_definite_array(0),cbor_new_definite_map(0),cbor_build_bytestring(_, 0),cbor_build_string(""),cbor_build_stringn(_, 0),cbor_copy_definiteof indefinite strings with no data, andcbor_load/cbor_stream_decode(via the builder) for any input containing an empty string, bytestring, array, or map cbor_array_handle,cbor_map_handle,cbor_bytestring_handle, andcbor_string_handlenow returnNULLfor empty definite items on all platforms (previously an implementation-definedmalloc(0)result, non-NULLon glibc/macOS). The pointer was never valid to dereference; code that asserted it was non-NULLor passed it tomemcpy& co. with a zero length must be adjusted- Custom
freeimplementations installed viacbor_set_allocsmust acceptNULL(as the standardfreedoes); it is now passed for every empty item that is deallocated
- Affected
- Fix
cbor_encode_halfproducing corrupted output for values outside the half-precision range (by afonsojanu)- Finite inputs with magnitude >= 65536 previously overflowed the 5-bit exponent field into the sign and mantissa bits, silently encoding an unrelated finite value or a NaN (e.g.
100000.0fencoded as NaN,1e30fas-12.6172). Such values now saturate to signed infinity, consistent withINFINITYinputs
- Finite inputs with magnitude >= 65536 previously overflowed the 5-bit exponent field into the sign and mantissa bits, silently encoding an unrelated finite value or a NaN (e.g.
- ABI BREAKING: Inline
cbor_increfandcbor_decreffast pathscbor_increfandcbor_decrefare nowstatic inlineincbor/common.h; the deallocation branch ofcbor_decrefmoved into a new exported helper_cbor_decref_free. Source-compatible — same signatures and semantics — but the two symbols are no longer exported from the shared library, so binaries relying on their extern resolution (includingdlsym) will fail to link against the new.so. Rebuilding against the updated headers is sufficient.
Full Changelog: v0.14.0...v0.15.0