github PJK/libcbor v0.15.0

one hour ago

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_load only 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_load used to preallocate before reading any, so 5 bytes of input could request gigabytes. Declarations above CBOR_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 of CBOR_ERR_MEMERROR or an out-of-memory kill. Clients that read more data on CBOR_ERR_NOTENOUGHDATA will 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_MEMERROR after the header, since their item count does not fit in size_t
    • No public API change. The internal struct _cbor_decoder_context and struct _cbor_stack_record change layout. Their headers are installed, and code that uses them with the exported cbor_builder_* callbacks and _cbor_stack_push (as examples/cjson2cbor.c does) must be rebuilt
    • Removed the test-only SANE_MALLOC CMake option; the tests it enabled no longer depend on how malloc handles huge requests
  • Make _cbor_builder_append and _cbor_decref_free iterative so cbor_load and cbor_decref run 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
  • Add CBOR_TAG_* macro constants in cbor/tags.h for the 15 tag numbers defined in RFC 8949 Section 3.4, Table 5 (#166)
  • Document that item arguments must be valid and non-NULL unless stated otherwise, and assert it in Debug builds (#457)
  • BREAKING: Stop exporting the internal _cbor_map_add_key and _cbor_map_add_value (#458); use cbor_map_add instead
  • Stop linking the math library
    • libcbor no longer calls ldexp (#453), so the build no longer checks for it or links -lm where ldexp is not in libc (#169). Code that relied on libcbor to pull in libm must link it itself
  • Declare copyright and license information in SPDX form, following the REUSE specification (#430)
    • Source headers now carry SPDX-FileCopyrightText and SPDX-License-Identifier tags; data, documentation, and configuration files are covered by REUSE.toml; license texts are in LICENSES/
    • 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.cmake and oss-fuzz/build.sh (Apache-2.0), and JoinPaths.cmake (MIT OR CC0-1.0)
  • 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=ON still need a C++ compiler
  • BREAKING: cbor_encode_single and cbor_encode_double now 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, matching cbor_encode_half since 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
  • Run the CBOR Working Group test vectors as part of the test suite
    • The .cbor containers from https://github.com/cbor-wg/cbor-test-vectors (BSD-2-Clause) are vendored in test/data/cbor-test-vectors; 1381 vectors, of which 3 known deviations (validity checks) are listed as expected failures in test/cbor_test_vectors_test.c, plus 12 signaling NaNs whose payload survives the round trip only on FPUs that do not quiet them
  • BREAKING: Decoders now accept all well-formed simple values
    • Previously, cbor_load and cbor_stream_decode rejected the unassigned simple values 0 to 19 (0xE0 to 0xF3) and 32 to 255 (0xF8 0x20 to 0xF8 0xFF) with CBOR_ERR_MALFORMATED / CBOR_DECODER_ERROR, even though RFC 8949 Section 3.3 defines them as well-formed and cbor_build_ctrl could already produce them. They are now decoded into ctrl items readable through cbor_ctrl_value. 0xF8 followed by a byte below 0x20 remains a well-formedness error as specified
    • New simple_value member appended to struct cbor_callbacks and a matching cbor_null_simple_value_callback no-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 dereference NULL on such input. Use cbor_null_simple_value_callback to ignore these values, or start from cbor_empty_callbacks
    • Discovered by running the CBOR Working Group test vectors (rfc8949-appendixA/mt7-simple)
  • BREAKING: Do not allocate zero-byte buffers for empty items, fixing creation and decoding failures on platforms and custom allocators where malloc(0) returns NULL (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_definite of indefinite strings with no data, and cbor_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, and cbor_string_handle now return NULL for empty definite items on all platforms (previously an implementation-defined malloc(0) result, non-NULL on glibc/macOS). The pointer was never valid to dereference; code that asserted it was non-NULL or passed it to memcpy & co. with a zero length must be adjusted
    • Custom free implementations installed via cbor_set_allocs must accept NULL (as the standard free does); it is now passed for every empty item that is deallocated
  • Fix cbor_encode_half producing 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.0f encoded as NaN, 1e30f as -12.6172). Such values now saturate to signed infinity, consistent with INFINITY inputs
  • ABI BREAKING: Inline cbor_incref and cbor_decref fast paths
    • cbor_incref and cbor_decref are now static inline in cbor/common.h; the deallocation branch of cbor_decref moved 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 (including dlsym) will fail to link against the new .so. Rebuilding against the updated headers is sufficient.

Full Changelog: v0.14.0...v0.15.0

Don't miss a new libcbor release

NewReleases is sending notifications on new releases.