Skip to content

1.1.0

Latest

Choose a tag to compare

@samoht samoht released this 22 Jul 17:10
9a6e463

CHANGES:

Added

  • Wire.Expr.land64 is an int64 bitwise AND for masking a full-width uint64
    field inside a constraint, and ~self_int64 / Field.int64 now accept a
    map-decoded uint64 field. A sign-magnitude offset bound such as a bsdiff
    seek (land64 self mask <= max) is now expressible and projects to a 3D
    refinement EverParse verifies (#227, @samoht)

Changed

  • The standalone c/ archive (3d mode) now builds and installs in every dune
    context through that context's own toolchain, so a cross build produces and
    installs a target-native verified parser instead of skipping the C. The build
    uses %{ocaml-config:c_compiler}, the ocaml-config partial linker, and the
    binutils that compiler resolves (-print-prog-name), so a cross cc finds
    the target's objcopy/ar. EverParseEndianness.h gains a freestanding
    __BYTE_ORDER__/__builtin_bswap* branch so it compiles for an OS-less
    target (a unikernel defines neither __linux__ nor __APPLE__). Only C
    regeneration and the agree differential test stay host-gated (#231, @samoht)

  • uint32/uint32be now decode to Optint.t and uint63/uint63be to
    Optint.Int63.t rather than a native int, so a value with bit 31 (or the
    high half) set is no longer silently truncated on a target whose int is
    narrower than 63 bits (js_of_ocaml, wasm_of_ocaml); a TCP sequence number now
    round-trips there. Read such a field with Optint.to_int / Optint.to_int32;
    a uint32 used as a size parameter must become int32be (#226, @samoht)

  • Decode errors are redesigned. parse_error is now a { at; field; kind }
    record instead of a flat variant: at is the failing field's byte offset,
    field the root-to-leaf path of field names to it, and kind a closed
    error_kind (Unexpected_eof, Invalid_enum, Invalid_tag,
    Missing_terminator, Non_zero_padding, Value_out_of_range,
    Constraint_failed), so a failure deep in a nested struct is both locatable
    and matchable. Constraint_failed of string becomes
    Constraint_failed { which; value }, naming the predicate that failed and
    carrying the offending field's value. Validation_error is removed
    (Codec.validate and the _exn decoders raise the single Parse_error), and
    the type gains equal_parse_error / compare_parse_error, pp_error_kind,
    and public parse_error / eof constructors. Match on e.kind, read e.at,
    replace Validation_error with Parse_error, and wrap Wire.parse_error in
    your own variant for domain errors (#219, @samoht)

  • Decoding a record codec with 17 to 32 fields no longer allocates a
    short-lived closure on each decode: the closure-free decode ceiling that
    1.0.0 raised to 16 fields now extends to 32. Real protocol headers cross the
    old limit routinely, such as an 18-field TCP header with its flag bits broken
    out, or telemetry and IPv4 headers in the high twenties, which now allocate
    only the record they return. A codec wider than 32 fields keeps the recursive
    fallback (#214, @samoht)

Fixed

  • A standalone Wire_3d archive no longer exposes its raw <Base>Validate*
    validators to C callers. Those entrypoints skip a StartPosition <= InputLength bound check, so a direct caller passing StartPosition > InputLength underflowed the read span and went out of bounds. The install now
    ships only the checked <Base>Wrapper.h header (not <Base>.h), and the
    archive build localizes every symbol except the <Base>Check<Codec> wrappers,
    so the raw validators are neither declared nor linkable; the wrapper validates
    from position 0 and is the safe public API (#228, #229, @samoht)

  • Codec values are now safe to share across domains: their validation scratch
    and parameter backing are per-domain, so encoding, decoding, or validating one
    codec concurrently no longer corrupts the result (#223, #224, @samoht)

  • A generated FFI parser (parse buf off) now raises Invalid_argument when
    off is negative or past the end of buf, instead of reading out of bounds.
    The C stub computed its length as Bytes.length buf - off in unsigned
    arithmetic, so an out-of-range off (which can carry a length or offset field
    parsed from untrusted input) underflowed the length into a huge span and
    pushed the read pointer past the buffer before the validator ran. An in-range
    off is unaffected (#222, @samoht)

  • A non-zero byte in an all_zeros padding field now reports the same error
    whether the field is decoded through a struct (Codec.decode /
    Codec.validate) or directly (Wire.of_string). The struct path used to
    report a stringly Constraint_failed that dropped the byte offset while the
    direct path reported the typed All_zeros_failed with the offset; both now
    report All_zeros_failed carrying the offset (#220, @samoht)

  • A casetype whose discriminant matches no case now fails with the typed
    Invalid_tag carrying the tag value, the same class as an out-of-range lookup
    index, instead of a stringly Constraint_failed (#220, @samoht)

  • A non-integer field referenced where an integer is required (a schema mistake,
    such as a float used as a length) now raises Invalid_argument rather than a
    parse error, keeping schema errors distinct from malformed input (#220,
    @samoht)