This is the mail archive of the
newlib@sourceware.org
mailing list for the newlib project.
[PATCH] stdio/vfprintf.c: Don't drop out on invalid chars in format string
- From: Corinna Vinschen <vinschen at redhat dot com>
- To: newlib at sourceware dot org
- Date: Sat, 9 Jan 2010 12:04:49 +0100
- Subject: [PATCH] stdio/vfprintf.c: Don't drop out on invalid chars in format string
- Reply-to: newlib at sourceware dot org
Hi,
assume the following test application:
#include <stdio.h>
#include <string.h>
#include <locale.h>
int
main ()
{
char buf[32];
int ret;
setlocale (LC_ALL, "en_US.UTF-8");
memset (buf, 0, sizeof buf);
ret = sprintf (buf, "\333%s", "ABCD");
printf ("(%d) %02x %02x %02x %02x %02x\n",
ret, buf[0], buf[1], buf[2], buf[3], buf[4]);
return 0;
}
It contains a character in the format string "\333", which is invalid
in the current charset (UTF-8). Running this application on Linux or
Solaris results in the following output:
(5) ffffffdb 41 42 43 44
Running this under newlib/Cygwin, the result is:
(0) 0 0 0 0 0
In newlib, the loop looking for '%' in the format string converts the
format string chars into wide chars, and then compares the character
with a '%'. The problem is that the vfprintf function simply exits as
soon as an invalid char is found in the format string and returns the
number of characters printed so far. This is not defined in POSIX.
Either printf is supposed to go ahead, or it is allowed to exit with
a return value of -1 and errno set to EILSEQ.
For compatiblity with Linux and Solaris, I'd like to opt for just going
ahaead and copy the invalid byte in the format string unchanged to the
output. The patch below will do that.
Ok to apply?
Thanks,
Corinna
* libc/stdio/vfprintf.c (_VFPRINTF_R): Just wave bytes invalid in
the current charset through.
Index: libc/stdio/vfprintf.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/vfprintf.c,v
retrieving revision 1.76
diff -u -p -r1.76 vfprintf.c
--- libc/stdio/vfprintf.c 18 Nov 2009 09:49:56 -0000 1.76
+++ libc/stdio/vfprintf.c 9 Jan 2010 11:03:39 -0000
@@ -724,8 +724,13 @@ _DEFUN(_VFPRINTF_R, (data, fp, fmt0, ap)
cp = fmt;
#ifdef _MB_CAPABLE
while ((n = __mbtowc (data, &wc, fmt, MB_CUR_MAX,
- __locale_charset (), &state)) > 0) {
- if (wc == '%')
+ __locale_charset (), &state)) != 0) {
+ if (n < 0) {
+ /* Wave invalid chars through. */
+ memset (&state, 0, sizeof state);
+ n = 1;
+ }
+ else if (wc == '%')
break;
fmt += n;
}
--
Corinna Vinschen
Cygwin Project Co-Leader
Red Hat