Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/winsup
diff options
context:
space:
mode:
authorChristopher Faylor <me@cgf.cx>2009-05-31 07:59:38 +0400
committerChristopher Faylor <me@cgf.cx>2009-05-31 07:59:38 +0400
commite44b9069cd227e8566888b85ec9fd2163d935e71 (patch)
tree50f098f82e3be4f97287f3958704dfdef44d3549 /winsup
parent025e4859affbadde459fb2bf42ad0946e5009d4c (diff)
* strfuncs.cc (sys_cp_mbstowcs): Treat src as unsigned char *. Convert failure
of f_mbtowc into a single malformed utf-16 value.
Diffstat (limited to 'winsup')
-rw-r--r--winsup/cygwin/ChangeLog5
-rw-r--r--winsup/cygwin/strfuncs.cc32
2 files changed, 30 insertions, 7 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index e64651ff8..b7ea755b2 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,5 +1,10 @@
2009-05-30 Christopher Faylor <me+cygwin@cgf.cx>
+ * strfuncs.cc (sys_cp_mbstowcs): Treat src as unsigned char *. Convert
+ failure of f_mbtowc into a single malformed utf-16 value.
+
+2009-05-30 Christopher Faylor <me+cygwin@cgf.cx>
+
* cygwin/include/sys/termios.h: Make default erase character "^?".
2009-05-30 Christopher Faylor <me+cygwin@cgf.cx>
diff --git a/winsup/cygwin/strfuncs.cc b/winsup/cygwin/strfuncs.cc
index 965bdeefd..4563f98db 100644
--- a/winsup/cygwin/strfuncs.cc
+++ b/winsup/cygwin/strfuncs.cc
@@ -523,7 +523,7 @@ sys_cp_mbstowcs (mbtowc_p f_mbtowc, char *charset, wchar_t *dst, size_t dlen,
const char *src, size_t nms)
{
wchar_t *ptr = dst;
- char *pmbs = (char *) src;
+ unsigned const char *pmbs = (unsigned const char *) src;
size_t count = 0;
size_t len = dlen;
int bytes;
@@ -539,12 +539,13 @@ sys_cp_mbstowcs (mbtowc_p f_mbtowc, char *charset, wchar_t *dst, size_t dlen,
UTF-8 sequence, there must be at least two more bytes left, and the
next byte must be a valid UTF-8 start byte. If the charset isn't
UTF-8 anyway, try to convert the following bytes as UTF-8 sequence. */
- if (*pmbs == 0x0e && nms > 2 && *(unsigned char *) (pmbs + 1) >= 0xc2
- && *(unsigned char *) (pmbs + 1) <= 0xf4 && *charset != 'U'/*TF-8*/)
+ if (*pmbs == 0x0e && nms > 2 && pmbs[1] >= 0xc2
+ && pmbs[1] <= 0xf4 && *charset != 'U'/*TF-8*/)
{
pmbs++;
--nms;
- bytes = __utf8_mbtowc (_REENT, ptr, pmbs, nms, charset, &ps);
+ bytes = __utf8_mbtowc (_REENT, ptr, (const char *) pmbs, nms,
+ charset, &ps);
if (bytes < 0)
{
/* Invalid UTF-8 sequence? Treat the ASCII SO character as
@@ -560,7 +561,7 @@ sys_cp_mbstowcs (mbtowc_p f_mbtowc, char *charset, wchar_t *dst, size_t dlen,
if (ps.__count == 4) /* First half of a surrogate. */
{
wchar_t *ptr2 = dst ? ptr + 1 : NULL;
- int bytes2 = __utf8_mbtowc (_REENT, ptr2, pmbs + bytes,
+ int bytes2 = __utf8_mbtowc (_REENT, ptr2, (const char *) pmbs + bytes,
nms - bytes, charset, &ps);
if (bytes2 < 0)
break;
@@ -571,8 +572,25 @@ sys_cp_mbstowcs (mbtowc_p f_mbtowc, char *charset, wchar_t *dst, size_t dlen,
--len;
}
}
- else
- bytes = f_mbtowc (_REENT, ptr, pmbs, nms, charset, &ps);
+ else if ((bytes = f_mbtowc (_REENT, ptr, (const char *) pmbs, nms, charset, &ps)) < 0 && *pmbs > '\x80')
+ {
+ /* This should probably be handled in f_mbtowc which can operate
+ on sequences rather than individual characters.
+ The technique is based on a discussion here:
+
+ http://www.mail-archive.com/linux-utf8@nl.linux.org/msg00080.html
+
+ This is hardly perfect. Windows doesn't do anything sensical with
+ characters converted to this format and (currently) we don't convert
+ them back into their original single byte form. It does allow
+ processing of src to continue, however, which, since there is no
+ way to signal decoding errors, seems like the best we can do.
+
+ */
+ *ptr = L'\xdc80' | *pmbs;
+ bytes = 1;
+ }
+
if (bytes > 0)
{
pmbs += bytes;