changeset 17660:ea9dc06bfca8

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.
author Paul Eggert <eggert@cs.ucla.edu>
date Fri, 16 May 2014 13:56:00 -0700
parents 3e1daa05022b
children ec75d04b657d
files ChangeLog lib/mbrtowc.c m4/mbrlen.m4 m4/mbrtowc.m4 tests/test-mbrtowc.c
diffstat 5 files changed, 97 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- 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  <eggert@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  <eggert@cs.ucla.edu>
 
 	doc: document mbrtowc and mbrlen problem with empty input
--- 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;
--- 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 <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], [
   :
--- 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 <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], [
   :
--- 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));
   }