sprintf(3s) query

Richard A. O'Keefe ok at quintus.uucp
Mon Dec 19 15:33:42 AEST 1988


In article <9205 at smoke.BRL.MIL> gwyn at brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes:
>In article <878 at quintus.UUCP> ok at quintus.UUCP (Richard A. O'Keefe) writes:
>-In article <9181 at smoke.BRL.MIL> gwyn at brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes:
>->I hope by now all the BSD code that depends on the value of
>->sprintf() being anything in particular has been changed to use
>->some other method.  Usually, something like
>->	buf[0] = '\0';
>->	(void)sprintf(buf, fmt, args);
>->	if (buf[0] == '\0')
>->		/* error */
>->is sufficient (it works with both definitions of sprintf()).
>-Except that it doesn't work with either.  Consider
>-	sprintf("%.*s", len, ptr);
>-when len happens to be 0.

>Again, I said "Usually, ..." which implies "not always".  The vast
>majority of sprintf() usage can correctly be changed to follow my
>suggestion.  I note that you offered no alternative.

I offered no alternative because I wanted to keep the message short.
According to the ULTRIX documentation, sprintf(3s) returns EOF to
indicate an error.  The alternative is thus
	#ifdef	BSD
	#define	BadSprintf (char*)(EOF) == sprintf
	#else /*SYS5*/
	#define	BadSprintf         EOF  == sprintf
	#endif
and then do
	if (BadSprintf(buf, fmt, args)) /* error */;

>-By the way, what _are_ the output error
>-conditions that *printf() can detect other than by crashing?

>There are several possible errors other than I/O errors.  Think
>hard enough and you should be able to imagine at least one.

I can _imagine_ a lot of possible errors, no problem.  The trouble is
that all the ones I've tested either dump core or are quietly accepted.
For example, "?" is not a defined conversion code, but sprintf accepts
"%.*?" as a format conversion, and writes '?'.  Then there are negative
field widths.  One might expect sprintf(buf, "%.*d", -9999, 44) to
either report an error or else act like "%-9999d", but it does neither.
It would be reasonable for sprintf(buf, "(%s)", (char*)NULL) to report
an error, but on my system it writes "((null))".  Another obvious error
is sprintf(buffer, "%4294967299d", 1), but it is not reported.  And so
it goes.

I think the following three points are uncontroversial:
(1) The (4.2BSD, S5R2, S5R3, Ultrix, SunOS) manual pages for printf(3s)
    do not say what any of the conditions which can cause an error return
    are.  (I haven't seen the 4.3BSD manual page.)
(2) There are a lot of errors which sprintf() either converts quietly to
    something plausible or dumps core with, not least buffer overflow.
(3) A portable program cannot rely on sprintf() catching any error at
    all, and thus had better do its own argument validation in any case.

It would be interesting to hear from someone who has UNIX sources what
the reported errors are.  



More information about the Comp.lang.c mailing list