Cygwin: fix buffer overrun in cygwin_strcasecmp
sys_mbstowcs is called with the destination buffer length set to MaximumLength from the receiving UNICODE_STRING buffer. This is twice as much as the actual size of the buffer in wchar_t units, which is the unit expected by sys_mbstowcs. sys_mbstowcs always attaches a NUL, within the destination buffersize given. But if the string is exactly one wchar_t less than the actual buffer, and the buffersize is given too large, sys_mbstowcs writes a NUL one wchar_t beyond the buffer. This has only been exposed with Cygwin 3.1.5 because alloca on newer gcc 9 apparently allocates more tightly. The alloca buffer here is requested with 16 bytes, which is exactly the number of bytes required for the string L"cmd.exe". Older gcc apparently allocated a few more bytes on the stack, while gcc 9 allocates in 16 byte granularity... Fix this by giving the correct destination buffer size to sys_mbstowcs. Fixes: https://cygwin.com/pipermail/cygwin/2020-June/245226.html Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
This commit is contained in:
parent
f095752167
commit
bb96bd03b0
|
@ -9,3 +9,6 @@ Bug Fixes:
|
||||||
----------
|
----------
|
||||||
|
|
||||||
- Fix IPPROTO_TCP option handling, especially in terms of TCP_MAXSEG.
|
- Fix IPPROTO_TCP option handling, especially in terms of TCP_MAXSEG.
|
||||||
|
|
||||||
|
- Fix a buffer overrun in Cygwin-internal string comparison.
|
||||||
|
Fixes: https://cygwin.com/pipermail/cygwin/2020-June/245226.html
|
||||||
|
|
|
@ -635,7 +635,7 @@ sys_cp_mbstowcs (mbtowc_p f_mbtowc, wchar_t *dst, size_t dlen,
|
||||||
/* The technique is based on a discussion here:
|
/* The technique is based on a discussion here:
|
||||||
http://www.mail-archive.com/linux-utf8@nl.linux.org/msg00080.html
|
http://www.mail-archive.com/linux-utf8@nl.linux.org/msg00080.html
|
||||||
|
|
||||||
Invalid bytes in a multibyte secuence are converted to
|
Invalid bytes in a multibyte sequence are converted to
|
||||||
the private use area which is already used to store ASCII
|
the private use area which is already used to store ASCII
|
||||||
chars invalid in Windows filenames. This technque allows
|
chars invalid in Windows filenames. This technque allows
|
||||||
to store them in a symmetric way. */
|
to store them in a symmetric way. */
|
||||||
|
@ -801,14 +801,18 @@ extern "C" int __stdcall
|
||||||
cygwin_strcasecmp (const char *cs, const char *ct)
|
cygwin_strcasecmp (const char *cs, const char *ct)
|
||||||
{
|
{
|
||||||
UNICODE_STRING us, ut;
|
UNICODE_STRING us, ut;
|
||||||
ULONG len;
|
ULONG len, ulen;
|
||||||
|
|
||||||
|
len = strlen (cs) + 1;
|
||||||
|
ulen = len * sizeof (WCHAR);
|
||||||
|
RtlInitEmptyUnicodeString (&us, (PWCHAR) alloca (ulen), ulen);
|
||||||
|
us.Length = sys_mbstowcs (us.Buffer, len, cs) * sizeof (WCHAR);
|
||||||
|
|
||||||
|
len = strlen (ct) + 1;
|
||||||
|
ulen = len * sizeof (WCHAR);
|
||||||
|
RtlInitEmptyUnicodeString (&ut, (PWCHAR) alloca (ulen), ulen);
|
||||||
|
ut.Length = sys_mbstowcs (ut.Buffer, len, ct) * sizeof (WCHAR);
|
||||||
|
|
||||||
len = (strlen (cs) + 1) * sizeof (WCHAR);
|
|
||||||
RtlInitEmptyUnicodeString (&us, (PWCHAR) alloca (len), len);
|
|
||||||
us.Length = sys_mbstowcs (us.Buffer, us.MaximumLength, cs) * sizeof (WCHAR);
|
|
||||||
len = (strlen (ct) + 1) * sizeof (WCHAR);
|
|
||||||
RtlInitEmptyUnicodeString (&ut, (PWCHAR) alloca (len), len);
|
|
||||||
ut.Length = sys_mbstowcs (ut.Buffer, ut.MaximumLength, ct) * sizeof (WCHAR);
|
|
||||||
return RtlCompareUnicodeString (&us, &ut, TRUE);
|
return RtlCompareUnicodeString (&us, &ut, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -816,19 +820,21 @@ extern "C" int __stdcall
|
||||||
cygwin_strncasecmp (const char *cs, const char *ct, size_t n)
|
cygwin_strncasecmp (const char *cs, const char *ct, size_t n)
|
||||||
{
|
{
|
||||||
UNICODE_STRING us, ut;
|
UNICODE_STRING us, ut;
|
||||||
ULONG len;
|
ULONG ulen;
|
||||||
size_t ls = 0, lt = 0;
|
size_t ls = 0, lt = 0;
|
||||||
|
|
||||||
while (cs[ls] && ls < n)
|
while (cs[ls] && ls < n)
|
||||||
++ls;
|
++ls;
|
||||||
len = (ls + 1) * sizeof (WCHAR);
|
ulen = (ls + 1) * sizeof (WCHAR);
|
||||||
RtlInitEmptyUnicodeString (&us, (PWCHAR) alloca (len), len);
|
RtlInitEmptyUnicodeString (&us, (PWCHAR) alloca (ulen), ulen);
|
||||||
us.Length = sys_mbstowcs (us.Buffer, ls + 1, cs, ls) * sizeof (WCHAR);
|
us.Length = sys_mbstowcs (us.Buffer, ls + 1, cs, ls) * sizeof (WCHAR);
|
||||||
|
|
||||||
while (ct[lt] && lt < n)
|
while (ct[lt] && lt < n)
|
||||||
++lt;
|
++lt;
|
||||||
len = (lt + 1) * sizeof (WCHAR);
|
ulen = (lt + 1) * sizeof (WCHAR);
|
||||||
RtlInitEmptyUnicodeString (&ut, (PWCHAR) alloca (len), len);
|
RtlInitEmptyUnicodeString (&ut, (PWCHAR) alloca (ulen), ulen);
|
||||||
ut.Length = sys_mbstowcs (ut.Buffer, lt + 1, ct, lt) * sizeof (WCHAR);
|
ut.Length = sys_mbstowcs (ut.Buffer, lt + 1, ct, lt) * sizeof (WCHAR);
|
||||||
|
|
||||||
return RtlCompareUnicodeString (&us, &ut, TRUE);
|
return RtlCompareUnicodeString (&us, &ut, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue