bufio: readahead signals overflow when it cannot grow (F-B)
The scanner readahead silently fell through when start==0 and the
buffer was full at maxread, producing no bytes and no error. scanbyte
then spun forever re-requesting bytes that never came (catB-144) and
scanrune nil-dereferenced s.ptr[s.start] (catB-145).
Make readahead the single overflow choke-point: at the ceiling it
returns a bufio-local `overflow` before the grow, propagated through
scanbyte/scanrune/scanbytes (scanbytes drops its now-redundant manual
pre-check). Mirrors ref/hare/bufio/scanner.ha:174-182, which returns
errors::overflow there; ww uses bufio-local overflow because io.error
is a closed enum without an overflow member. Consumers (regex, the 778
embedded source) gain the totality arm.
Table-driven @test crosses {nil-ptr, zero-len} x {scanbyte, scanrune};
neutralizing the overflow return reproduces the catB-144 hang.
This commit is contained in:
@@ -1206,6 +1206,10 @@ fn search(
|
||||
};
|
||||
case let e: io.error => abort("regex: scanrune io error");
|
||||
case utf8.invalid => abort("regex: scanrune invalid utf8");
|
||||
// Unreachable: this scanner is newscanner(h, I32_MAX), so the
|
||||
// can't-grow ceiling is never hit; the arm keeps the match
|
||||
// total over scanrune's widened overflow surface (drain F-B).
|
||||
case bufio.overflow => abort("regex: scanrune overflow");
|
||||
};
|
||||
if (r_or_end is rune) {
|
||||
last_bytesize = (utf8.runesz(r_or_end as rune): size);
|
||||
|
||||
Reference in New Issue
Block a user