- Update fseek fix (#854337)
This commit is contained in:
parent
9564fbf78d
commit
e063906d55
@ -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@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;
|
||||
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;
|
||||
|
@ -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@redhat.com> - 2.16-13
|
||||
- Update fseek fix (#854337)
|
||||
|
||||
* Tue Sep 4 2012 Jeff Law <law@redhat.com> - 2.16-12
|
||||
- Incorporate ppc64p7 arch changes (#854250)
|
||||
- Fix fseek in wide mode (#854337)
|
||||
|
Loading…
x
Reference in New Issue
Block a user