boundedread

package module
v0.1.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 17, 2026 License: MIT Imports: 11 Imported by: 0

README

Documentation

Overview

Package boundedread provides a go/analysis analyzer for the resiliency rule that a read of a stream whose size this code does not control must carry an explicit bound: io.ReadAll over a caller-supplied reader or an HTTP body allocates whatever the peer sends, which is a denial of service the program asked for. The conforming forms are io.ReadAll(io.LimitReader(r, max)), io.CopyN, and http.MaxBytesReader.

The sinks

Three shapes pull an entire stream into memory and are reported: io.ReadAll (and the ioutil alias), io.Copy into a *bytes.Buffer or *strings.Builder — a ReadAll spelled differently — and (*bytes.Buffer).ReadFrom, which is that same copy written as a method. Copying to a file, a socket, or a ResponseWriter streams and allocates nothing unbounded, so it is not a sink.

The sources, and why the set is small

A finding needs a source whose size is provably outside this code's reach. Exactly two shapes qualify, and -sources selects which of them are claimed:

  • An HTTP message BODY — the Body field of an http.Request or an http.Response. The peer chooses that length, never this program, and no caller can bound it on this code's behalf. This class needs no judgment and is the DEFAULT (-sources=http).
  • A PARAMETER whose static type is a stream interface declared in io or net — io.Reader, io.ReadCloser, net.Conn, and so on. This is the same "untrusted input" that yze/fuzzreq classifies, seen from the reading side: the value arrives from a caller, its dynamic type is invisible here, and no interface can advertise a length. Such a read is unbounded by the letter, but whether the BOUND belongs here or at the caller is a design question a reviewer answers, so the class is opt-in (-sources=all). See sources.go.

Everything else is deliberately SILENT, because the alternative is a rule that fires on ordinary correct code:

  • A LOCAL variable is silent, whatever its type. `lr := io.LimitReader(r, max); io.ReadAll(lr)` is the conforming form and holds an io.Reader; a rule that judged the interface alone would report the very fix it asks for. Judging a local means tracking what was assigned to it, which is dataflow this analyzer does not do.
  • A CONCRETE type is silent — *bytes.Reader, *strings.Reader, an embed.FS entry, *io.LimitedReader, and *os.File alike. The first four are bounded by construction; a file the program itself named is the judgment call the rule declines to make, since reading a config file the operator chose is not a denial of service. The known cost of that line is a concrete socket — *net.TCPConn and its siblings are unbounded and go unreported, because a socket is nearly always held as net.Conn.
  • A REBOUND source is silent: if any assignment in the package replaces the parameter or the Body field (`r = io.LimitReader(r, max)`, `req.Body = http.MaxBytesReader(w, req.Body, max)`), the value read is no longer the one that arrived, so nothing is claimed about it.
  • TEST files are out of scope: a test reads the fixture it wrote itself.

bufio.Scanner is deliberately absent

A scanner is commonly named as an unbounded read, and the premise does not hold: bufio.Scanner caps a token at bufio.MaxScanTokenSize (64 KiB) and returns bufio.ErrTooLong past it, so the DEFAULT scanner is already bounded and reporting it would be a false positive. Only an explicit Buffer(buf, huge) removes the cap — and deciding which cap is "huge", and tying a Buffer call back to the source its scanner was built from, is dataflow and judgment rather than a provable fact. The rule stays silent rather than guess.

Index

Constants

This section is empty.

Variables

View Source
var Analyzer = newAnalyzer()

Analyzer reports unbounded reads of streams whose size is beyond the code's sight.

View Source
var Registration = goyze.Registration{
	Name:       "boundedread",
	Categories: []goyze.Category{"patterns"},
	URL:        "https://docs.gomatic.dev/yze/boundedread",
	Analyzer:   Analyzer,
}

Registration declares this analyzer to the yze framework.

Functions

This section is empty.

Types

This section is empty.

Directories

Path Synopsis
cmd
yze-go-boundedread command
Command yze-go-boundedread runs the boundedread analyzer as a standalone go/analysis checker (text and -json output, and usable as a `go vet -vettool`).
Command yze-go-boundedread runs the boundedread analyzer as a standalone go/analysis checker (text and -json output, and usable as a `go vet -vettool`).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL