Releases: khanaffan/sqlite-msgpack
v1.5.0
v1.5.0
🔴 Security Fixes
- Fix critical integer overflow in MAP32/MAP16 validation (C API) —
count*2could wrap to zero for counts ≥ 0x80000000, bypassing validation of map elements. - Fix std::bad_alloc crash in C++ Blob API — oversized MAP32/ARRAY32 counts could trigger unbounded vector allocations. Added plausibility checks.
⬆️ SQLite Update
- Bundled SQLite updated from 3.51.3 → 3.53.1 (latest stable, May 2026)
🧪 Testing Improvements
- 8 new edge-case tests for overflow boundary values on MAP32 and ARRAY32
- 4 new fuzz corpus binary files targeting arithmetic overflow scenarios
✅ Full test suite passes (16/16)
v1.4.0 — Security & robustness hardening
What's new in v1.4.0
Security / robustness fixes
These bugs were found during a comprehensive code review; all are fixed in this release.
| Component | Bug | Impact |
|---|---|---|
msgpack.c |
mpSkipOne had no recursion depth limit — adversarial deep-nested blobs could stack-overflow during validation or mutation |
Stack overflow / crash on untrusted input |
msgpack_blob.cpp |
Same issue in C++ skip_one |
Stack overflow / crash on untrusted input |
msgpack_blob.cpp |
Value::binary(ptr, len) stored a raw pointer — use-after-free when the source Blob was destroyed before the Value |
Use-after-free / UB |
msgpack_blob.cpp |
Copied Value instances had stale blob_ptr_ — blob_data() returned a dangling pointer |
Use-after-free / UB |
Correctness fixes
Value::unsigned_integer(uint64_t): values > INT64_MAX now setIntWidth::Uint64soBuilder::value()encodes them correctly (previously re-encoded as signed, wrong wire bytes).tree_walkdepth limit: unified tokMaxDepth(200) — was hardcoded to 64, making deeply-nested iteration inconsistent with JSON conversion and merge-patch.
Tests
- 8 new C++ test functions: depth-limit regression, binary lifetime regression,
error_position,Iterator::reset, empty containers,unsigned_integerround-trip,Value::as_float(320 total assertions). - New C test group
test_misc:msgpack_version(),msgpack_pretty(blob, n), 250-deep-nest rejection regression (29 total assertions).
Fuzz corpus
94 → 104 seeds — adversarial inputs: 300-level nested array/map, unterminated deep chain, truncated str32/bin32/timestamp-ext headers, array32 with huge claimed count, partial map32, reserved byte 0xc1.
Documentation
- README.md: corrected compiler requirement C99 → C11/C++17; added Limits and robustness table; updated test counts.
- docs/cpp-api.md: documented
kMaxDepth/kMaxOutputconstants andValue::binarycopy semantics.
Upgrading
No API changes — drop-in replacement for v1.3.0.
v1.3.0 — Standalone C++ MsgPack Blob API
Highlights
This release adds a standalone C++ library for creating, querying, mutating, and iterating MessagePack blobs — with zero SQLite dependency. Blobs produced by the C++ API are byte-identical to those from the SQLite extension.
New: C++ Blob API (#include "msgpack_blob.hpp")
msgpack::Blob— owning byte buffer with path-based extraction, copy-on-write mutation (set/insert/replace/remove/array_insert/patch), and JSON conversionmsgpack::Value— decoded scalar with static constructors for all msgpack typesmsgpack::Builder— streaming encoder with method chainingmsgpack::Iterator— flat and recursive iteration (mirrorsmsgpack_each/msgpack_tree)
Full type coverage
All msgpack primitive types: nil, bool, integers (compact + fixed-width int8–int64/uint8–uint64), float32/64, string, binary, ext, timestamp (ts32/ts64/ts96), arrays, maps.
Comprehensive testing
- 289 standalone C++ unit tests (
msgpack_blob_unit) - 197 C++ ↔ SQLite interop tests (
msgpack_interop) — verifies byte-identical encoding, cross-API mutation, JSON round-trips, and iterator/vtable parity - Fuzz harness for every public C++ entry point with 94+ corpus seed files
- 16 CTest targets, all passing
Documentation & project files
docs/cpp-api.md— complete API reference with type tables, examples, and build integrationCONTRIBUTING.md— build, test, code style, and PR guidelinesSECURITY.md— vulnerability reporting policy and hardening measuresREADME.md— updated with C++ API and testing sections
Code quality
- Compiles cleanly with
-Wall -Wextra -Wpedantic -Wshadow -Wconversion -Wsign-conversion - No duplicate internal encoding logic (Builder methods are the single source of truth)
Full changelog: v1.1.0...v1.3.0
v1.2.0 — Performance Optimizations
Performance Optimizations
Seven targeted improvements across hot paths:
- JSON string serialization: batch consecutive safe characters (fewer
mpBufAppendcalls) - Pretty-print indentation: bulk-write spaces from a static buffer
- Binary→hex conversion: batch through a 128-byte stack buffer
msgpack_nil()/msgpack_true()/msgpack_false(): return static BLOBs — zero allocation per callmsgpack_patch()(RFC 7386 merge-patch): pre-scan patch keys into an index; Phase 2 drops from O(n×m) to O(m)- Window aggregate inverse: O(1) offset advance instead of O(n)
memmove; lazy compaction at 50% waste - Chained mutations (
msgpack_set,msgpack_insert, etc.): reuse value buffer across edits
Full Changelog
v1.1.0 — Schema Validation
What's new
msgpack_schema_validate(mp, schema)
New SQL function that validates a MessagePack BLOB against a declarative schema. Enables data-contract enforcement directly in SQL via CHECK constraints, triggers, or ad-hoc queries.
Schema keywords supported:
| Category | Keywords |
|---|---|
| Type | type (single or union array), const, enum |
| Numeric | minimum, maximum, exclusiveMinimum, exclusiveMaximum |
| Text | minLength, maxLength (UTF-8 codepoints) |
| Array | items, minItems, maxItems |
| Map | properties, required, additionalProperties |
Example:
CREATE TABLE users (
id INTEGER PRIMARY KEY,
profile BLOB NOT NULL
CHECK (msgpack_schema_validate(profile, '{
"type": "map",
"required": ["name", "age"],
"properties": {
"name": {"type": "text", "minLength": 1},
"age": {"type": "integer", "minimum": 0}
}
}'))
);Highlights
- Schema accepts JSON text or pre-compiled msgpack BLOB
- Automatic caching for constant schemas (zero per-row JSON parsing overhead)
- Recursive validation with depth limit (200 levels)
- Boolean schemas:
true(accept all) /false(reject all) - 87 unit tests + 24 fuzz corpus seeds + 14 fuzz harness targets
Bug fixes (found via fuzz testing)
mpReadStringAt: bounds check for oversized str32 headersmpMapFindKey: guard against out-of-bounds value offset- Schema caching: copy-then-cache to prevent use-after-free
Documentation
- Comprehensive schema validation section in README
- New standalone guide:
docs/schema-validation.md
v1.0.1
Security & Robustness Fixes
This release fixes multiple memory safety vulnerabilities found via fuzz testing and adds a libFuzzer harness for ongoing use.
Bug Fixes
-
Heap-buffer-overflow in
msgpack_to_json(): Map/array loops now break early when the cursor reaches the end of the blob, preventing hangs and null-emission on truncated containers. String/binary decoders now clamp payload lengths to the remaining buffer. -
Heap-buffer-overflow in
mpSkipOne(): Fixed integer overflow in bounds checks forstr32/bin32/ext32types where(i+sz<=n)could wrap u32, causingmpSkipOneto return positions before the cursor. Also fixed off-by-one header checks forext8/ext16/ext32. -
Heap-buffer-overflow in
mpToJsonAt(): Added missing bounds checks before reading integer and float values (uint8–int64,float32/float64) from truncated elements. -
Heap-buffer-overflow in
mpMergePatch(): Added missing bounds checks on MAP16/MAP32 header reads and loop cursor guards in both key-scan phases.
Hardening
- Recursion depth limit (
MP_MAX_DEPTH=200): Prevents stack overflow on deeply nested structures inmpToJsonAtandmpMergePatch. - Output buffer cap (
MP_MAX_OUTPUT=64MB): Prevents OOM from adversarial inputs that cause exponential output growth. - Integer overflow fix in
mpBufAppend/mpBufReservesize calculations.
Fuzz Testing Infrastructure
tests/fuzz_msgpack.c: libFuzzer harness exercising all 15+ SQL entry pointstests/fuzz_corpus/: 42 seed inputs covering every msgpack format typeCMakeLists.txt:MSGPACK_BUILD_FUZZ=ONoption (requires Clang with libFuzzer)
Validated with 1.1M+ fuzzer iterations under AddressSanitizer with zero crashes.
v1.0.0 — Initial release
sqlite-msgpack v1.0.0
Initial stable release.
What's included
- 30+ SQL functions modelled after SQLite's JSON1 extension:
msgpack_quote,msgpack_array,msgpack_object,msgpack_extract,msgpack_type,msgpack_set/insert/replace/remove,msgpack_patch,msgpack_array_insert,msgpack_from_json,msgpack_to_json,msgpack_pretty,msgpack_group_array,msgpack_group_object,msgpack_each,msgpack_tree,msgpack_valid,msgpack_error_position,msgpack_version - Full MessagePack spec compliance — all 36 format families, smallest-encoding rule, never-used byte detection
- JSON1-compatible path syntax —
$.key,$[N], chained navigation - Copy-on-write mutation — all mutation functions are side-effect free
- Window function support for
msgpack_group_arrayandmsgpack_group_object - Cross-platform build — Linux, macOS, Windows/MSVC via CMake ≥ 3.16
- GitHub Actions CI on
ubuntu-latest— all 9 CTest targets pass - 7-phase spec-compliance test suite — 283 cases covering every MessagePack format and every SQL function
- Performance benchmarks and size-comparison vs JSON text and JSONB binary (
MSGPACK_BUILD_BENCH=ON)
Quick start
cmake -B build && cmake --build build.load ./build/msgpack
SELECT msgpack_version(); -- 1.0.0
SELECT msgpack_to_json(msgpack_object('id',1,'name','Alice')); -- {"id":1,"name":"Alice"}
SELECT msgpack_extract(msgpack_from_json('[1,2,3]'), '$[1]'); -- 2