From 6d19a40a8a23d9aa5d61ace247a5fea1bd103995 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 8 Jun 2021 15:08:22 +0900 Subject: core: Avoid truncation of error message in the middle of a character. * configure.ac (AM_LANGINFO_CODESET): Add. * src/strerror.c (_gpg_strerror_r): Check the boundary of character. -- GnuPG-bug-id: 5048 Signed-off-by: NIIBE Yutaka --- src/strerror.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'src') diff --git a/src/strerror.c b/src/strerror.c index 4cce17f..fb1bebf 100644 --- a/src/strerror.c +++ b/src/strerror.c @@ -32,6 +32,10 @@ #include "gettext.h" #include "err-codes.h" +#if defined(ENABLE_NLS) && defined(HAVE_LANGINFO_CODESET) +#include +#endif + /* Return a pointer to a string containing a description of the error code in the error value ERR. This function is not thread-safe. */ const char * @@ -169,9 +173,30 @@ _gpg_strerror_r (gpg_error_t err, char *buf, size_t buflen) errstr = dgettext (PACKAGE, msgstr + msgidx[msgidxof (code)]); errstr_len = strlen (errstr) + 1; cpy_len = errstr_len < buflen ? errstr_len : buflen; +#if defined(ENABLE_NLS) && defined(HAVE_LANGINFO_CODESET) + /* Avoid truncation in the middle of "character" boundary. */ + if (buflen && errstr_len > buflen + && ((unsigned char)errstr[cpy_len-1] & 0xC0) == 0x80 + && !strcasecmp (nl_langinfo (CODESET), "UTF-8")) + { + /* Go back to the boundary */ + for (; cpy_len; cpy_len--) + if (((unsigned char)errstr[cpy_len-1] & 0xC0) != 0x80) + break; + memcpy (buf, errstr, cpy_len); + memset (buf+cpy_len, 0, buflen - cpy_len); + } + else + { + memcpy (buf, errstr, cpy_len); + if (buflen) + buf[buflen - 1] = '\0'; + } +#else memcpy (buf, errstr, cpy_len); if (buflen) buf[buflen - 1] = '\0'; +#endif return cpy_len == errstr_len ? 0 : ERANGE; } -- cgit v1.2.3