Changelog v0.6.0
Release Date: 2026-06-10
🛡️ Hardening + perf release. Adds crash/OOM guards against untrusted input and a faster float emit path. Output format is unchanged; the new guards are on-by-default for raw-bytes/CLI input and transparent on the dict/list hot path.
Security & Robustness
Stack-overflow crash guard for deeply-nested input (#21)
- Deeply-nested JSON previously overflowed the stack in both the sonic-rs DOM parser and the recursive emitter, aborting the host process near depth ~50k (
SIGSEGV/abort) through the raw-bytes (dumps(bytes)) and CLI/file paths. sonic-rs's DOM parse usesDocumentVisitor, not serde's 256-level guard, so it had no built-in depth cap. - New
max_depthoption (default1000) runs anO(n)pre-scan that rejects over-deep input before parsing, covering both recursion sources in a single pass. The scan skips string interiors withmemchrand classifies structural bytes via a lookup table. - Untrusted input now returns a clean error (
ValueError/ CLI exit 1) instead of crashing the process.
Input-size OOM guard (#21)
- New
max_input_bytesoption (default0= off) lets callers encoding untrusted byte input bound peak memory.
Performance
Faster float-heavy emit (−33%) (#21)
write_floatnow usesryu, falling back to stdDisplayonly when ryu emits scientific notation (TOON requires expanded decimals). Array-length headers useitoa.- Float-heavy payloads: 275.8µs → 184.2µs (−33%); tabular / nested / string payloads neutral.
- No hot-path regression: dict/list input is already depth-bounded by orjson + CPython's recursion limit, so the Python wrapper passes
max_depth=0on that path to skip the redundant pre-scan — the guard cost lands only where untrusted raw bytes actually enter.
Pull Requests
| PR | Description |
|---|---|
| #21 | feat: crash/OOM guards + ryu float emit (v0.6.0) |
Full Changelog: v0.5.0...v0.6.0