diff --git a/glibc-rh854337.patch b/glibc-rh854337.patch index 551b698..d6e6ed3 100644 --- a/glibc-rh854337.patch +++ b/glibc-rh854337.patch @@ -1,78 +1,7 @@ -From libc-alpha-return-32469-listarch-libc-alpha=sources dot redhat dot com at sourceware dot org Tue Sep 04 16:35:13 2012 -Return-Path: -Delivered-To: listarch-libc-alpha at sources dot redhat dot com -Received: (qmail 31908 invoked by alias); 4 Sep 2012 16:35:07 -0000 -Received: (qmail 31178 invoked by uid 22791); 4 Sep 2012 16:35:03 -0000 -X-SWARE-Spam-Status: No, hits=-6.8 required=5.0 - tests=AWL,BAYES_00,KHOP_RCVD_UNTRUST,RCVD_IN_DNSWL_HI,RCVD_IN_HOSTKARMA_W,RP_MATCHES_RCVD,SPF_HELO_PASS,TW_SW,TW_TV,TW_TW,TW_VB -X-Spam-Check-By: sourceware.org -Date: Tue, 4 Sep 2012 22:03:55 +0530 -From: Siddhesh Poyarekar -To: libc-alpha at sourceware dot org -Subject: [PATCH][BZ #14543] Fix fseek behaviour when called in wide mode -Message-ID: <20120904220355.5ef5d279@spoyarek> -Mime-Version: 1.0 -Content-Type: multipart/mixed; boundary="MP_/nT+8opq/57jsIpH2GwJ_t+V" -Mailing-List: contact libc-alpha-help at sourceware dot org; run by ezmlm -Precedence: bulk -List-Id: -List-Subscribe: -List-Archive: -List-Post: -List-Help: , -Sender: libc-alpha-owner at sourceware dot org -Delivered-To: mailing list libc-alpha at sourceware dot org - ---MP_/nT+8opq/57jsIpH2GwJ_t+V -Content-Type: text/plain; charset=US-ASCII -Content-Transfer-Encoding: 7bit -Content-Disposition: inline - -Hi, - -This is a patch to fix the problem Jeff Law had posted about in July: - -http://sourceware.org/ml/libc-alpha/2012-07/msg00179.html - -When fseek is called in wide mode, i.e. when the locale uses a -multibyte character set, it does not set the internal buffer state -correctly due to which, an ftell following it returns an invalid file -offset. This can be reproduced reliably with the reproducer program in -the bugzilla. - -The attached patch sets the internal buffer state correctly whenever -the external buffer state is modified by fseek. This involves either -computing the current _IO_read_ptr/end for the internal buffer based on -the new _IO_read_ptr in the external buffer or converting the content -read into the external buffer, up to the extent of the requested fseek -offset. - -The patch also includes a test case that verifies the fix. I have -verified that the patch does not cause a regression in the testsuite on -my F16 x86_64. - -Regards, -Siddhesh - -ChangeLog: - - * libio/Makefile (tests): New test case tst-fseek. - * libio/tst-fseek.c: New test case to verify that fseek/ftell - combination works in wide mode. - * libio/wfileops.c (_IO_wfile_seekoff): Adjust internal buffer - state when the external buffer state changes. - - ---MP_/nT+8opq/57jsIpH2GwJ_t+V -Content-Type: text/x-patch -Content-Transfer-Encoding: 7bit -Content-Disposition: attachment; filename=wide-fseek.patch - -diff --git a/libio/Makefile b/libio/Makefile -index c555dd0..e760ddc 100644 ---- a/libio/Makefile -+++ b/libio/Makefile -@@ -57,7 +57,7 @@ tests = tst_swprintf tst_wprintf tst_swscanf tst_wscanf tst_getwc tst_putwc \ +diff -Nrup a/libio/Makefile b/libio/Makefile +--- a/libio/Makefile 2012-06-30 13:12:34.000000000 -0600 ++++ b/libio/Makefile 2012-09-05 22:26:34.675086743 -0600 +@@ -57,7 +57,7 @@ tests = tst_swprintf tst_wprintf tst_sws tst-memstream1 tst-memstream2 \ tst-wmemstream1 tst-wmemstream2 \ bug-memstream1 bug-wmemstream1 \ @@ -81,12 +10,10 @@ index c555dd0..e760ddc 100644 test-srcs = test-freopen all: # Make this the default target; it will be defined in Rules. -diff --git a/libio/tst-fseek.c b/libio/tst-fseek.c -new file mode 100644 -index 0000000..e7984b0 ---- /dev/null -+++ b/libio/tst-fseek.c -@@ -0,0 +1,152 @@ +diff -Nrup a/libio/tst-fseek.c b/libio/tst-fseek.c +--- a/libio/tst-fseek.c 1969-12-31 17:00:00.000000000 -0700 ++++ b/libio/tst-fseek.c 2012-09-05 22:26:11.237181749 -0600 +@@ -0,0 +1,153 @@ +/* Verify that fseek/ftell combination works for wide chars. + + Copyright (C) 2012 Free Software Foundation, Inc. @@ -112,6 +39,7 @@ index 0000000..e7984b0 +#include +#include +#include ++#include + +/* Defined in test-skeleton.c. */ +static int create_temp_file (const char *base, char **filename); @@ -239,85 +167,84 @@ index 0000000..e7984b0 + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" -diff --git a/libio/wfileops.c b/libio/wfileops.c -index 3f628bf..96debc6 100644 ---- a/libio/wfileops.c -+++ b/libio/wfileops.c -@@ -684,13 +684,25 @@ _IO_wfile_seekoff (fp, offset, dir, mode) - - (fp->_IO_read_end - fp->_IO_buf_base)); - if (offset >= start_offset && offset < fp->_offset) - { -+ struct _IO_codecvt *cv = fp->_codecvt; -+ _IO_off64_t off; +diff -Nrup a/libio/wfileops.c b/libio/wfileops.c +--- a/libio/wfileops.c 2012-06-30 13:12:34.000000000 -0600 ++++ b/libio/wfileops.c 2012-09-05 22:26:11.540180521 -0600 +@@ -545,6 +545,55 @@ _IO_wfile_sync (fp) + } + libc_hidden_def (_IO_wfile_sync) + ++/* Adjust the internal buffer pointers to reflect the state in the external ++ buffer. The content between fp->_IO_read_base and fp->_IO_read_ptr is ++ assumed to be converted and available in the range ++ fp->_wide_data->_IO_read_base and fp->_wide_data->_IO_read_end. */ ++static inline int ++adjust_wide_data (_IO_FILE *fp, bool do_convert) ++{ ++ struct _IO_codecvt *cv = fp->_codecvt; + - _IO_setg (fp, fp->_IO_buf_base, - fp->_IO_buf_base + (offset - start_offset), - fp->_IO_read_end); - _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base); ++ int clen = (*cv->__codecvt_do_encoding) (cv); + -+ /* Get corresponding offset for the _wide_data. */ -+ fp->_wide_data->_IO_last_state = fp->_wide_data->_IO_state; -+ off = (*cv->__codecvt_do_length) (cv, &fp->_wide_data->_IO_state, -+ fp->_IO_read_base, fp->_IO_read_ptr, -+ (fp->_wide_data->_IO_buf_end -+ - fp->_wide_data->_IO_buf_base)); ++ /* Take the easy way out for constant length encodings if we don't need to ++ convert. */ ++ if (!do_convert && clen > 0) ++ { ++ fp->_wide_data->_IO_read_end += ((fp->_IO_read_ptr - fp->_IO_read_base) ++ / clen); ++ goto done; ++ } + - _IO_wsetg (fp, fp->_wide_data->_IO_buf_base, -- fp->_wide_data->_IO_buf_base, -- fp->_wide_data->_IO_buf_base); -+ fp->_wide_data->_IO_buf_base + off, -+ fp->_wide_data->_IO_buf_base + off); -+ - _IO_wsetp (fp, fp->_wide_data->_IO_buf_base, - fp->_wide_data->_IO_buf_base); - _IO_mask_flags (fp, 0, _IO_EOF_SEEN); -@@ -727,11 +739,43 @@ _IO_wfile_seekoff (fp, offset, dir, mode) - goto dumb; - } - } -- _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base + delta, -- fp->_IO_buf_base + count); -- _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base); -+ -+ /* Convert up to the location we're seeking to. */ + enum __codecvt_result status; -+ _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, -+ fp->_IO_buf_base + delta); - _IO_wsetg (fp, fp->_wide_data->_IO_buf_base, - fp->_wide_data->_IO_buf_base, fp->_wide_data->_IO_buf_base); -+ ++ const char *read_stop = (const char *) fp->_IO_read_base; + do + { -+ struct _IO_codecvt *cv = fp->_codecvt; -+ const char *read_stop = (const char *) fp->_IO_read_ptr; + + fp->_wide_data->_IO_last_state = fp->_wide_data->_IO_state; + status = (*cv->__codecvt_do_in) (cv, &fp->_wide_data->_IO_state, -+ fp->_IO_read_ptr, fp->_IO_read_end, ++ fp->_IO_read_base, fp->_IO_read_ptr, + &read_stop, -+ fp->_wide_data->_IO_read_ptr, ++ fp->_wide_data->_IO_read_base, + fp->_wide_data->_IO_buf_end, + &fp->_wide_data->_IO_read_end); + -+ /* Should we return EILSEQ instead? */ ++ /* Should we return EILSEQ? */ + if (__builtin_expect (status == __codecvt_error, 0)) -+ goto dumb; -+ -+ fp->_IO_read_ptr = (char *) read_stop; ++ { ++ fp->_flags |= _IO_ERR_SEEN; ++ return -1; ++ } + } + while (__builtin_expect (status == __codecvt_partial, 0)); + -+ /* Now seek to the location in the _wide data buffer. */ ++done: ++ /* Now seek to the end of the read buffer. */ + fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_end; + -+ /* Finally, set _IO_read_end to reflect how much we have actually read in -+ from the file. */ -+ fp->_IO_read_end = fp->_IO_buf_base + count; ++ return 0; ++} + -+ _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base); + _IO_off64_t + _IO_wfile_seekoff (fp, offset, dir, mode) + _IO_FILE *fp; +@@ -693,6 +742,10 @@ _IO_wfile_seekoff (fp, offset, dir, mode + fp->_wide_data->_IO_buf_base); + _IO_wsetp (fp, fp->_wide_data->_IO_buf_base, + fp->_wide_data->_IO_buf_base); ++ ++ if (adjust_wide_data (fp, false)) ++ goto dumb; ++ + _IO_mask_flags (fp, 0, _IO_EOF_SEEN); + goto resync; + } +@@ -733,6 +786,10 @@ _IO_wfile_seekoff (fp, offset, dir, mode + _IO_wsetg (fp, fp->_wide_data->_IO_buf_base, + fp->_wide_data->_IO_buf_base, fp->_wide_data->_IO_buf_base); _IO_wsetp (fp, fp->_wide_data->_IO_buf_base, fp->_wide_data->_IO_buf_base); ++ ++ if (adjust_wide_data (fp, true)) ++ goto dumb; ++ fp->_offset = result + count; _IO_mask_flags (fp, 0, _IO_EOF_SEEN); - ---MP_/nT+8opq/57jsIpH2GwJ_t+V-- - + return offset; diff --git a/glibc.spec b/glibc.spec index 51d7902..4db5d58 100644 --- a/glibc.spec +++ b/glibc.spec @@ -28,7 +28,7 @@ Summary: The GNU libc libraries Name: glibc Version: %{glibcversion} -Release: 12%{?dist} +Release: 13%{?dist} # GPLv2+ is used in a bunch of programs, LGPLv2+ is used for libraries. # Things that are linked directly into dynamically linked programs # and shared libraries (e.g. crt files, lib*_nonshared.a) have an additional @@ -1317,6 +1317,9 @@ rm -f *.filelist* %endif %changelog +* Tue Sep 4 2012 Jeff Law - 2.16-13 + - Update fseek fix (#854337) + * Tue Sep 4 2012 Jeff Law - 2.16-12 - Incorporate ppc64p7 arch changes (#854250) - Fix fseek in wide mode (#854337)