6.1.2 - Bounded chunk-fetch body
A crash fix on the FFmpeg/AVIO source path. Anyone opening large progressive HTTP sources on iOS or tvOS wants this one.
Fixed
-
Opening a large progressive HTTP source no longer dies in the allocator before the first frame.
ChunkFetchDelegatereserved whatever the response declared, with no ceiling:body.reserveCapacity(Int(http.expectedContentLength)). One of the requests that reaches that line is the HEAD size probe, and a HEAD declares the entire source while delivering zero body bytes, so opening a 12.4 GB MKV asked malloc for 12.4 GB in order to buffer nothing. On a 6 GB iPhone the allocation returned NULL and__DataStorage.init(capacity:)force-unwrapped it:EXC_BREAKPOINTon the URLSession delegate queue, before a frame played. It traps rather than throwing, so a host app could neither catch it nor degrade. Reported by dlev02 from a symbolicated crash report and register state (#255).The surface was wider than the reported case.
probeFileSize()launches the HEAD fallback 0.75 s after the range probes and runs it whenever they have not resolved a size yet, so any non-prefetch open (still extraction, one-shot seekable) against a slow origin could take the crash, not only an origin that rejects Range outright.Both halves of the fix come from the request instead of the response. The reservation is the declared length clamped to what the request itself can deliver: the span of a bounded
Range: bytes=a-b, nothing at all for a HEAD, a flat 8 MB ceiling when the request is open-ended.Datagrows on demand, so the cap costs at most one reallocation on a legitimately larger body.The body is bounded by that same span. An origin that ignores
Rangeand answers a bounded chunk request with200plus the whole source's length used to be buffered in full and only then rejected by the caller's status check; the reader now keeps the prefix it asked for and hangs up. Measured against a scripted origin, that path pulled 134 MB over the wire and then failed the read outright; it now writes single-digit MB, and the truncated chunk serves the read.Not affected: the persistent and streaming reader paths, whose resident window is bounded at 48 MB by the reader's own backpressure cap whatever the origin does, and
HTTPDiscIOReader, which never reserves from a declared length and requires working Range support at init.
Upgrading
.package(url: "https://github.com/superuser404notfound/AetherEngine", from: "6.1.2")No API change and no source change for consumers.