glibc/glibc-rh1052846.patch
Siddhesh Poyarekar 8ecbeeba6e Sync with upstream master and fix #1052846
- Sync with upstream master.
- Fix infinite loop in ftell when writing wide char data (#1052846).
2014-01-14 14:16:38 +05:30

444 lines
15 KiB
Diff

commit 403ce35141da511898cde550f48ebc68a2a3ac82
Author: Siddhesh Poyarekar <siddhesh@redhat.com>
Date: Mon Jan 6 14:37:21 2014 +0530
Fix infinite loop in ftell when writing wide char data (BZ #16398)
ftell tries to avoid flushing the buffer when it is in write mode by
converting the wide char data and placing it into the binary buffer.
If the output buffer space is full and there is data to write, the
code reverts to flushing the buffer. This breaks when there is space
in the buffer but it is not enough to convert the next character in
the wide data buffer, due to which __codecvt_do_out returns a
__codecvt_partial status. In this case, ftell keeps running in an
infinite loop.
The fix here is to detect the __codecvt_partial status in addition to
checking if the buffer is full. I have also added a test case
(written by Arjun Shankar) that demonstrates the infinite loop.
diff --git a/libio/Makefile b/libio/Makefile
index 05432f4..38bdeb3 100644
--- a/libio/Makefile
+++ b/libio/Makefile
@@ -60,7 +60,7 @@ tests = tst_swprintf tst_wprintf tst_swscanf tst_wscanf tst_getwc tst_putwc \
tst-wmemstream1 tst-wmemstream2 \
bug-memstream1 bug-wmemstream1 \
tst-setvbuf1 tst-popen1 tst-fgetwc bug-wsetpos tst-fseek \
- tst-fwrite-error
+ tst-fwrite-error tst-fseek-partial-wide
ifeq (yes,$(build-shared))
# Add test-fopenloc only if shared library is enabled since it depends on
# shared localedata objects.
diff --git a/libio/tst-fseek-partial-wide.c b/libio/tst-fseek-partial-wide.c
new file mode 100644
index 0000000..9a34443
--- /dev/null
+++ b/libio/tst-fseek-partial-wide.c
@@ -0,0 +1,376 @@
+/* Verify that ftell does not go into an infinite loop when a conversion fails
+ due to insufficient space in the buffer.
+ Copyright (C) 2014 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 <wchar.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <locale.h>
+#include <errno.h>
+#include <unistd.h>
+
+/* Defined in test-skeleton.c. */
+static int create_temp_file (const char *base, char **filename);
+
+const wchar_t *numbers[] = {
+ L"ゼロ\n",
+ L"いち\n",
+ L"に\n",
+ L"さん\n",
+ L"よん\n",
+ L"ご\n",
+ L"ろく\n",
+ L"なな\n",
+ L"はち\n",
+ L"きゅう\n",
+ L"じゅう\n",
+ L"じゅういち\n",
+ L"じゅうに\n",
+ L"じゅうさん\n",
+ L"じゅうよん\n",
+ L"じゅうご\n",
+ L"じゅうろく\n",
+ L"じゅうなな\n",
+ L"じゅうはち\n",
+ L"じゅうきゅう\n",
+ L"にじゅう\n",
+ L"にじゅういち\n",
+ L"にじゅうに\n",
+ L"にじゅうさん\n",
+ L"にじゅうよん\n",
+ L"にじゅうご\n",
+ L"にじゅうろく\n",
+ L"にじゅうなな\n",
+ L"にじゅうはち\n",
+ L"にじゅうきゅう\n",
+ L"さんじゅう\n",
+ L"さんじゅういち\n",
+ L"さんじゅうに\n",
+ L"さんじゅうさん\n",
+ L"さんじゅうよん\n",
+ L"さんじゅうご\n",
+ L"さんじゅうろく\n",
+ L"さんじゅうなな\n",
+ L"さんじゅうはち\n",
+ L"さんじゅうきゅう\n",
+ L"よんじゅう\n",
+ L"よんじゅういち\n",
+ L"よんじゅうに\n",
+ L"よんじゅうさん\n",
+ L"よんじゅうよん\n",
+ L"よんじゅうご\n",
+ L"よんじゅうろく\n",
+ L"よんじゅうなな\n",
+ L"よんじゅうはち\n",
+ L"よんじゅうきゅう\n",
+ L"ごじゅう\n",
+ L"ごじゅういち\n",
+ L"ごじゅうに\n",
+ L"ごじゅうさん\n",
+ L"ごじゅうよん\n",
+ L"ごじゅうご\n",
+ L"ごじゅうろく\n",
+ L"ごじゅうなな\n",
+ L"ごじゅうはち\n",
+ L"ごじゅうきゅう\n",
+ L"ろくじゅう\n",
+ L"ろくじゅういち\n",
+ L"ろくじゅうに\n",
+ L"ろくじゅうさん\n",
+ L"ろくじゅうよん\n",
+ L"ろくじゅうご\n",
+ L"ろくじゅうろく\n",
+ L"ろくじゅうなな\n",
+ L"ろくじゅうはち\n",
+ L"ろくじゅうきゅう\n",
+ L"ななじゅう\n",
+ L"ななじゅういち\n",
+ L"ななじゅうに\n",
+ L"ななじゅうさん\n",
+ L"ななじゅうよん\n",
+ L"ななじゅうご\n",
+ L"ななじゅうろく\n",
+ L"ななじゅうなな\n",
+ L"ななじゅうはち\n",
+ L"ななじゅうきゅう\n",
+ L"はちじゅう\n",
+ L"はちじゅういち\n",
+ L"はちじゅうに\n",
+ L"はちじゅうさん\n",
+ L"はちじゅうよん\n",
+ L"はちじゅうご\n",
+ L"はちじゅうろく\n",
+ L"はちじゅうなな\n",
+ L"はちじゅうはち\n",
+ L"はちじゅうきゅう\n",
+ L"きゅうじゅう\n",
+ L"きゅうじゅういち\n",
+ L"きゅうじゅうに\n",
+ L"きゅうじゅうさん\n",
+ L"きゅうじゅうよん\n",
+ L"きゅうじゅうご\n",
+ L"きゅうじゅうろく\n",
+ L"きゅうじゅうなな\n",
+ L"きゅうじゅうはち\n",
+ L"きゅうじゅうきゅう\n",
+ L"ひゃく\n",
+ L"ひゃくいち\n",
+ L"ひゃくに\n",
+ L"ひゃくさん\n",
+ L"ひゃくよん\n",
+ L"ひゃくご\n",
+ L"ひゃくろく\n",
+ L"ひゃくなな\n",
+ L"ひゃくはち\n",
+ L"ひゃくきゅう\n",
+ L"ひゃくじゅう\n",
+ L"ひゃくじゅういち\n",
+ L"ひゃくじゅうに\n",
+ L"ひゃくじゅうさん\n",
+ L"ひゃくじゅうよん\n",
+ L"ひゃくじゅうご\n",
+ L"ひゃくじゅうろく\n",
+ L"ひゃくじゅうなな\n",
+ L"ひゃくじゅうはち\n",
+ L"ひゃくじゅうきゅう\n",
+ L"ひゃくにじゅう\n",
+ L"ひゃくにじゅういち\n",
+ L"ひゃくにじゅうに\n",
+ L"ひゃくにじゅうさん\n",
+ L"ひゃくにじゅうよん\n",
+ L"ひゃくにじゅうご\n",
+ L"ひゃくにじゅうろく\n",
+ L"ひゃくにじゅうなな\n",
+ L"ひゃくにじゅうはち\n",
+ L"ひゃくにじゅうきゅう\n",
+ L"ひゃくさんじゅう\n",
+ L"ひゃくさんじゅういち\n",
+ L"ひゃくさんじゅうに\n",
+ L"ひゃくさんじゅうさん\n",
+ L"ひゃくさんじゅうよん\n",
+ L"ひゃくさんじゅうご\n",
+ L"ひゃくさんじゅうろく\n",
+ L"ひゃくさんじゅうなな\n",
+ L"ひゃくさんじゅうはち\n",
+ L"ひゃくさんじゅうきゅう\n",
+ L"ひゃくよんじゅう\n",
+ L"ひゃくよんじゅういち\n",
+ L"ひゃくよんじゅうに\n",
+ L"ひゃくよんじゅうさん\n",
+ L"ひゃくよんじゅうよん\n",
+ L"ひゃくよんじゅうご\n",
+ L"ひゃくよんじゅうろく\n",
+ L"ひゃくよんじゅうなな\n",
+ L"ひゃくよんじゅうはち\n",
+ L"ひゃくよんじゅうきゅう\n",
+ L"ひゃくごじゅう\n",
+ L"ひゃくごじゅういち\n",
+ L"ひゃくごじゅうに\n",
+ L"ひゃくごじゅうさん\n",
+ L"ひゃくごじゅうよん\n",
+ L"ひゃくごじゅうご\n",
+ L"ひゃくごじゅうろく\n",
+ L"ひゃくごじゅうなな\n",
+ L"ひゃくごじゅうはち\n",
+ L"ひゃくごじゅうきゅう\n",
+ L"ひゃくろくじゅう\n",
+ L"ひゃくろくじゅういち\n",
+ L"ひゃくろくじゅうに\n",
+ L"ひゃくろくじゅうさん\n",
+ L"ひゃくろくじゅうよん\n",
+ L"ひゃくろくじゅうご\n",
+ L"ひゃくろくじゅうろく\n",
+ L"ひゃくろくじゅうなな\n",
+ L"ひゃくろくじゅうはち\n",
+ L"ひゃくろくじゅうきゅう\n",
+ L"ひゃくななじゅう\n",
+ L"ひゃくななじゅういち\n",
+ L"ひゃくななじゅうに\n",
+ L"ひゃくななじゅうさん\n",
+ L"ひゃくななじゅうよん\n",
+ L"ひゃくななじゅうご\n",
+ L"ひゃくななじゅうろく\n",
+ L"ひゃくななじゅうなな\n",
+ L"ひゃくななじゅうはち\n",
+ L"ひゃくななじゅうきゅう\n",
+ L"ひゃくはちじゅう\n",
+ L"ひゃくはちじゅういち\n",
+ L"ひゃくはちじゅうに\n",
+ L"ひゃくはちじゅうさん\n",
+ L"ひゃくはちじゅうよん\n",
+ L"ひゃくはちじゅうご\n",
+ L"ひゃくはちじゅうろく\n",
+ L"ひゃくはちじゅうなな\n",
+ L"ひゃくはちじゅうはち\n",
+ L"ひゃくはちじゅうきゅう\n",
+ L"ひゃくきゅうじゅう\n",
+ L"ひゃくきゅうじゅういち\n",
+ L"ひゃくきゅうじゅうに\n",
+ L"ひゃくきゅうじゅうさん\n",
+ L"ひゃくきゅうじゅうよん\n",
+ L"ひゃくきゅうじゅうご\n",
+ L"ひゃくきゅうじゅうろく\n",
+ L"ひゃくきゅうじゅうなな\n",
+ L"ひゃくきゅうじゅうはち\n",
+ L"ひゃくきゅうじゅうきゅう\n",
+ L"にひゃく\n",
+ L"にひゃくいち\n",
+ L"にひゃくに\n",
+ L"にひゃくさん\n",
+ L"にひゃくよん\n",
+ L"にひゃくご\n",
+ L"にひゃくろく\n",
+ L"にひゃくなな\n",
+ L"にひゃくはち\n",
+ L"にひゃくきゅう\n",
+ L"にひゃくじゅう\n",
+ L"にひゃくじゅういち\n",
+ L"にひゃくじゅうに\n",
+ L"にひゃくじゅうさん\n",
+ L"にひゃくじゅうよん\n",
+ L"にひゃくじゅうご\n",
+ L"にひゃくじゅうろく\n",
+ L"にひゃくじゅうなな\n",
+ L"にひゃくじゅうはち\n",
+ L"にひゃくじゅうきゅう\n",
+ L"にひゃくにじゅう\n",
+ L"にひゃくにじゅういち\n",
+ L"にひゃくにじゅうに\n",
+ L"にひゃくにじゅうさん\n",
+ L"にひゃくにじゅうよん\n",
+ L"にひゃくにじゅうご\n",
+ L"にひゃくにじゅうろく\n",
+ L"にひゃくにじゅうなな\n",
+ L"にひゃくにじゅうはち\n",
+ L"にひゃくにじゅうきゅう\n",
+ L"にひゃくさんじゅう\n",
+ L"にひゃくさんじゅういち\n",
+ L"にひゃくさんじゅうに\n",
+ L"にひゃくさんじゅうさん\n",
+ L"にひゃくさんじゅうよん\n",
+ L"にひゃくさんじゅうご\n",
+ L"にひゃくさんじゅうろく\n",
+ L"にひゃくさんじゅうなな\n",
+ L"にひゃくさんじゅうはち\n",
+ L"にひゃくさんじゅうきゅう\n",
+ L"にひゃくよんじゅう\n",
+ L"にひゃくよんじゅういち\n",
+ L"にひゃくよんじゅうに\n",
+ L"にひゃくよんじゅうさん\n",
+ L"にひゃくよんじゅうよん\n",
+ L"にひゃくよんじゅうご\n",
+ L"にひゃくよんじゅうろく\n",
+ L"にひゃくよんじゅうなな\n",
+ L"にひゃくよんじゅうはち\n",
+ L"にひゃくよんじゅうきゅう\n",
+ L"にひゃくごじゅう\n",
+ L"にひゃくごじゅういち\n",
+ L"にひゃくごじゅうに\n",
+ L"にひゃくごじゅうさん\n",
+ L"にひゃくごじゅうよん\n",
+ L"にひゃくごじゅうご\n",
+ L"にひゃくごじゅうろく\n",
+ L"にひゃくごじゅうなな\n",
+ L"にひゃくごじゅうはち\n",
+ L"にひゃくごじゅうきゅう\n",
+ L"にひゃくろくじゅう\n",
+ L"にひゃくろくじゅういち\n",
+ L"にひゃくろくじゅうに\n",
+ L"にひゃくろくじゅうさん\n",
+ L"にひゃくろくじゅうよん\n",
+ L"にひゃくろくじゅうご\n",
+ L"にひゃくろくじゅうろく\n",
+ L"にひゃくろくじゅうなな\n",
+ L"にひゃくろくじゅうはち\n",
+ L"にひゃくろくじゅうきゅう\n",
+ L"にひゃくななじゅう\n",
+ L"にひゃくななじゅういち\n",
+ L"にひゃくななじゅうに\n",
+ L"にひゃくななじゅうさん\n",
+ L"にひゃくななじゅうよん\n",
+ L"にひゃくななじゅうご\n",
+ L"にひゃくななじゅうろく\n",
+ L"にひゃくななじゅうなな\n",
+ L"にひゃくななじゅうはち\n",
+ L"にひゃくななじゅうきゅう\n",
+ L"にひゃくはちじゅう\n",
+ L"にひゃくはちじゅういち\n",
+ L"にひゃくはちじゅうに\n",
+ L"にひゃくはちじゅうさん\n",
+ L"にひゃくはちじゅうよん\n",
+ L"にひゃくはちじゅうご\n",
+ L"にひゃくはちじゅうろく\n",
+ L"にひゃくはちじゅうなな\n",
+ L"にひゃくはちじゅうはち\n",
+ L"にひゃくはちじゅうきゅう\n",
+ L"にひゃくきゅうじゅう\n",
+ L"にひゃくきゅうじゅういち\n",
+ L"にひゃくきゅうじゅうに\n",
+ L"にひゃくきゅうじゅうさん\n",
+ L"にひゃくきゅうじゅうよん\n",
+ L"にひゃくきゅうじゅうご\n",
+ L"にひゃくきゅうじゅうろく\n",
+ L"にひゃくきゅうじゅうなな\n",
+ L"にひゃくきゅうじゅうはち\n",
+ L"にひゃくきゅうじゅうきゅう\n",
+ L"さんびゃく\n",
+};
+
+
+int
+do_test (void)
+{
+ int i;
+
+ if (setlocale (LC_ALL, "en_US.UTF-8") == NULL)
+ {
+ printf ("Cannot set en_US.UTF-8 locale.\n");
+ exit (1);
+ }
+
+ char *filename;
+ int fd = create_temp_file ("tst-fseek-wide-partial.out", &filename);
+
+ if (fd == -1)
+ return 1;
+
+ FILE *fp = fdopen (fd, "w+");
+ if (fp == NULL)
+ {
+ printf ("fopen: %s\n", strerror (errno));
+ close (fd);
+ return 1;
+ }
+
+ for (i = 0; i < sizeof (numbers) / sizeof (char *); i++)
+ {
+ printf ("offset: %ld\n", ftell (fp));
+ if (fputws (numbers[i], fp) == -1)
+ {
+ perror ("fputws");
+ return 1;
+ }
+ }
+ fclose (fp);
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/libio/wfileops.c b/libio/wfileops.c
index 87d3cdc..877fc1f 100644
--- a/libio/wfileops.c
+++ b/libio/wfileops.c
@@ -715,7 +715,7 @@ _IO_wfile_seekoff (fp, offset, dir, mode)
- fp->_wide_data->_IO_write_base) / clen;
else
{
- enum __codecvt_result status;
+ enum __codecvt_result status = __codecvt_ok;
delta = (fp->_wide_data->_IO_write_ptr
- fp->_wide_data->_IO_write_base);
const wchar_t *write_base = fp->_wide_data->_IO_write_base;
@@ -728,9 +728,12 @@ _IO_wfile_seekoff (fp, offset, dir, mode)
flush buffers for every ftell. */
do
{
- /* Ugh, no point trying to avoid the flush. Just do it
- and go back to how it was with the read mode. */
- if (delta > 0 && new_write_ptr == fp->_IO_buf_end)
+ /* There is not enough space in the buffer to do the entire
+ conversion, so there is no point trying to avoid the
+ buffer flush. Just do it and go back to how it was with
+ the read mode. */
+ if (status == __codecvt_partial
+ || (delta > 0 && new_write_ptr == fp->_IO_buf_end))
{
if (_IO_switch_to_wget_mode (fp))
return WEOF;