Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <20260722155416.GA27423@brightrain.aerifal.cx>
Date: Wed, 22 Jul 2026 11:54:16 -0400
From: Rich Felker <dalias@...c.org>
To: Demi Marie Obenour <demiobenour@...il.com>
Cc: musl@...ts.openwall.com,
	Luca Kellermann <mailto.luca.kellermann@...il.com>
Subject: Re: [PATCH] sprintf: fix one byte truncation when producing
 string of length INT_MAX

On Wed, Jul 22, 2026 at 11:46:55AM -0400, Rich Felker wrote:
> On Tue, Jul 21, 2026 at 10:33:08PM -0400, Demi Marie Obenour wrote:
> > On 7/21/26 18:28, Rich Felker wrote:
> > > On Tue, Jul 21, 2026 at 10:31:04PM +0200, Luca Kellermann wrote:
> > >> (v)sprint() is supposed to return the number of bytes written to s,
> > >> excluding the terminating null byte. however, when these functions
> > >> return INT_MAX, only INT_MAX - 1 bytes (excluding the terminating null
> > >> byte) are written.
> > >>
> > >> this is caused by the way vsprintf() is implemented: calling
> > >> vsnprintf() with n = INT_MAX. vsnprintf() returns the number of bytes
> > >> that would be written to s had n been sufficiently large excluding the
> > >> terminating null byte. output bytes beyond the n-1st are discarded.
> > >>
> > >> to accommodate the largest strings (v)sprintf() can produce (length
> > >> INT_MAX, the return value is of type int), vsnprintf() has to be
> > >> called with n >= INT_MAX + 1.
> > >>
> > >> calling vsnprintf() with n > INT_MAX is possible since commit
> > >> 11fb383275d20f5f94c00425bd888a02ecbd218e.
> > > 
> > > Thanks. Indeed, prior to this commit, there was no way for [v]sprintf
> > > to handle this case right, since vsnprintf would reject the larger
> > > size.
> > > 
> > > On 32-bit archs there was never a bug here, because objects of size
> > > larger than INT_MAX can't exist. But indeed your test case
> > > demonstrates the problem on 64-bit.
> > 
> > What does [v]snprintf do if the output would legitimately overflow
> > INT_MAX?
> 
> It returns -1 with errno set to EOVERFLOW.
> 
> For the other printf variants not specified to do this, the behavior
> is just undefined by virtue of not being able to satisfy the
> requirement that the return value be the number of bytes
> written/stored (since that number isn't representable in int).

Actually, good news: POSIX has been updated to specify the EOVERFLOW
behavior for all of them.

Unfortunately though requirement is POSIX-specific even for snprintf;
I had forgotten that. In the baseline C specification, the behavior is
just undefined so you need to be careful not to pass arguments that
would result in more than INT_MAX bytes if you care about portability
to implementations that don't meet the POSIX requirement. It would be
really nice to get this fixed, but getting WG14 to fix things is a
huge pain..

Rich

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.