Compare commits

...
Author SHA1 Message Date
Florian Weimer d9d04be3f0 WIP Support exotic character sets in __fxprintf [BZ #24562]
This does not quite work because vfprintf has a similar
incorrect assumption.
2019-05-16 12:08:38 +02:00
4 changed files with 124 additions and 25 deletions
+6
View File
@@ -1,3 +1,9 @@
2019-05-16 Florian Weimer <fweimer@redhat.com>
[BZ #24562]
* stdio-common/fxprintf.c (call_fwprintf): New function.
(locked_vfxprintf): Use it.
2019-05-15 Mark Wielaard <mark@klomp.org>
[BZ# 24476]
+7 -1
View File
@@ -86,7 +86,8 @@ tests := tst-dirname tst-tsearch tst-fdset tst-mntent tst-hsearch \
tst-mntent-blank-corrupt tst-mntent-blank-passno bug18240 \
tst-preadvwritev tst-preadvwritev64 tst-makedev tst-empty \
tst-preadvwritev2 tst-preadvwritev64v2 tst-warn-wide \
tst-ldbl-warn tst-ldbl-error tst-dbl-efgcvt tst-ldbl-efgcvt
tst-ldbl-warn tst-ldbl-error tst-dbl-efgcvt tst-ldbl-efgcvt \
tst-warn-wide-tscii
# Tests which need libdl.
ifeq (yes,$(build-shared))
@@ -138,6 +139,11 @@ CFLAGS-brk.op = $(no-stack-protector)
include ../Rules
LOCALES := en_US.TSCII
include ../gen-locales.mk
$(objpfx)tst-warn-wide-tscii.out: $(gen-locales)
$(objpfx)libg.a: $(dep-dummy-lib); $(make-dummy-lib)
$(objpfx)tst-tsearch: $(libm)
+63
View File
@@ -0,0 +1,63 @@
/* Test wide output conversion for warn with TSCII.
Copyright (C) 2019 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
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <err.h>
#include <locale.h>
#include <stdlib.h>
#include <support/check.h>
#include <support/temp_file.h>
#include <support/xstdio.h>
#include <support/xunistd.h>
#include <wchar.h>
static int
do_test (void)
{
if (setlocale (LC_ALL, "en_US.TSCII") == NULL)
FAIL_EXIT1 ("setlocale");
char *path;
xclose (create_temp_file ("tst-warn-wide-tscii-", &path));
FILE *fp = xfopen (path, "w,ccs=UTF-8");
TEST_COMPARE (fwide (fp, 0), 1);
FILE *old_stderr = stderr;
stderr = fp;
/* Special character that expands to four wide characters. */
warnx ("[[\x8C]]");
stderr = old_stderr;
/* Verify that the expected data was written. */
xfclose (fp);
fp = xfopen (path, "rb");
char line[1024];
TEST_VERIFY (fgets (line, sizeof (line), fp) != NULL);
TEST_COMPARE_STRING (line, "tst-warn-wide-tscii: [["
"\xe0\xae\x95\xe0\xaf\x8d\xe0\xae\xb7\xe0\xaf\x8d]]\n");
TEST_COMPARE (fgetc (fp), EOF);
TEST_VERIFY (feof (fp));
TEST_VERIFY (!ferror (fp));
free (path);
return 0;
}
#include <support/test-driver.c>
+48 -24
View File
@@ -23,6 +23,18 @@
#include <wchar.h>
#include <libioP.h>
/* See libio/fwprintf.c. */
static int
call_fwprintf (FILE *stream, unsigned int mode_flags,
const wchar_t *format, ...)
{
va_list arg;
va_start (arg, format);
int done = __vfwprintf_internal (stream, format, arg, mode_flags);
va_end (arg);
return done;
}
static int
locked_vfxprintf (FILE *fp, const char *fmt, va_list ap,
unsigned int mode_flags)
@@ -30,34 +42,46 @@ locked_vfxprintf (FILE *fp, const char *fmt, va_list ap,
if (_IO_fwide (fp, 0) <= 0)
return __vfprintf_internal (fp, fmt, ap, mode_flags);
/* We must convert the narrow format string to a wide one.
Each byte can produce at most one wide character. */
wchar_t *wfmt;
mbstate_t mbstate;
int res;
int used_malloc = 0;
size_t len = strlen (fmt) + 1;
int saved_errno = errno;
if (__glibc_unlikely (len > SIZE_MAX / sizeof (wchar_t)))
{
__set_errno (EOVERFLOW);
return -1;
}
if (__libc_use_alloca (len * sizeof (wchar_t)))
wfmt = alloca (len * sizeof (wchar_t));
else if ((wfmt = malloc (len * sizeof (wchar_t))) == NULL)
return -1;
/* Format the narrow string as a multibyte string. Try to use an
on-stack buffer first, to avoid the heap allocation. */
char buffer[512];
va_list ap1;
va_copy (ap1, ap);
int res = __vsnprintf_internal (buffer, sizeof (buffer),
fmt, ap1, mode_flags);
va_end (ap1);
if (res < 0)
return res;
char *ptr;
if (res < sizeof (buffer))
ptr = buffer;
else
used_malloc = 1;
{
/* Use a heap allocation for a large buffer. */
if (res == INT_MAX)
{
__set_errno (EOVERFLOW);
return -1;
}
size_t len = res + 1;
ptr = malloc (len);
if (ptr == NULL)
return -1;
__set_errno (saved_errno);
res = __vsnprintf_internal (ptr, len, fmt, ap, mode_flags);
if (res < 0)
return -1;
}
memset (&mbstate, 0, sizeof mbstate);
res = __mbsrtowcs (wfmt, &fmt, len, &mbstate);
/* Write the formatted multibyte string to the wide stream. */
if (res >= 0)
res = call_fwprintf (fp, mode_flags, L"%s", ptr);
if (res != -1)
res = __vfwprintf_internal (fp, wfmt, ap, mode_flags);
if (used_malloc)
free (wfmt);
if (ptr != buffer)
free (ptr);
__set_errno (saved_errno);
return res;
}