[PATCH] _wctomb_r mishandles invalid wchars in single byte mode

Jeff Johnston jjohnstn@redhat.com
Tue Mar 3 09:31:00 GMT 2009


Thanks Corinna.  Patch checked in.

-- Jeff J.

Corinna Vinschen wrote:
> Hi,
>
> right now the _wctomb_r function simply assumes that the incoming wchar
> is a single byte value if the current multibyte charset is a singlebyte
> charset.  This is wrong.  Per POSIX, wctomb "shall return -1 if the
> value of wchar does not correspond to a valid character".  Per
> POSIX.1-2008, wctomb should also set errno to EILSEQ.  The below patch
> fixes that.
>
>
> Corinna
>
>
> 	* libc/stdlib/wctomb_r.c (_wctomb_r): Return EILSEQ in case of an
> 	invalid wchar.  Return -1 if wchar doesn't fit into singlebyte
> 	value in case of using a singlebyte charset.
>
>
> Index: libc/stdlib/wctomb_r.c
> ===================================================================
> RCS file: /cvs/src/src/newlib/libc/stdlib/wctomb_r.c,v
> retrieving revision 1.8
> diff -u -p -r1.8 wctomb_r.c
> --- libc/stdlib/wctomb_r.c	25 Feb 2009 09:10:09 -0000	1.8
> +++ libc/stdlib/wctomb_r.c	27 Feb 2009 10:06:15 -0000
> @@ -1,3 +1,4 @@
> +#include <errno.h>
>  #include <stdlib.h>
>  #include <string.h>
>  #include <wchar.h>
> @@ -31,6 +32,7 @@ _DEFUN (_wctomb_r, (r, s, wchar, state),
>        if (state->__count == -4 && (wchar < 0xdc00 || wchar >= 0xdfff))
>  	{
>  	  /* At this point only the second half of a surrogate pair is valid. */
> +	  r->_errno = EILSEQ;
>  	  return -1;
>  	}
>        if (wchar <= 0x7f)
> @@ -51,14 +53,20 @@ _DEFUN (_wctomb_r, (r, s, wchar, state),
>  	      wint_t tmp;
>  	      /* UTF-16 surrogates -- must not occur in normal UCS-4 data */
>  	      if (sizeof (wchar_t) != 2)
> -		return -1;
> +		{
> +		  r->_errno = EILSEQ;
> +		  return -1;
> +		}
>  	      if (wchar >= 0xdc00)
>  		{
>  		  /* Second half of a surrogate pair. It's not valid if
>  		     we don't have already read a first half of a surrogate
>  		     before. */
>  		  if (state->__count != -4)
> -		    return -1;
> +		    {
> +		      r->_errno = EILSEQ;
> +		      return -1;
> +		    }
>  		  /* If it's valid, reconstruct the full Unicode value and
>  		     return the trailing three bytes of the UTF-8 char. */
>  		  tmp = (state->__value.__wchb[0] << 16)
> @@ -93,7 +101,10 @@ _DEFUN (_wctomb_r, (r, s, wchar, state),
>            return 4;
>          }
>        else
> -        return -1;
> +	{
> +	  r->_errno = EILSEQ;
> +	  return -1;
> +	}
>      }
>    else if (!strcmp (__lc_ctype, "C-SJIS"))
>      {
> @@ -113,7 +124,10 @@ _DEFUN (_wctomb_r, (r, s, wchar, state),
>                return 2;
>              }
>            else
> -            return -1;
> +	    {
> +	      r->_errno = EILSEQ;
> +	      return -1;
> +	    }
>          }
>      }
>    else if (!strcmp (__lc_ctype, "C-EUCJP"))
> @@ -134,7 +148,10 @@ _DEFUN (_wctomb_r, (r, s, wchar, state),
>                return 2;
>              }
>            else
> -            return -1;
> +	    {
> +	      r->_errno = EILSEQ;
> +	      return -1;
> +	    }
>          }
>      }
>    else if (!strcmp (__lc_ctype, "C-JIS"))
> @@ -165,7 +182,10 @@ _DEFUN (_wctomb_r, (r, s, wchar, state),
>                return cnt + 2;
>              }
>            else
> -            return -1;
> +	    {
> +	      r->_errno = EILSEQ;
> +	      return -1;
> +	    }
>          }
>        else
>          {
> @@ -187,6 +207,12 @@ _DEFUN (_wctomb_r, (r, s, wchar, state),
>      return 0;
>   
>    /* otherwise we are dealing with a single byte character */
> +  if (wchar >= 0x100)
> +    {
> +      r->_errno = EILSEQ;
> +      return -1;
> +    }
> +
>    *s = (char) wchar;
>    return 1;
>  }
>
>
>   



More information about the Newlib mailing list