# HG changeset patch # User Paul Eggert # Date 1400273760 25200 # Node ID ea9dc06bfca841b5970732520bbd5634b117094d # Parent 3e1daa05022bbf4c8e7592dda7b2a2a31788f13d mbrlen, mbrtowc: fix bug with empty input * lib/mbrtowc.c (rpl_mbrtowc) [MBRTOWC_EMPTY_INPUT_BUG]: Fix the bug. * m4/mbrlen.m4 (gl_MBRLEN_EMPTY_INPUT): New macro. It's not used, so this is mainly for documentation. * m4/mbrtowc.m4 (gl_MBRTOWC_EMPTY_INPUT): New macro. (gl_FUNC_MBRTOWC): Use it. * tests/test-mbrtowc.c (main): Test for the bug. diff -r 3e1daa05022b -r ea9dc06bfca8 ChangeLog --- a/ChangeLog Thu May 15 18:30:04 2014 -0700 +++ b/ChangeLog Fri May 16 13:56:00 2014 -0700 @@ -1,3 +1,13 @@ +2014-05-16 Paul Eggert + + mbrlen, mbrtowc: fix bug with empty input + * lib/mbrtowc.c (rpl_mbrtowc) [MBRTOWC_EMPTY_INPUT_BUG]: Fix the bug. + * m4/mbrlen.m4 (gl_MBRLEN_EMPTY_INPUT): New macro. It's not used, + so this is mainly for documentation. + * m4/mbrtowc.m4 (gl_MBRTOWC_EMPTY_INPUT): New macro. + (gl_FUNC_MBRTOWC): Use it. + * tests/test-mbrtowc.c (main): Test for the bug. + 2014-05-15 Paul Eggert doc: document mbrtowc and mbrlen problem with empty input diff -r 3e1daa05022b -r ea9dc06bfca8 lib/mbrtowc.c --- a/lib/mbrtowc.c Thu May 15 18:30:04 2014 -0700 +++ b/lib/mbrtowc.c Fri May 16 13:56:00 2014 -0700 @@ -328,7 +328,7 @@ size_t rpl_mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps) { -# if MBRTOWC_NULL_ARG2_BUG || MBRTOWC_RETVAL_BUG +# if MBRTOWC_NULL_ARG2_BUG || MBRTOWC_RETVAL_BUG || MBRTOWC_EMPTY_INPUT_BUG if (s == NULL) { pwc = NULL; @@ -337,6 +337,11 @@ } # endif +# if MBRTOWC_EMPTY_INPUT_BUG + if (n == 0) + return (size_t) -2; +# endif + # if MBRTOWC_RETVAL_BUG { static mbstate_t internal_state; diff -r 3e1daa05022b -r ea9dc06bfca8 m4/mbrlen.m4 --- a/m4/mbrlen.m4 Thu May 15 18:30:04 2014 -0700 +++ b/m4/mbrlen.m4 Fri May 16 13:56:00 2014 -0700 @@ -1,4 +1,4 @@ -# mbrlen.m4 serial 8 +# mbrlen.m4 serial 9 dnl Copyright (C) 2008, 2010-2014 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -227,6 +227,40 @@ ]) ]) +dnl Test whether mbrlen returns the correct value on empty input. + +AC_DEFUN([gl_MBRLEN_EMPTY_INPUT], +[ + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles + AC_CACHE_CHECK([whether mbrlen works on empty input], + [gl_cv_func_mbrlen_empty_input], + [ + dnl Initial guess, used when cross-compiling or when no suitable locale + dnl is present. +changequote(,)dnl + case "$host_os" in + # Guess no on AIX and glibc systems. + aix* | *-gnu*) + gl_cv_func_mbrlen_empty_input="guessing no" ;; + *) gl_cv_func_mbrlen_empty_input="guessing yes" ;; + esac +changequote([,])dnl + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ + #include + static mbstate_t mbs; + int + main (void) + { + return mbrlen ("", 0, &mbs) == (size_t) -2; + }]])], + [gl_cv_func_mbrlen_empty_input=no], + [gl_cv_func_mbrlen_empty_input=yes], + [:]) + ]) +]) + # Prerequisites of lib/mbrlen.c. AC_DEFUN([gl_PREREQ_MBRLEN], [ : diff -r 3e1daa05022b -r ea9dc06bfca8 m4/mbrtowc.m4 --- a/m4/mbrtowc.m4 Thu May 15 18:30:04 2014 -0700 +++ b/m4/mbrtowc.m4 Fri May 16 13:56:00 2014 -0700 @@ -1,4 +1,4 @@ -# mbrtowc.m4 serial 25 +# mbrtowc.m4 serial 26 dnl Copyright (C) 2001-2002, 2004-2005, 2008-2014 Free Software Foundation, dnl Inc. dnl This file is free software; the Free Software Foundation @@ -39,6 +39,7 @@ gl_MBRTOWC_NULL_ARG2 gl_MBRTOWC_RETVAL gl_MBRTOWC_NUL_RETVAL + gl_MBRTOWC_EMPTY_INPUT case "$gl_cv_func_mbrtowc_null_arg1" in *yes) ;; *) AC_DEFINE([MBRTOWC_NULL_ARG1_BUG], [1], @@ -67,6 +68,14 @@ REPLACE_MBRTOWC=1 ;; esac + case "$gl_cv_func_mbrtowc_empty_input" in + *yes) ;; + *) AC_DEFINE([MBRTOWC_EMPTY_INPUT_BUG], [1], + [Define if the mbrtowc function does not return (size_t) 2 + for empty input.]) + REPLACE_MBRTOWC=1 + ;; + esac fi fi ]) @@ -533,6 +542,41 @@ ]) ]) +dnl Test whether mbrtowc returns the correct value on empty input. + +AC_DEFUN([gl_MBRTOWC_EMPTY_INPUT], +[ + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles + AC_CACHE_CHECK([whether mbrtowc works on empty input], + [gl_cv_func_mbrtowc_empty_input], + [ + dnl Initial guess, used when cross-compiling or when no suitable locale + dnl is present. +changequote(,)dnl + case "$host_os" in + # Guess no on AIX and glibc systems. + aix* | *-gnu*) + gl_cv_func_mbrtowc_empty_input="guessing no" ;; + *) gl_cv_func_mbrtowc_empty_input="guessing yes" ;; + esac +changequote([,])dnl + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ + #include + static wchar_t wc; + static mbstate_t mbs; + int + main (void) + { + return mbrtowc (&wc, "", 0, &mbs) == (size_t) -2; + }]])], + [gl_cv_func_mbrtowc_empty_input=no], + [gl_cv_func_mbrtowc_empty_input=yes], + [:]) + ]) +]) + # Prerequisites of lib/mbrtowc.c. AC_DEFUN([gl_PREREQ_MBRTOWC], [ : diff -r 3e1daa05022b -r ea9dc06bfca8 tests/test-mbrtowc.c --- a/tests/test-mbrtowc.c Thu May 15 18:30:04 2014 -0700 +++ b/tests/test-mbrtowc.c Fri May 16 13:56:00 2014 -0700 @@ -46,10 +46,7 @@ memset (&state, '\0', sizeof (mbstate_t)); wc = (wchar_t) 0xBADFACE; ret = mbrtowc (&wc, "x", 0, &state); - /* gnulib's implementation returns (size_t)(-2). - The AIX 5.1 implementation returns (size_t)(-1). - glibc's implementation returns 0. */ - ASSERT (ret == (size_t)(-2) || ret == (size_t)(-1) || ret == 0); + ASSERT (ret == (size_t)(-2)); ASSERT (mbsinit (&state)); }