1.3.0
Robustness, Safety, and Error Handling
π‘οΈ Major Robustness Improvements
This release makes SwiftMsgpack production-ready with comprehensive error handling and protection against malformed inputs.
π Security & Safety
- Added max nesting depth guard (512 levels) to prevent stack overflow attacks from deeply nested payloads
- Added corrupt flag to MsgPackScanner for early detection of malformed inputs
- Bounds checking for all reads β no more out-of-bounds access on truncated data
- Integer overflow guards β values that don't fit the target type now throw instead of truncating
- UTF-8 validation β invalid UTF-8 strings now throw DecodingError instead of returning garbage
π Critical Fixes
- Nil into non-optional β no longer crashes (now throws DecodingError)
- Empty data β now throws instead of crashing
- Data slices β now decode correctly without requiring a copy
- Truncated payloads β fixed-width, variable-length, and container headers all validate remaining bytes
- Huge claimed lengths (4GB+) β fail fast instead of exhausting memory
- Timestamp validation β negative nanoseconds and values β₯ 1e9 now throw
β‘ Performance
- Reserve capacity in encoder to reduce reallocations
- Container header size pre-calculation for more efficient writes
- loadUnaligned for safer and faster timestamp reading
π§ͺ Testing
Added comprehensive RobustnessTests suite covering:
- Truncated inputs
- Huge claimed lengths
- Deep nesting (200k levels)
- Nil into non-optional
- Invalid UTF-8
- Integer overflow
- Cross-format numeric interop
- Timestamp edge cases
- Data slice decoding
β οΈ Breaking Change
Decoding nil into non-optional types now throws DecodingError instead of returning nil. This aligns with Swift's standard JSONDecoder behavior and prevents silent data corruption.
// BEFORE: returned nil (crash on force unwrap)
let value = try decoder.decode(Int.self, from: Data([0xC0])) // π₯
// AFTER: throws DecodingError
let value = try decoder.decode(Int.self, from: Data([0xC0])) // β
throws