* 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. --- ChangeLog | 10 ++++++++++ lib/mbrtowc.c | 7 ++++++- m4/mbrlen.m4 | 36 +++++++++++++++++++++++++++++++++++- m4/mbrtowc.m4 | 46 +++++++++++++++++++++++++++++++++++++++++++++- tests/test-mbrtowc.c | 5 +---- 5 files changed, 97 insertions(+), 7 deletions(-)
diff --git a/ChangeLog b/ChangeLog index 2e59362..39e4c10 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2014-05-16 Paul Eggert <egg...@cs.ucla.edu> + + 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 <egg...@cs.ucla.edu> doc: document mbrtowc and mbrlen problem with empty input diff --git a/lib/mbrtowc.c b/lib/mbrtowc.c index 9415fd7..5743f43 100644 --- a/lib/mbrtowc.c +++ b/lib/mbrtowc.c @@ -328,7 +328,7 @@ mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps) 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 @@ rpl_mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps) } # endif +# if MBRTOWC_EMPTY_INPUT_BUG + if (n == 0) + return (size_t) -2; +# endif + # if MBRTOWC_RETVAL_BUG { static mbstate_t internal_state; diff --git a/m4/mbrlen.m4 b/m4/mbrlen.m4 index 57db29a..10df9b3 100644 --- a/m4/mbrlen.m4 +++ b/m4/mbrlen.m4 @@ -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 @@ int main () ]) ]) +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 <wchar.h> + 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 --git a/m4/mbrtowc.m4 b/m4/mbrtowc.m4 index a9d1570..47ab2f4 100644 --- a/m4/mbrtowc.m4 +++ b/m4/mbrtowc.m4 @@ -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 @@ AC_DEFUN([gl_FUNC_MBRTOWC], 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 @@ AC_DEFUN([gl_FUNC_MBRTOWC], 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 @@ int main () ]) ]) +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 <wchar.h> + 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 --git a/tests/test-mbrtowc.c b/tests/test-mbrtowc.c index f64af4f..e8cdea0 100644 --- a/tests/test-mbrtowc.c +++ b/tests/test-mbrtowc.c @@ -46,10 +46,7 @@ main (int argc, char *argv[]) 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)); } -- 1.9.0