diff --git a/glibc-rh1052846.patch b/glibc-rh1052846.patch new file mode 100644 index 0000000..c88675a --- /dev/null +++ b/glibc-rh1052846.patch @@ -0,0 +1,443 @@ +commit 403ce35141da511898cde550f48ebc68a2a3ac82 +Author: Siddhesh Poyarekar +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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* 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; diff --git a/glibc.spec b/glibc.spec index e9e28e8..4294b16 100644 --- a/glibc.spec +++ b/glibc.spec @@ -1,6 +1,6 @@ -%define glibcsrcdir glibc-2.18-753-gd5780fe +%define glibcsrcdir glibc-2.18-788-g497b1e6 %define glibcversion 2.18.90 -%define glibcrelease 20%{?dist} +%define glibcrelease 21%{?dist} # Pre-release tarballs are pulled in from git using a command that is # effectively: # @@ -211,6 +211,9 @@ Patch2027: %{name}-rh819430.patch # Fix nscd to use permission names not constants. Patch2028: %{name}-rh1025126.patch +# Upstream BZ 16398 +Patch2029: %{name}-rh1052846.patch + ############################################################################## # End of glibc patches. ############################################################################## @@ -535,6 +538,7 @@ package or when debugging this package. %patch0044 -p1 %patch0046 -p1 %patch2028 -p1 +%patch2029 -p1 ############################################################################## # %%prep - Additional prep required... @@ -1620,6 +1624,10 @@ rm -f *.filelist* %endif %changelog +* Tue Jan 14 2014 Siddhesh Poyarekar - 2.18.90-21 +- Sync with upstream master. +- Fix infinite loop in ftell when writing wide char data (#1052846). + * Tue Jan 7 2014 Siddhesh Poyarekar - 2.18.90-20 - Sync with upstream master. - Enable systemtap probes on Power and S/390. diff --git a/sources b/sources index 8fbe070..05b4e53 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -8453361d6cfeec94dd6c7ad5ef1e01e1 glibc-2.18-753-gd5780fe.tar.gz +68d30f09d625972d997ffc5c2763a097 glibc-2.18-788-g497b1e6.tar.gz