limitedReader.Read passed the caller's buffer to the source untouched and
only looked at the running total afterwards, and the refusal did not stick.
io.Reader asks callers to process the n>0 bytes of a read before treating
its error as fatal, so a caller following that advice — encoding/json's
Decoder among them — kept getting real data on every call after the limit
had already been passed. With a 5 byte limit and a 50 byte body, 50 bytes
came through.
The read is now capped at one byte past the limit, which is all it takes to
know the body is too large; that byte is not handed to the caller; and once
the limit is passed the reader stays refused without touching the source
again.
Fixes labstack#3071
Fixes #3071.
limitedReader.Read passed the caller's buffer to the source untouched and only looked at the running total afterwards, and the refusal did not stick. io.Reader asks callers to process the n>0 bytes of a read before treating its error as fatal, so a caller following that advice kept getting real data on every call after the limit had already been passed.
With a 5 byte limit against a 50 byte body, reading the way the docs describe returned all 50.
Three changes, each of which the tests pin separately:
Existing BodyLimit tests are unchanged and pass.