[PATCH] stdio/vfprintf.c: Don't drop out on invalid chars in format string
Jeff Johnston
jjohnstn@redhat.com
Wed Jan 13 22:59:00 GMT 2010
On 09/01/10 06:04 AM, Corinna Vinschen wrote:
> 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?
>
Yes, go ahead.
-- Jeff J.
>
> 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;
> }
>
>
More information about the Newlib
mailing list