Skip to content

Ghost Serialization 1.2.0 Latest

Choose a tag to compare

@juanchurtado1991 juanchurtado1991 released this 30 May 09:20
· 520 commits to main since this release

This release introduces native, declarative network annotations (@GhostStrict and @GhostCoerce) across all major HTTP integrations (Retrofit, Spring Boot, and Ktor), implements critical security and boundary bug fixes with zero-allocation performance preservation, and recovers maximum lenient parsing throughput by default in all network adapters.


🚀 What's New

🛠️ Declarative Network Customization

  • Native Declarative Annotations (@GhostStrict & @GhostCoerce): Shipped new dynamic annotations for elegant, declarative, and zero-allocation parsing customization:
    • Retrofit: Fully supports @GhostStrict and @GhostCoerce on API service interface methods to customize parser configurations dynamically per endpoint.
    • Spring Boot (Spring WebMvc): Integrates native thread-safe annotation scanning using RequestBodyAdvice. Supports @GhostStrict and @GhostCoerce at the controller class, endpoint method, or @RequestBody parameter levels out-of-the-box.
    • Ktor (KMP): Enhanced the GhostContentConverter in ghost-ktor with a custom configurer lambda parameter, enabling developers to dynamically tune or enforce strict/coerced settings directly in their KMP ContentNegotiation pipelines.

🛠️ What's Changed

🛡️ Core Security & Resilience Fixes

  • Scientific Notation Exponent Integer Overflow: Fixed a vulnerability in parseExponentValue for flat and streaming readers by clamping exponent values exceeding 1000 to prevent integer overflows.
  • Geometric Capacity Overflow Protection: Fixed a potential buffer overflow vulnerability in FlatByteArrayWriter.ensureCapacity by safely catching integer overflows and clamping growth boundaries to Int.MAX_VALUE.
  • Dynamic Key Hash Collision mixing: Eliminated perfect hash collision vulnerabilities in JsonReaderOptions and reader subsystems by dynamically detecting perfect key collisions at initialization and conditionally applying a branchless last-byte mix.
  • Serializer Delegation Config Preservation: Fixed a configuration propagation leak in the GhostSerializer.deserialize(GhostJsonFlatReader) default delegation method by copying all configuration attributes (e.g. strictMode, coerceStringsToNumbers) to the delegated streaming reader.
  • Negative Depth Boundary Safety: Protected reader depth decrement operations in endObject() and endArray() to stay non-negative, preventing bitmask corruption under malformed or resilient parsing.
  • Unbounded Surrogate Parser Checks: Fixed a boundary bug in GhostJsonReader and GhostJsonFlatReaderStrings where checking for trailing unicode surrogate pairs at the end of truncated strings caused IndexOutOfBoundsException instead of structured GhostJsonException.
  • Long Overflow Check: Fixed a silent overflow bug in calculateLongWithOverflowCheck where values matching Long.MIN_VALUE with additional trailing digits bypassed overflow verification.

⚙️ Parser & Writer Correctness

  • Strict Comma Validation: Enforced strict JSON comma checking in both streaming and flat readers using zero-allocation bitwise mask tracking. Bound strictly to strictMode = true to preserve maximum lenient parsing speed by default.
  • Iterative Comma Synchronization in hasNext(): Fixed a critical parser state leak in hasNext() where commaConsumedMask and needsCommaMask were not correctly cleared and tracked during iterative loops like skipValue().
  • Select Separator Comma Synchronization: Fixed internalSelect in both flat and streaming readers to correctly synchronize and clear commaConsumedMask when a separator comma is consumed, resolving unexpected comma errors in subsequent field decodes.
  • Strict Byte Checking: Resolved a project rule violation in expectByte by replacing the prohibited toChar() extension method with the direct Char(expected) constructor path.
  • Negative Zero Sign Loss: Corrected double formatting in GhostDoubleFormatter to preserve the minus sign for -0.0 by performing a zero-copy raw bits sign check.
  • Double Formatter Precision Threshold: Lowered MASSIVE_DOUBLE_THRESHOLD from 1e15 to 1e9 in GhostDoubleFormatter to guarantee standard-compliant shortest representation.
  • Leading Zero Shift Masking: Corrected a shift-masking bug in validateLeadingZero where non-digit characters in the ASCII range of 112..121 were validated as digits.
  • Flat Writer Infinite Loop: Fixed an infinite loop in ensureCapacity when FlatByteArrayWriter was initialized with zero capacity.
  • Primitive Collection Doubling: Fixed an ArrayIndexOutOfBoundsException in GhostIntList and GhostLongList when initialized with zero capacity.

⚡ Performance & Allocation Optimization

  • Zero-Allocation Stream Decoding: In StreamingGhostSource.decodeToString, eliminated a temporary Buffer allocation and segment copy. Now leverages Okio's snapshot(end).substring(start, end).utf8() directly, resulting in zero-copy range views of existing buffered segments.
  • Pool Tier Collision: Resolved a collision in GhostPools.kt where SCRATCH_BUFFER_SIZE (48 bytes) and TIER_SMALL (1024 bytes) shared the same pool slot. Added a dedicated scratch field to GhostPool to prevent buffer eviction leaks.

🐘 Compiler (KSP) & Gradle

  • Non-Nested Sealed Subclasses: Enhanced KSP generation to scan superTypes for sealed parents. This ensures that non-nested/top-level sealed subclasses correctly serialize and deserialize their type discriminator key.
  • Gradle Plugin KSP Setup Order: Refactored KSP compiler dependency injection in the Gradle plugin to be completely order-independent and reactive to KSP and KMP target application sequences.

📚 Documentation

  • Updated README.md and CHANGELOG.md with complete usage guides, annotations targets, and configuration examples for Retrofit, Spring Boot, and Ktor.