Since #4, bufreader_fill returns -1 when it cannot grow the read buffer.
read_until cannot tell that apart from end of stream:
int r = bufreader_fill(br);
if (r <= 0) {
int avail = bufreader_available(br);
if (avail > 0) { /* returns the buffered bytes as a complete result */ }
So an allocation failure part-way through a line is reported to the caller as a
successful short read, and read-line hands back a fragment that looks like a
whole line. Only a completely empty buffer becomes
(Result.Error "connection closed"), which also conflates EOF with failure.
This is better than the pre-#4 behaviour (a NULL dereference), and it only
triggers under allocation failure, so it is not urgent. But read-until,
read-line and read-n all treat r <= 0 as one condition and none of them
can currently say "the stream failed" as opposed to "the stream ended".
Fix is to distinguish the two at the bufreader_fill boundary (0 for EOF, -1
for error) and propagate that through the Result the Carp side returns.
Since #4,
bufreader_fillreturns-1when it cannot grow the read buffer.read_untilcannot tell that apart from end of stream:So an allocation failure part-way through a line is reported to the caller as a
successful short read, and
read-linehands back a fragment that looks like awhole line. Only a completely empty buffer becomes
(Result.Error "connection closed"), which also conflates EOF with failure.This is better than the pre-#4 behaviour (a NULL dereference), and it only
triggers under allocation failure, so it is not urgent. But
read-until,read-lineandread-nall treatr <= 0as one condition and none of themcan currently say "the stream failed" as opposed to "the stream ended".
Fix is to distinguish the two at the
bufreader_fillboundary (0 for EOF, -1for error) and propagate that through the
Resultthe Carp side returns.