This is sources Bugzilla
Bugzilla Version 2.17.5
Bugzilla Bug 7075
  sprintf(buf, "%sfoo", buf) has different results with -O2 -D_FORTIFY_SOURCE=2 (__sprintf_chk bug?) Last modified: 2009-02-05 08:55
     Query page      Enter new bug
Bug#: 7075   Hardware:   Reporter: Kees Cook <kees@outflux.net>
Host: Target: Build:
Product:     Add CC:
Component:   Version:   CC:
Remove selected CCs
Status: RESOLVED   Priority:  
Resolution: INVALID   Severity:  
Assigned To: Ulrich Drepper <drepper@redhat.com>   Target Milestone:  
Flags: Requestee:
  backport ()
  examined ()
  testsuite ()
Summary:
Keywords:

Attachment Description Type Created Actions
foo.c test case text/plain 2008-12-07 17:42 Edit None
no-sprintf-pre-truncate.diff work-around pre-trunc behavior patch 2008-12-24 17:40 Edit | Diff
Create a New Attachment (proposed patch, testcase, etc.) View All

Bug 7075 depends on: Show dependency tree
Show dependency graph
Bug 7075 blocks:

Additional Comments:


Leave as RESOLVED INVALID
Reopen bug
Mark bug as VERIFIED

View Bug Activity   |   Format For Printing


Description:   Last confirmed: 0000-00-00 00:00 Opened: 2008-12-07 17:42
Anders Kaseorg noticed that the use of _FORTIFY_SOURCE breaks a specific use of
sprintf (see attached):

$ gcc -O0 -o foo foo.c && ./foo
not fail
$ gcc -O2 -o foo foo.c && ./foo
not fail
$ gcc -O2 -D_FORTIFY_SOURCE=2 -o foo foo.c && ./foo
fail

The original report was filed in Ubuntu, where -D_FORTIFY_SOURCE=2 is enabled by
default: https://bugs.launchpad.net/ubuntu/+source/glibc/+bug/305901

C99 states:
The sprintf function is equivalent to fprintf, except that the output is written
into an array (specified by the argument s) rather than to a stream. A null
character is written at the end of the characters written; it is not counted as
part of the returned value. If copying takes place between objects that overlap,
the behavior is undefined.

The man page does not mention this limitation, and prior to the use of
__sprintf_chk, this style of call worked as expected.  As such, a large volume
of source code uses this style of call:
http://web.mit.edu/andersk/Public/sprintf-results

It seems that it would make sense to fix __sprintf_chk, or very loudly mention
the C99-described overlap-is-undefined behavior in sprintf documentation.

------- Additional Comment #1 From Kees Cook 2008-12-07 17:42 -------
Created an attachment (id=3095)
test case

------- Additional Comment #2 From Andreas Schwab 2008-12-07 17:49 -------
sprintf(buf, "%sfoo", buf) is UNDEFINED.

------- Additional Comment #3 From Kees Cook 2008-12-07 18:33 -------
Thanks for the clarification.  However, I think it is still a bug that the
limitation is not mentioned in the manpage.

------- Additional Comment #4 From Andreas Schwab 2008-12-07 19:05 -------
Then contact whoever wrote it.

------- Additional Comment #5 From Jakub Jelinek 2008-12-07 22:56 -------
man 3p sprintf certainly documents it:
"If  copying  takes  place  between objects that overlap as a result of a call
to sprintf() or snprintf(), the results are undefined."

------- Additional Comment #6 From Petr Baudis 2008-12-07 23:38 -------
I have submitted a patch for linux-manpages:
http://thread.gmane.org/gmane.linux.man/639

------- Additional Comment #7 From Michael Kerrisk 2008-12-19 16:57 -------
(In reply to comment #6)
> I have submitted a patch for linux-manpages:
> http://thread.gmane.org/gmane.linux.man/639

I've applied the following patch for man-pages-3.16.

--- a/man3/printf.3
+++ b/man3/printf.3
@@ -133,6 +133,17 @@ string that specifies how subsequent arguments (or
arguments accessed via
 the variable-length argument facilities of
 .BR stdarg (3))
 are converted for output.
+
+C99 and POSIX.1-2001 specify that the results are undefined if a call to
+.BR sprintf (),
+.BR snprintf (),
+.BR vsprintf (),
+or
+.BR vsnprintf ()
+would cause to copying to take place between objects that overlap
+(e.g., if the target string array and one of the supplied input arguments
+refer to the same buffer).
+See NOTES.
 .SS "Return value"
 Upon successful return, these functions return the number of characters
 printed (not including the
@@ -851,6 +862,26 @@ and conversion characters \fBa\fP and \fBA\fP.
 glibc 2.2 adds the conversion character \fBF\fP with C99 semantics,
 and the flag character \fBI\fP.
 .SH NOTES
+Some programs imprudently rely on code such as the following
+
+    sprintf(buf, "%s some further text", buf);
+
+to append text to
+.IR buf .
+However, the standards explicitly note that the results are undefined
+if source and destination buffers overlap when calling
+.BR sprintf (),
+.BR snprintf (),
+.BR vsprintf (),
+and
+.BR vsnprintf ().
+.\" http://sourceware.org/bugzilla/show_bug.cgi?id=7075
+Depending on the version of
+.BR gcc (1)
+used, and the compiler options employed, calls such as the above will
+.B not
+produce the expected results.
+
 The glibc implementation of the functions
 .BR snprintf ()
 and

------- Additional Comment #8 From Kees Cook 2008-12-24 17:40 -------
Created an attachment (id=3625)
work-around pre-trunc behavior

This patch restores the prior sprintf behavior.  Looking through
_IO_str_init_static_internal seems to indicate that nothing actually requires
"s" to lead with a NULL.  Is there anything wrong with this work-around, which
could be used until the number of affected upstream sources is not quite so
large?

     Query page      Enter new bug
Actions: New | Query | bug # | Reports | Requests   New Account | Log In