[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