File bash-4.2-bsc1138676.patch of Package bash.13161
Fix for CVE-2012-6711 reported in bsc#1138676
---
lib/sh/unicode.c | 140 +++++++++++++++++++++++++++++++++++++++----------------
1 file changed, 100 insertions(+), 40 deletions(-)
--- lib/sh/unicode.c
+++ lib/sh/unicode.c 2019-11-08 13:49:17.538469163 +0000
@@ -1,6 +1,6 @@
/* unicode.c - functions to convert unicode characters */
-/* Copyright (C) 2010 Free Software Foundation, Inc.
+/* Copyright (C) 2010-2012 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -61,6 +61,8 @@ static iconv_t localconv;
#endif
#ifndef HAVE_LOCALE_CHARSET
+static char charsetbuf[40];
+
static char *
stub_charset ()
{
@@ -68,32 +70,32 @@ stub_charset ()
locale = get_locale_var ("LC_CTYPE");
if (locale == 0 || *locale == 0)
- return "ASCII";
+ {
+ strcpy (charsetbuf, "ASCII");
+ return charsetbuf;
+ }
s = strrchr (locale, '.');
if (s)
{
- t = strchr (s, '@');
+ strcpy (charsetbuf, s+1);
+ t = strchr (charsetbuf, '@');
if (t)
*t = 0;
- return ++s;
+ return charsetbuf;
}
- else if (STREQ (locale, "UTF-8"))
- return "UTF-8";
- else
- return "ASCII";
+ strcpy (charsetbuf, locale);
+ return charsetbuf;
}
#endif
/* u32toascii ? */
int
-u32tochar (wc, s)
- wchar_t wc;
+u32tochar (x, s)
+ unsigned long x;
char *s;
{
- unsigned long x;
int l;
- x = wc;
l = (x <= UCHAR_MAX) ? 1 : ((x <= USHORT_MAX) ? 2 : 4);
if (x <= UCHAR_MAX)
@@ -116,30 +118,91 @@ u32tochar (wc, s)
int
u32toutf8 (wc, s)
- wchar_t wc;
+ u_bits32_t wc;
char *s;
{
int l;
- l = (wc < 0x0080) ? 1 : ((wc < 0x0800) ? 2 : 3);
-
if (wc < 0x0080)
- s[0] = (unsigned char)wc;
+ {
+ s[0] = (char)wc;
+ l = 1;
+ }
else if (wc < 0x0800)
{
s[0] = (wc >> 6) | 0xc0;
s[1] = (wc & 0x3f) | 0x80;
+ l = 2;
}
- else
+ else if (wc < 0x10000)
{
+ /* Technically, we could return 0 here if 0xd800 <= wc <= 0x0dfff */
s[0] = (wc >> 12) | 0xe0;
s[1] = ((wc >> 6) & 0x3f) | 0x80;
s[2] = (wc & 0x3f) | 0x80;
+ l = 3;
+ }
+ else if (wc < 0x200000)
+ {
+ s[0] = (wc >> 18) | 0xf0;
+ s[1] = ((wc >> 12) & 0x3f) | 0x80;
+ s[2] = ((wc >> 6) & 0x3f) | 0x80;
+ s[3] = (wc & 0x3f) | 0x80;
+ l = 4;
+ }
+ /* Strictly speaking, UTF-8 doesn't have characters longer than 4 bytes */
+ else if (wc < 0x04000000)
+ {
+ s[0] = (wc >> 24) | 0xf8;
+ s[1] = ((wc >> 18) & 0x3f) | 0x80;
+ s[2] = ((wc >> 12) & 0x3f) | 0x80;
+ s[3] = ((wc >> 6) & 0x3f) | 0x80;
+ s[4] = (wc & 0x3f) | 0x80;
+ l = 5;
}
+ else if (wc < 0x080000000)
+ {
+ s[0] = (wc >> 30) | 0xf8;
+ s[1] = ((wc >> 24) & 0x3f) | 0x80;
+ s[2] = ((wc >> 18) & 0x3f) | 0x80;
+ s[3] = ((wc >> 12) & 0x3f) | 0x80;
+ s[4] = ((wc >> 6) & 0x3f) | 0x80;
+ s[5] = (wc & 0x3f) | 0x80;
+ l = 6;
+ }
+ else
+ l = 0;
+
s[l] = '\0';
return l;
}
+/* Convert a 32-bit unsigned int (unicode) to a UTF-16 string. Rarely used,
+ only if sizeof(wchar_t) == 2. */
+int
+u32toutf16 (c, s)
+ u_bits32_t c;
+ unsigned short *s;
+{
+ int l;
+
+ l = 0;
+ if (c < 0x0d800)
+ {
+ s[0] = (unsigned short) (c & 0xFFFF);
+ l = 1;
+ }
+ else if (c >= 0x0e000 && c <= 0x010ffff)
+ {
+ c -= 0x010000;
+ s[0] = (unsigned short)((c >> 10) + 0xd800);
+ s[1] = (unsigned short)((c & 0x3ff) + 0xdc00);
+ l = 2;
+ }
+ s[l] = 0;
+ return l;
+}
+
/* convert a single unicode-32 character into a multibyte string and put the
result in S, which must be large enough (at least MB_LEN_MAX bytes) */
int
@@ -148,6 +211,7 @@ u32cconv (c, s)
char *s;
{
wchar_t wc;
+ wchar_t ws[3];
int n;
#if HAVE_ICONV
const char *charset;
@@ -157,21 +221,23 @@ u32cconv (c, s)
size_t sn;
#endif
- wc = c;
-
#if __STDC_ISO_10646__
- if (sizeof (wchar_t) == 4)
- {
- n = wctomb (s, wc);
- return n;
- }
+ wc = c;
+ if (sizeof (wchar_t) == 4 && c <= 0x7fffffff)
+ n = wctomb (s, wc);
+ else if (sizeof (wchar_t) == 2 && c <= 0x10ffff && u32toutf16 (c, ws))
+ n = wcstombs (s, ws, MB_LEN_MAX);
+ else
+ n = -1;
+ if (n != -1)
+ return n;
#endif
#if HAVE_NL_LANGINFO
codeset = nl_langinfo (CODESET);
if (STREQ (codeset, "UTF-8"))
{
- n = u32toutf8 (wc, s);
+ n = u32toutf8 (c, s);
return n;
}
#endif
@@ -196,19 +262,9 @@ u32cconv (c, s)
u32init = 1;
}
- if (utf8locale)
- {
- n = u32toutf8 (wc, s);
- return n;
- }
-
- if (localconv == (iconv_t)-1)
- {
- n = u32tochar (wc, s);
- return n;
- }
-
- n = u32toutf8 (wc, s);
+ n = u32toutf8 (c, s);
+ if (utf8locale || localconv == (iconv_t)-1)
+ return n;
optr = obuf;
obytesleft = sizeof (obuf);
@@ -228,8 +284,12 @@ u32cconv (c, s)
return (optr - obuf);
#endif
- n = u32tochar (wc, s); /* fallback */
+ n = u32tochar (c, s); /* fallback */
return n;
}
-
+#else
+void
+u32reset ()
+{
+}
#endif /* HANDLE_MULTIBYTE */