Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 12 Dec 2005 13:14:23 +0100
From:      Poul-Henning Kamp <phk@phk.freebsd.dk>
To:        arch@freebsd.org
Subject:   printf behaviour with illegal or malformed format string
Message-ID:  <1023.1134389663@critter.freebsd.dk>

next in thread | raw e-mail | index | archive | help

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: \"...\".


If you cannot possibly live with that, please state why, and describe
what behaviour you would prefer instead.

Thankyou, (and may the best bikeshed win).

Poul-Henning

-- 
Poul-Henning Kamp       | UNIX since Zilog Zeus 3.20
phk@FreeBSD.ORG         | TCP/IP since RFC 956
FreeBSD committer       | BSD since 4.3-tahoe
Never attribute to malice what can adequately be explained by incompetence.



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?1023.1134389663>