[newlib-cygwin] Cygwin: wcsxfrm_l: Only byte swap if dest size is > 0

Corinna Vinschen corinna@sourceware.org
Tue Mar 19 20:03:00 GMT 2019


https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=10900b98d177c6cf01d294fa187e9d13b053b80c

commit 10900b98d177c6cf01d294fa187e9d13b053b80c
Author: Corinna Vinschen <corinna@vinschen.de>
Date:   Tue Mar 19 20:56:11 2019 +0100

    Cygwin: wcsxfrm_l: Only byte swap if dest size is > 0
    
    commit c0d7d3e1a2fa96db15613cbd68a68c96966bc402 removed the usage of the
    LCMAP_BYTEREV flag in the call to LCMapStringW to workaround a strange
    bug in LCMapStringW.  This patch didn't take a userspace call of
    wcsxfrm{_l} with NULL buffer and 0 size to evaluate the required buffer
    size into account.  This introduced a crash trying to byte swap the
    NULL buffer.  This patch fixes that problem.
    
    Signed-off-by: Corinna Vinschen <corinna@vinschen.de>

Diff:
---
 winsup/cygwin/nlsfuncs.cc   | 21 ++++++++++++---------
 winsup/cygwin/release/3.0.5 |  3 +++
 2 files changed, 15 insertions(+), 9 deletions(-)

diff --git a/winsup/cygwin/nlsfuncs.cc b/winsup/cygwin/nlsfuncs.cc
index 5bf7d22..455afb4 100644
--- a/winsup/cygwin/nlsfuncs.cc
+++ b/winsup/cygwin/nlsfuncs.cc
@@ -1204,15 +1204,18 @@ wcsxfrm_l (wchar_t *__restrict ws1, const wchar_t *__restrict ws2, size_t wsn,
   if (ret)
     {
       ret /= sizeof (wchar_t);
-     /* Byte swap the array ourselves here. */
-      for (size_t idx = 0; idx < ret; ++idx)
-	ws1[idx] = __builtin_bswap16 (ws1[idx]);
-      /* LCMapStringW returns byte count including the terminating NUL char.
-	 wcsxfrm is supposed to return length in wchar_t excluding the NUL.
-	 Since the array is only single byte NUL-terminated yet, make sure
-	 the result is wchar_t-NUL terminated. */
-      if (ret < wsn)
-	ws1[ret] = L'\0';
+      if (wsn)
+	{
+	  /* Byte swap the array ourselves here. */
+	  for (size_t idx = 0; idx < ret; ++idx)
+	    ws1[idx] = __builtin_bswap16 (ws1[idx]);
+	  /* LCMapStringW returns byte count including the terminating NUL char.
+	     wcsxfrm is supposed to return length in wchar_t excluding the NUL.
+	     Since the array is only single byte NUL-terminated yet, make sure
+	     the result is wchar_t-NUL terminated. */
+	  if (ret < wsn)
+	    ws1[ret] = L'\0';
+	}
       return ret;
     }
   if (GetLastError () != ERROR_INSUFFICIENT_BUFFER)
diff --git a/winsup/cygwin/release/3.0.5 b/winsup/cygwin/release/3.0.5
index 62c8cf5..a52412c 100644
--- a/winsup/cygwin/release/3.0.5
+++ b/winsup/cygwin/release/3.0.5
@@ -11,3 +11,6 @@ Bug Fixes
 
 - Fix /proc/version after uname change
   Addresses: https://cygwin.com/ml/cygwin/2019-03/msg00467.html
+
+- Fix a crash in wcsxfrm_l if destination size is 0.
+  Addresses: https://cygwin.com/ml/cygwin/2019-03/msg00492.html



More information about the Cygwin-cvs mailing list