Vulnerability Development mailing list archives

RE: OT: snprintf() null termination


From: Michael Wojcik <Michael.Wojcik () microfocus com>
Date: Thu, 30 May 2002 13:01:00 -0700

Last I checked, Microsoft's snprintf (actually _snprintf, thereby allowing
them to dodge the spec) also didn't follow the return-value convention used
by most Unix variants and enshrined by C99.  Those "good" snprintf
implementations return -1 for a formatting error, or the number of
characters that *would have been written* (not counting the terminating nul)
given a sufficiently large buffer.  That lets the caller determine whether
the buffer needs to be larger.

Microsoft's _snprintf returns -1 for a formatting error or buffer overrun.
Not very useful.

SUSv2's definition of snprintf says that the return value (in the absence of
a formatting error, and with a buffer size of at least 1) will be "the
number of characters transmitted", which is a bit ambiguous but sounds to me
like they're requiring the Wrong Thing - returning the number of characters
actually written into the buffer, and not the length the fully-formatted
string would have been.  If the return value is the buffer size, then there
may have been an overrun, and the only way to detect it is to try again with
a larger buffer.

Unless and until it's possible to target only C99, the safest thing to do
would be to assume you have to nul-terminate the buffer yourself, and if you
need to handle snprintf buffer overruns gracefully, wrap snprintf (or rather
vsnprintf) with a function that has conditionally-compiled code to handle
the various return value conventions.  On Windows, I'd use a heuristic: if I
get a -1 from vsnprintf, try enlarging the buffer, but don't let it grow
beyond a predefined maximum, so that formatting errors don't just eat up all
the available malloc space.  On SUSv2-compliant platforms, enlarge in the
boundary case where the return value matches the buffer size (possibly
fudged by one, since SUSv2 also isn't clear about whether the nul is
counted).

Pity K&R didn't just define snprintf right off the bat; in retrospect it
certainly seems like an obvious candidate, and sprintf clearly makes an
unreasonable assumption about the caller's ability to judge the output of
the formatter.  They gave us fgets as well as gets...

Or use a third-party [v]snprintf implementation.  I've seen a few, and
there's always GNU libc (which I believe does the right thing).

Michael Wojcik
Principal Software Systems Developer, Micro Focus
Department of English, Miami University


-----Original Message-----
From: Gerardo Richarte [mailto:core.lists.exploit-dev () core-sdi com]
Sent: Thursday, May 30, 2002 1:21 PM
To: vuln-dev () securityfocus com
Subject: Re: OT: snprintf() null termination


Vanja Hrustic wrote:

So - do all platforms properly null-terminate string (on 
overflow) when
snprintf() is used, or one should still use 
"sizeof(string)-1" for the
size of the snprintf()-ed string?

    regarding snprintf():

    -Linux, Solaris and OpenBSD do terminate with NUL when 
not enough space is available
    -Windows does not (Microsoft's libraries, at least up to 
Visual Studio 6)

    the other OSes where not tested, but I guess most unixes 
will (just guessing)

    gera


--- for a personal reply use: Gerardo Richarte <gera () corest com>



Current thread: