The vsnprintf() libc function called by sbuf_vprintf() returns the number of characters, *excluding the NULL-terminator*, that it would have written into the sbuf had sufficient space been available i.e. the sbuf needs len + 1 bytes of available space. SBUF_FREESPACE() reserves space for the NULL-terminator in its calculationAn off-by-one error exists in sbuf_vprintf()'s use of SBUF_HASROOM() when an sbuf is filled to capacity by vsnprintf(), and thus for vsnprintf() to have successfully written all of the bytesthe loop exits without error, SBUF_FREESPACE() must be greater than lenand the sbuf is not marked as auto-extendable.
SBUF_HASROOM() evaluates true if there is room for one or more non-NULL characters, but in the case that the sbuf was filled exactly to capacity, SBUF_HASROOM() evaluates false. Consequently, sbuf_vprintf() incorrectly assigns an ENOMEM error to the sbuf when in fact everything is fine, in turn poisoning the buffer for all subsequent operations.
Correct by moving the ENOMEM assignment into the loop where it can be made unambiguously.
As a related safety net change, explicitly check for the zero bytes drained case in sbuf_drain() and set EDEADLK as the error. This avoids an infinite loop in sbuf_vprintf() if a drain function were to inadvertently return a value of zero to sbuf_drain().
Sponsored by: Netflix, Inc.