Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
2009-02-04 Ulrich Drepper <drepper@redhat.com>
	* libio/wfileops.c (_IO_wfile_underflow): Fix handling of
	incomplete characters at end of input buffer.
	* libio/Makefile (tests): Add tst-fgetwc.
	* libio/tst-fgetwc.c: New file.
	* libio/tst-fgetwc.input: New file.
  • Loading branch information
Ulrich Drepper committed Feb 4, 2009
1 parent 3d44c0b commit 82f2e9c
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 15 deletions.
8 changes: 6 additions & 2 deletions ChangeLog
@@ -1,6 +1,10 @@
2009-02-04 Andreas Jaeger <aj@suse.de>
2009-02-04 Ulrich Drepper <drepper@redhat.com>

* FAQ.in: Remove reference to my mips page.
* libio/wfileops.c (_IO_wfile_underflow): Fix handling of
incomplete characters at end of input buffer.
* libio/Makefile (tests): Add tst-fgetwc.
* libio/tst-fgetwc.c: New file.
* libio/tst-fgetwc.input: New file.

2009-02-02 Andrew Stubbs <ams@codesourcery.com>

Expand Down
4 changes: 2 additions & 2 deletions libio/Makefile
@@ -1,4 +1,4 @@
# Copyright (C) 1995-2004,2006,2007,2008 Free Software Foundation, Inc.
# Copyright (C) 1995-2004,2006,2007,2008,2009 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
Expand Down Expand Up @@ -58,7 +58,7 @@ tests = tst_swprintf tst_wprintf tst_swscanf tst_wscanf tst_getwc tst_putwc \
tst-memstream1 tst-memstream2 \
tst-wmemstream1 tst-wmemstream2 \
bug-memstream1 bug-wmemstream1 \
tst-setvbuf1 tst-popen1
tst-setvbuf1 tst-popen1 tst-fgetwc
test-srcs = test-freopen

all: # Make this the default target; it will be defined in Rules.
Expand Down
2 changes: 2 additions & 0 deletions libio/tst-fgetwc.input
@@ -0,0 +1,2 @@
йцукен
qwerty
48 changes: 37 additions & 11 deletions libio/wfileops.c
@@ -1,4 +1,4 @@
/* Copyright (C) 1993,1995,1997-2003,2004, 2006 Free Software Foundation, Inc.
/* Copyright (C) 1993,1995,1997-2004,2006,2009 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Written by Ulrich Drepper <drepper@cygnus.com>.
Based on the single byte version by Per Bothner <bothner@cygnus.com>.
Expand Down Expand Up @@ -123,8 +123,6 @@ _IO_wfile_underflow (fp)
struct _IO_codecvt *cd;
enum __codecvt_result status;
_IO_ssize_t count;
int tries;
const char *read_ptr_copy;

if (__builtin_expect (fp->_flags & _IO_NO_READS, 0))
{
Expand Down Expand Up @@ -236,21 +234,23 @@ _IO_wfile_underflow (fp)
fp->_wide_data->_IO_write_base = fp->_wide_data->_IO_write_ptr =
fp->_wide_data->_IO_write_end = fp->_wide_data->_IO_buf_base;

tries = 0;
const char *read_ptr_copy;
char accbuf[MB_LEN_MAX];
size_t naccbuf = 0;
again:
count = _IO_SYSREAD (fp, fp->_IO_read_end,
fp->_IO_buf_end - fp->_IO_read_end);
if (count <= 0)
{
if (count == 0 && tries == 0)
if (count == 0 && naccbuf == 0)
fp->_flags |= _IO_EOF_SEEN;
else
fp->_flags |= _IO_ERR_SEEN, count = 0;
}
fp->_IO_read_end += count;
if (count == 0)
{
if (tries != 0)
if (naccbuf != 0)
/* There are some bytes in the external buffer but they don't
convert to anything. */
__set_errno (EILSEQ);
Expand All @@ -262,26 +262,52 @@ _IO_wfile_underflow (fp)
/* Now convert the read input. */
fp->_wide_data->_IO_last_state = fp->_wide_data->_IO_state;
fp->_IO_read_base = fp->_IO_read_ptr;
const char *from = fp->_IO_read_ptr;
const char *to = fp->_IO_read_end;
size_t to_copy = count;
if (__builtin_expect (naccbuf != 0, 0))
{
to_copy = MIN (sizeof (accbuf) - naccbuf, count);
to = __mempcpy (&accbuf[naccbuf], from, to_copy);
naccbuf += to_copy;
from = accbuf;
}
status = (*cd->__codecvt_do_in) (cd, &fp->_wide_data->_IO_state,
fp->_IO_read_ptr, fp->_IO_read_end,
&read_ptr_copy,
from, to, &read_ptr_copy,
fp->_wide_data->_IO_read_end,
fp->_wide_data->_IO_buf_end,
&fp->_wide_data->_IO_read_end);

fp->_IO_read_ptr = (char *) read_ptr_copy;
if (__builtin_expect (naccbuf != 0, 0))
fp->_IO_read_ptr += MAX (0, read_ptr_copy - &accbuf[naccbuf - to_copy]);
else
fp->_IO_read_ptr = (char *) read_ptr_copy;
if (fp->_wide_data->_IO_read_end == fp->_wide_data->_IO_buf_base)
{
if (status == __codecvt_error || fp->_IO_read_end == fp->_IO_buf_end)
if (status == __codecvt_error)
{
out_eilseq:
__set_errno (EILSEQ);
fp->_flags |= _IO_ERR_SEEN;
return WEOF;
}

/* The read bytes make no complete character. Try reading again. */
assert (status == __codecvt_partial);
++tries;

if (naccbuf == 0)
{
naccbuf = fp->_IO_read_end - fp->_IO_read_ptr;
if (naccbuf >= sizeof (accbuf))
goto out_eilseq;

memcpy (accbuf, fp->_IO_read_ptr, naccbuf);
}
else if (naccbuf == sizeof (accbuf))
goto out_eilseq;

fp->_IO_read_ptr = fp->_IO_read_end = fp->_IO_read_base;

goto again;
}

Expand Down

0 comments on commit 82f2e9c

Please sign in to comment.