forked from rpms/glibc
48 lines
2.0 KiB
Diff
48 lines
2.0 KiB
Diff
commit 403ce35141da511898cde550f48ebc68a2a3ac82
|
|
Author: Siddhesh Poyarekar <siddhesh@redhat.com>
|
|
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.
|
|
|
|
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;
|