@@ -67,6 +67,7 @@ tests = tst_swprintf tst_wprintf tst_swscanf tst_wscanf tst_getwc tst_putwc \
tst-ftell-append tst-fputws tst-bz22415 tst-fgetc-after-eof \
tst-sprintf-ub tst-sprintf-chk-ub tst-bz24051 tst-bz24153 \
tst-wfile-sync tst-bz28828
+tests += tst-wdoalloc
tests-internal = tst-vtables tst-vtables-interposed
new file mode 100644
@@ -0,0 +1,32 @@
+/* Test setup of buffers on wide-oriented stream - BZ #20632 */
+
+#include <stdio.h>
+#include <wchar.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <support/check.h>
+
+static int
+do_test (void)
+{
+ /* This test uses stderr because it is an unbuffered stream where the
+ stdio buffers haven't been set up yet. */
+
+ /* Close stderr descriptor so that output to it will fail. */
+ close (2);
+
+ /* Output a long string. */
+ const int sz = 4096;
+ wchar_t *buff = calloc (sz + 1, sizeof *buff);
+ for (int i = 0; i < sz; i++)
+ buff[i] = L'x';
+ fputws (buff, stderr);
+
+ /* Output shorter strings. */
+ for (int i = 0; i < 1024; i++)
+ fputws (L"0123456789ABCDEF", stderr);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
@@ -418,16 +418,15 @@ _IO_wfile_overflow (FILE *f, wint_t wch)
/* Allocate a buffer if needed. */
if (f->_wide_data->_IO_write_base == 0)
{
- _IO_wdoallocbuf (f);
- _IO_free_wbackup_area (f);
- _IO_wsetg (f, f->_wide_data->_IO_buf_base,
- f->_wide_data->_IO_buf_base, f->_wide_data->_IO_buf_base);
-
if (f->_IO_write_base == NULL)
{
_IO_doallocbuf (f);
_IO_setg (f, f->_IO_buf_base, f->_IO_buf_base, f->_IO_buf_base);
}
+ _IO_wdoallocbuf (f);
+ _IO_free_wbackup_area (f);
+ _IO_wsetg (f, f->_wide_data->_IO_buf_base,
+ f->_wide_data->_IO_buf_base, f->_wide_data->_IO_buf_base);
}
else
{