[glibc/f18] - Update fseek fix (#854337)

Jeffrey Law law at fedoraproject.org
Thu Sep 6 04:36:23 UTC 2012


commit e063906d5574797e71f67819f728b6a89414f0ca
Author: Jeff Law <law at redhat.com>
Date:   Wed Sep 5 22:35:57 2012 -0600

    - Update fseek fix (#854337)

 glibc-rh854337.patch |  209 ++++++++++++++++---------------------------------
 glibc.spec           |    5 +-
 2 files changed, 72 insertions(+), 142 deletions(-)
---
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: <libc-alpha-return-32469-listarch-libc-alpha=sources dot redhat dot com at sourceware dot org>
-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 <siddhesh at redhat dot com>
-To: libc-alpha at sourceware dot org
-Subject: [PATCH][BZ #14543] Fix fseek behaviour when called in wide mode
-Message-ID: <20120904220355.5ef5d279 at 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: <libc-alpha.sourceware.org>
-List-Subscribe: <mailto:libc-alpha-subscribe at sourceware dot org>
-List-Archive: <http://sourceware.org/ml/libc-alpha/>
-List-Post: <mailto:libc-alpha at sourceware dot org>
-List-Help: <mailto:libc-alpha-help at sourceware dot org>, <http://sourceware dot org/ml/#faqs>
-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 <errno.h>
 +#include <wchar.h>
 +#include <unistd.h>
++#include <string.h>
 +
 +/* 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;
-+
- 	  _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);
-+
-+	  /* 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));
-+
- 	  _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);
+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_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);
++  int clen = (*cv->__codecvt_do_encoding) (cv);
 +
-+  /* 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);
++  /* 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;
++    }
 +
++  enum __codecvt_result status;
++  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_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_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
+ 	  _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 <law at redhat.com> - 2.16-13
+  - Update fseek fix (#854337)
+
 * Tue Sep 4 2012 Jeff Law <law at redhat.com> - 2.16-12
   - Incorporate ppc64p7 arch changes (#854250)
   - Fix fseek in wide mode (#854337)


More information about the scm-commits mailing list