diff options
author | Siddhesh Poyarekar <siddhesh@redhat.com> | 2012-11-16 19:13:11 +0530 |
---|---|---|
committer | Siddhesh Poyarekar <siddhesh@redhat.com> | 2012-11-16 19:13:11 +0530 |
commit | 2b766585f9b4ffabeef2f36200c275976b93f2c7 (patch) | |
tree | d6be89abc6bfa88e5e9fd997bb4cfd94b035adc2 | |
parent | b1848fdeec705bc7d2f64e3a365f1ff66eeb4f0d (diff) | |
download | glibc-2b766585f9b4ffabeef2f36200c275976b93f2c7.tar.gz glibc-2b766585f9b4ffabeef2f36200c275976b93f2c7.tar.xz glibc-2b766585f9b4ffabeef2f36200c275976b93f2c7.zip |
printf should return negative value on error
[BZ #11741] Fixed bug where printf and family may return a spurious success when printing padded formats.
-rw-r--r-- | ChangeLog | 16 | ||||
-rw-r--r-- | NEWS | 22 | ||||
-rw-r--r-- | libio/fileops.c | 18 | ||||
-rw-r--r-- | libio/iopadn.c | 2 | ||||
-rw-r--r-- | libio/iowpadn.c | 4 | ||||
-rw-r--r-- | libio/libioP.h | 5 | ||||
-rw-r--r-- | stdio-common/tst-put-error.c | 26 | ||||
-rw-r--r-- | stdio-common/vfprintf.c | 28 |
8 files changed, 92 insertions, 29 deletions
diff --git a/ChangeLog b/ChangeLog index 6d522d60db..fb21238ecf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,21 @@ 2012-11-16 Siddhesh Poyarekar <siddhesh@redhat.com> + [BZ #11741] + * libio/fileops.c (_IO_new_file_write): Correctly return error. + (_IO_new_file_xsputn): Also return EOF if none of the input + data was written when overflow failed. + * libio/iopadn.c (_IO_padn): Likewise. + * libio/iowpadn.c (_IO_wpadn): Likewise. + * stdio-common/tst-put-error.c: Add copyright notice. + (do_test): Add case for printing padded string. + * stdio-common/vfprintf [!COMPILE_WPRINTF] (PAD): Flag error if + _IO_padn returned error. + [COMPILE_WPRINTF] (PAD): Flag error if _IO_wpadn returned error. + * libio/libioP.h (_IO_xsputn_t): Note in comment that xsputn can + return EOF. + +2012-11-16 Siddhesh Poyarekar <siddhesh@redhat.com> + * libio/libioP.h: Add comment note that the references to C++ bits are now obsolete. diff --git a/NEWS b/NEWS index 9791e30dbf..4f57ddb276 100644 --- a/NEWS +++ b/NEWS @@ -10,17 +10,17 @@ Version 2.17 * The following bugs are resolved with this release: 1349, 3439, 3479, 3665, 5044, 5246, 5298, 5400, 6530, 6778, 6808, 9685, - 9914, 10014, 10038, 10631, 10873, 11438, 11607, 11638, 12140, 13412, - 13542, 13601, 13603, 13604, 13629, 13679, 13696, 13698, 13717, 13741, - 13939, 13950, 13952, 13966, 14042, 14047, 14090, 14150, 14151, 14152, - 14154, 14157, 14166, 14173, 14195, 14237, 14251, 14252, 14283, 14298, - 14303, 14307, 14328, 14331, 14336, 14337, 14347, 14349, 14376, 14417, - 14459, 14476, 14477, 14501, 14505, 14510, 14516, 14518, 14519, 14530, - 14532, 14538, 14543, 14544, 14545, 14557, 14562, 14568, 14576, 14579, - 14583, 14587, 14595, 14602, 14610, 14621, 14638, 14645, 14648, 14652, - 14660, 14661, 14669, 14683, 14694, 14716, 14743, 14767, 14783, 14784, - 14785, 14793, 14796, 14797, 14801, 14805, 14807, 14809, 14811, 14815, - 14821, 14824, 14828, 14831, 14838. + 9914, 10014, 10038, 10631, 10873, 11438, 11607, 11638, 11741, 12140, + 13412, 13542, 13601, 13603, 13604, 13629, 13679, 13696, 13698, 13717, + 13741, 13939, 13950, 13952, 13966, 14042, 14047, 14090, 14150, 14151, + 14152, 14154, 14157, 14166, 14173, 14195, 14237, 14251, 14252, 14283, + 14298, 14303, 14307, 14328, 14331, 14336, 14337, 14347, 14349, 14376, + 14417, 14459, 14476, 14477, 14501, 14505, 14510, 14516, 14518, 14519, + 14530, 14532, 14538, 14543, 14544, 14545, 14557, 14562, 14568, 14576, + 14579, 14583, 14587, 14595, 14602, 14610, 14621, 14638, 14645, 14648, + 14652, 14660, 14661, 14669, 14683, 14694, 14716, 14743, 14767, 14783, + 14784, 14785, 14793, 14796, 14797, 14801, 14805, 14807, 14809, 14811, + 14815, 14821, 14824, 14828, 14831, 14838. * Port to ARM AArch64 contributed by Linaro. diff --git a/libio/fileops.c b/libio/fileops.c index 6aabadc644..fb6ac17b64 100644 --- a/libio/fileops.c +++ b/libio/fileops.c @@ -1253,12 +1253,13 @@ _IO_new_file_write (f, data, n) _IO_ssize_t n; { _IO_ssize_t to_do = n; + _IO_ssize_t count = 0; while (to_do > 0) { - _IO_ssize_t count = (__builtin_expect (f->_flags2 - & _IO_FLAGS2_NOTCANCEL, 0) - ? write_not_cancel (f->_fileno, data, to_do) - : write (f->_fileno, data, to_do)); + count = (__builtin_expect (f->_flags2 + & _IO_FLAGS2_NOTCANCEL, 0) + ? write_not_cancel (f->_fileno, data, to_do) + : write (f->_fileno, data, to_do)); if (count < 0) { f->_flags |= _IO_ERR_SEEN; @@ -1270,7 +1271,7 @@ _IO_new_file_write (f, data, n) n -= to_do; if (f->_offset >= 0) f->_offset += n; - return n; + return count < 0 ? count : n; } _IO_size_t @@ -1330,9 +1331,10 @@ _IO_new_file_xsputn (f, data, n) _IO_size_t block_size, do_write; /* Next flush the (full) buffer. */ if (_IO_OVERFLOW (f, EOF) == EOF) - /* If nothing else has to be written we must not signal the - caller that everything has been written. */ - return to_do == 0 ? EOF : n - to_do; + /* If nothing else has to be written or nothing has been written, we + must not signal the caller that the call was even partially + successful. */ + return (to_do == 0 || to_do == n) ? EOF : n - to_do; /* Try to maintain alignment: write a whole number of blocks. dont_write is what gets left over. */ diff --git a/libio/iopadn.c b/libio/iopadn.c index 7e374508f0..b7a4c5a739 100644 --- a/libio/iopadn.c +++ b/libio/iopadn.c @@ -59,7 +59,7 @@ _IO_padn (fp, pad, count) w = _IO_sputn (fp, padptr, PADSIZE); written += w; if (w != PADSIZE) - return written; + return w == EOF ? w : written; } if (i > 0) diff --git a/libio/iowpadn.c b/libio/iowpadn.c index 05632d5bf0..56e4b8ccb2 100644 --- a/libio/iowpadn.c +++ b/libio/iowpadn.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1997, 1999 Free Software Foundation, Inc. +/* Copyright (C) 1993-2012 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -65,7 +65,7 @@ _IO_wpadn (fp, pad, count) w = _IO_sputn (fp, (char *) padptr, PADSIZE); written += w; if (w != PADSIZE) - return written; + return w == EOF ? w : written; } if (i > 0) diff --git a/libio/libioP.h b/libio/libioP.h index fe81115094..a402958b9c 100644 --- a/libio/libioP.h +++ b/libio/libioP.h @@ -1,5 +1,4 @@ -/* Copyright (C) 1993, 1997-2003,2004,2005,2006,2007,2012 - Free Software Foundation, Inc. +/* Copyright (C) 1993-2012 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -167,7 +166,7 @@ typedef int (*_IO_pbackfail_t) (_IO_FILE *, int); #define _IO_WPBACKFAIL(FP, CH) WJUMP1 (__pbackfail, FP, CH) /* The 'xsputn' hook writes upto N characters from buffer DATA. - Returns the number of character actually written. + Returns EOF or the number of character actually written. It matches the streambuf::xsputn virtual function. */ typedef _IO_size_t (*_IO_xsputn_t) (_IO_FILE *FP, const void *DATA, _IO_size_t N); diff --git a/stdio-common/tst-put-error.c b/stdio-common/tst-put-error.c index 115dbd509a..7b95491725 100644 --- a/stdio-common/tst-put-error.c +++ b/stdio-common/tst-put-error.c @@ -1,3 +1,22 @@ +/* Verify that print functions return error when there is an I/O error. + + Copyright (C) 2005-2012 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + #include <errno.h> #include <error.h> #include <stdio.h> @@ -26,6 +45,13 @@ do_test (void) printf ("fprintf = %d\n", n); if (n >= 0) error (EXIT_FAILURE, 0, "second fprintf succeeded"); + + /* Padded printing takes a different code path. */ + n = fprintf (fp, "%10000s", "foo"); + printf ("fprintf = %d\n", n); + if (n >= 0) + error (EXIT_FAILURE, 0, "padded fprintf succeeded"); + return 0; } diff --git a/stdio-common/vfprintf.c b/stdio-common/vfprintf.c index 17d3f42a97..0c1339febd 100644 --- a/stdio-common/vfprintf.c +++ b/stdio-common/vfprintf.c @@ -87,8 +87,18 @@ # define PUT(F, S, N) _IO_sputn ((F), (S), (N)) # define PAD(Padchar) \ - if (width > 0) \ - done_add (_IO_padn (s, (Padchar), width)) + do { \ + if (width > 0) \ + { \ + unsigned int d = _IO_padn (s, (Padchar), width); \ + if (__builtin_expect (d == EOF, 0)) \ + { \ + done = -1; \ + goto all_done; \ + } \ + done_add (d); \ + } \ + } while (0) # define PUTC(C, F) _IO_putc_unlocked (C, F) # define ORIENT if (_IO_vtable_offset (s) == 0 && _IO_fwide (s, -1) != -1)\ return -1 @@ -106,8 +116,18 @@ # define PUT(F, S, N) _IO_sputn ((F), (S), (N)) # define PAD(Padchar) \ - if (width > 0) \ - done_add (_IO_wpadn (s, (Padchar), width)) + do { \ + if (width > 0) \ + { \ + unsigned int d = _IO_wpadn (s, (Padchar), width); \ + if (__builtin_expect (d == EOF, 0)) \ + { \ + done = -1; \ + goto all_done; \ + } \ + done_add (d); \ + } \ + } while (0) # define PUTC(C, F) _IO_putwc_unlocked (C, F) # define ORIENT if (_IO_fwide (s, 1) != 1) return -1 |