printf behaviour with illegal or malformed format string

Max Laier max at love2party.net
Mon Dec 12 07:43:52 PST 2005


On Monday 12 December 2005 13:14, Poul-Henning Kamp wrote:
> Obligatory bikeshed avoidance notice:
> >> Please read all the way to the bottom of this email before you reply <<
>
> Given that illegal or malformed format strings to the printf family
> of functions mostly result in harmless misformatting but occationally
> in coredumps and maybe some times in security issues, what is the
> desired behaviour of libc's printf implementation ?
>
> A very good example is
>
> 	printf("%hf", 1.0);
>
> The 'h' modifier is not legal for %f format, and it is therefore a good
> bet that the programmer was confused and we know that the program
> contains at least one error.
>
>
> Our first line of defence against this kind of error is compile-time
> checking by GCC, but we cannot rely on the string being sane in libc,
> we still need to do error checking.
>
> The context for the above is that I'm working on adding extensibility
> to our printf, compatible with the GLIBC (see 12.13 in the glibc
> manual).  Obviously, gcc cannot compile-time check such extensions
> for us, and therefore the question gains a bit more relevance.
>
> In an ideal world, the printf family of functions would have been
> defined to return EINVAL in this case.  Almost nobody checks the
> return values of printf-like functions however and those few that
> do, all pressume that it is an I/O error so such an approach is
> unlikely to gain us much if anything.
>
> Another alternative is to spit out the format string unformatted,
> possibly with an attached notice, but this doesn't really seem to
> help anybody either, but at least indicates what the problem is.
>
>
> I'm leaning towards doing what phkmalloc has migrated to over time:
> Make a variable which can select between "normal/paranoia" and force
> it to paranoia for (uid==0 || gid==0 || setuid || setgid).
>
> If the variable is set, a bogus format string will result in abort(2).
>
> If it is not set, the format string will be output unformatted in
> the message "WARNING: Illegal printf() format string: \"...\".

I agree on principle but would like to ask if we need to revisit some of the 
error cases.  Especially with regard to 64bit porting there are some 
"artifacts" that might cause serious pain for ported applications if the 
above is adopted.

Specifically, right now the following will warn "long long int format, int64_t 
arg (arg 2)" on our 64bit architectures while it is required on - at least - 
i386

	int64_t i = 1;
	printf("%lld", i);

Many other platforms allow it for 64bit architectures as well.  As for all our 
64bit architectures sizeof(long) == sizeof(long long) (as far as I am aware), 
I am not convinced this should be a (fatal) error.  There might be other 
similar cases.

So the question is, how strict should this check be?  Are there cases where we 
are better off with a "just do it"-sollution?


As a community service, there is a right way to do this (according to C99):

	int64_t i = 1;
	printf("%" PRIi64 "\n", i);

but it's obvious this is not going to be adopted.  The other often used 
workaround is:

	int64_t i = 1;
	printf("%jd\n", (intmax_t)i);

or:

	printf("%lld\n", (long long)i);

which kind of reverts the idea behind useing C99-types.

Note that:

	printf("%jd\n, i);

seems to work as well, but I not sure this is correct.

-- 
/"\  Best regards,                      | mlaier at freebsd.org
\ /  Max Laier                          | ICQ #67774661
 X   http://pf4freebsd.love2party.net/  | mlaier at EFnet
/ \  ASCII Ribbon Campaign              | Against HTML Mail and News
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 187 bytes
Desc: not available
Url : http://lists.freebsd.org/pipermail/freebsd-arch/attachments/20051212/75c79ccb/attachment.bin


More information about the freebsd-arch mailing list