From: Michihiro NAKAJIMA Date: Sat, 26 Mar 2011 03:21:44 +0000 (-0400) Subject: We should use mbrtowc/mbtowc at archive_wstring_append_from_mbs instead of X-Git-Tag: v3.0.0a~601 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=399121d23f241007ad7a508bb3a923707deea7dd;p=thirdparty%2Flibarchive.git We should use mbrtowc/mbtowc at archive_wstring_append_from_mbs instead of mbsrtowcs/mbstowcs because we cannot check the MBS limit specified by a caller with a parameter 'len', and it is possible that mbsrtowcs/mbstowcs convert extra MBS when strlen(MBS) > 'len'. SVN-Revision: 3077 --- diff --git a/CMakeLists.txt b/CMakeLists.txt index e2eef8dd6..0fcd5235f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -575,7 +575,6 @@ CHECK_FUNCTION_EXISTS_GLIBC(lstat HAVE_LSTAT) CHECK_FUNCTION_EXISTS_GLIBC(lutimes HAVE_LUTIMES) CHECK_FUNCTION_EXISTS_GLIBC(mbrtowc HAVE_MBRTOWC) CHECK_FUNCTION_EXISTS_GLIBC(mbsnrtowcs HAVE_MBSNRTOWCS) -CHECK_FUNCTION_EXISTS_GLIBC(mbsrtowcs HAVE_MBSRTOWCS) CHECK_FUNCTION_EXISTS_GLIBC(memmove HAVE_MEMMOVE) CHECK_FUNCTION_EXISTS_GLIBC(mkdir HAVE_MKDIR) CHECK_FUNCTION_EXISTS_GLIBC(mkfifo HAVE_MKFIFO) diff --git a/build/cmake/config.h.in b/build/cmake/config.h.in index 87263a7f5..07364a1ce 100644 --- a/build/cmake/config.h.in +++ b/build/cmake/config.h.in @@ -622,9 +622,6 @@ typedef uint64_t uintmax_t; /* Define to 1 if you have the `mbsnrtowcs' function. */ #cmakedefine HAVE_MBSNRTOWCS 1 -/* Define to 1 if you have the `mbsrtowcs' function. */ -#cmakedefine HAVE_MBSRTOWCS 1 - /* Define to 1 if you have the `memmove' function. */ #cmakedefine HAVE_MEMMOVE 1 diff --git a/configure.ac b/configure.ac index c628063d2..b679a99e8 100644 --- a/configure.ac +++ b/configure.ac @@ -437,7 +437,7 @@ AC_CHECK_FUNCS([fstat fstatat fstatfs fstatvfs ftruncate futimens futimes]) AC_CHECK_FUNCS([geteuid getpid getgrgid_r getgrnam_r]) AC_CHECK_FUNCS([getpwnam_r getpwuid_r getvfsbyname gmtime_r]) AC_CHECK_FUNCS([lchflags lchmod lchown link localtime_r lstat lutimes]) -AC_CHECK_FUNCS([mbrtowc mbsnrtowcs mbsrtowcs memmove memset]) +AC_CHECK_FUNCS([mbrtowc mbsnrtowcs memmove memset]) AC_CHECK_FUNCS([mkdir mkfifo mknod mkstemp]) AC_CHECK_FUNCS([nl_langinfo openat pipe poll readlink readlinkat]) AC_CHECK_FUNCS([select setenv setlocale sigaction statfs statvfs]) diff --git a/libarchive/archive_string.c b/libarchive/archive_string.c index 3a0a397de..d0c859dc2 100644 --- a/libarchive/archive_string.c +++ b/libarchive/archive_string.c @@ -469,8 +469,10 @@ archive_wstring_append_from_mbs(struct archive *a, * so this length estimate will always be big enough. */ size_t wcs_length = len; + size_t mbs_length = len; const char *mbs = p; -#if HAVE_MBSRTOWCS || HAVE_MBSNRTOWCS + wchar_t *wcs; +#if HAVE_MBRTOWC || HAVE_MBSNRTOWCS mbstate_t shift_state; memset(&shift_state, 0, sizeof(shift_state)); @@ -478,21 +480,42 @@ archive_wstring_append_from_mbs(struct archive *a, if (NULL == archive_wstring_ensure(dest, dest->length + wcs_length + 1)) __archive_errx(1, "No memory for archive_wstring_append_from_mbs()"); - + wcs = dest->s + dest->length; #if HAVE_MBSNRTOWCS - r = mbsnrtowcs(dest->s + dest->length, &mbs, len, wcs_length, - &shift_state); -#elif HAVE_MBSRTOWCS - r = mbsrtowcs(dest->s + dest->length, &mbs, wcs_length, &shift_state); -#else - r = mbstowcs(dest->s + dest->length, mbs, wcs_length); -#endif + r = mbsnrtowcs(wcs, &mbs, mbs_length, wcs_length, &shift_state); if (r != (size_t)-1) { dest->length += r; dest->s[dest->length] = L'\0'; return (0); } return (-1); +#else /* HAVE_MBSNRTOWCS */ + /* + * We cannot use mbsrtowcs/mbstowcs here because those may convert + * extra MBS when strlen(p) > len and one wide character consis of + * multi bytes. + */ + while (wcs_length > 0 && *mbs && mbs_length > 0) { +#if HAVE_MBRTOWC + r = mbrtowc(wcs, mbs, wcs_length, &shift_state); +#else + r = mbtowc(wcs, mbs, wcs_length); +#endif + if (r == (size_t)-1 || r == (size_t)-2) { + dest->s[dest->length] = L'\0'; + return (-1); + } + if (r == 0 || r > mbs_length) + break; + wcs++; + wcs_length--; + mbs += r; + mbs_length -= r; + } + dest->length = wcs - dest->s; + dest->s[dest->length] = L'\0'; + return (0); +#endif /* HAVE_MBSNRTOWCS */ } #endif