summary refs log tree commit diff
path: root/stdio-common
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2000-07-22 07:02:05 +0000
committerUlrich Drepper <drepper@redhat.com>2000-07-22 07:02:05 +0000
commit40c014b3dcc698ae2cc935aefabbeb2196088128 (patch)
treead1ae53dfe308220ec4fc6d32521986d627891c6 /stdio-common
parentc056ee48cbf7d3fc88d840af64d75c68ac281519 (diff)
downloadglibc-40c014b3dcc698ae2cc935aefabbeb2196088128.tar.gz
glibc-40c014b3dcc698ae2cc935aefabbeb2196088128.tar.xz
glibc-40c014b3dcc698ae2cc935aefabbeb2196088128.zip
Update.
2000-07-22  Ulrich Drepper  <drepper@redhat.com>

	* stdio-common/vfprintf.c (process_string_arg): Correct handling
	of multibyte character strings in %s format with precision.
Diffstat (limited to 'stdio-common')
-rw-r--r--stdio-common/vfprintf.c31
1 files changed, 28 insertions, 3 deletions
diff --git a/stdio-common/vfprintf.c b/stdio-common/vfprintf.c
index 23981d18cd..1682b0b6ce 100644
--- a/stdio-common/vfprintf.c
+++ b/stdio-common/vfprintf.c
@@ -1142,9 +1142,34 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
 	else if (!is_long && spec != L_('S'))				      \
 	  {								      \
 	    if (prec != -1)						      \
-	      /* Search for the end of the string, but don't search past      \
-		 the length specified by the precision.  */		      \
-	      len = __strnlen (string, prec);				      \
+	      {								      \
+		/* Search for the end of the string, but don't search past    \
+		   the length (in bytes) specified by the precision.  Also    \
+		   don't use incomplete characters.  */			      \
+		if (_NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_MB_CUR_MAX) == 1)   \
+		  len = __strnlen (string, prec);			      \
+		else							      \
+		  {							      \
+		    /* In case we have a multibyte character set the	      \
+		       situation is more compilcated.  We must not copy	      \
+		       bytes at the end which form an incomplete character. */\
+		    wchar_t ignore[prec];				      \
+		    const char *str2 = string;				      \
+		    mbstate_t ps;					      \
+									      \
+		    memset (&ps, '\0', sizeof (ps));			      \
+		    if (__mbsnrtowcs (ignore, &str2, prec, prec, &ps)	      \
+			== (size_t) -1)					      \
+		      {							      \
+			done = -1;					      \
+			goto all_done;					      \
+		      }							      \
+		    if (str2 == NULL)					      \
+		      len = strlen (string);				      \
+		    else						      \
+		      len = str2 - string - (ps.__count);		      \
+		  }							      \
+	      }								      \
 	    else							      \
 	      len = strlen (string);					      \
 	  }								      \