From: VMware, Inc <> Date: Mon, 20 Dec 2010 21:43:16 +0000 (-0800) Subject: lib/misc: expose a useful function X-Git-Tag: 2010.12.19-339835~60 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=48fb68fa20f5b640911ce6fb41956f0a91da1b4c;p=thirdparty%2Fopen-vm-tools.git lib/misc: expose a useful function There are some serious problems with lib/unicode; exposing this function will make the fixes rather easy and fairly obvious. Signed-off-by: Marcelo Vanzin --- diff --git a/open-vm-tools/lib/include/codeset.h b/open-vm-tools/lib/include/codeset.h index 317dbbda5..236c6c876 100644 --- a/open-vm-tools/lib/include/codeset.h +++ b/open-vm-tools/lib/include/codeset.h @@ -378,6 +378,11 @@ Bool CodeSet_UTF32ToUTF8(const char *utf32, int CodeSet_LengthInCodePoints(const char *utf8); +int CodeSet_GetUtf8(const char *string, + const char *end, + uint32 *uchar); + + /* *----------------------------------------------------------------------------- * diff --git a/open-vm-tools/lib/misc/codeset.c b/open-vm-tools/lib/misc/codeset.c index 79d80ad13..0a3f194d6 100644 --- a/open-vm-tools/lib/misc/codeset.c +++ b/open-vm-tools/lib/misc/codeset.c @@ -1654,6 +1654,101 @@ CodeSet_Validate(const char *buf, // IN: the string } +/* + *----------------------------------------------------------------------------- + * + * CodeSet_GetUtf8 -- + * + * Parse the next UTF-8 sequence. + * + * Results: + * 0 on failure. + * Length of sequence and Unicode character in *uchar on success. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +int +CodeSet_GetUtf8(const char *string, // IN: string + const char *end, // IN: end of string + uint32 *uchar) // OUT: the Unicode character +{ + uint8 *p = (uint8 *) string; + uint8 *e; + uint32 c; + int len; + ASSERT(string < end); + + c = *p; + + if (c < 0x80) { + // ASCII: U+0000 - U+007F: 1 byte of UTF-8. + len = 1; + goto out; + } + + if ((c < 0xc2) || (c > 0xf4)) { + // 0x81 to 0xbf are not valid first bytes + // 0xc0 and 0xc1 cannot appear in UTF-8, see below + // leading char can not be > 0xf4, illegal as well + return 0; + } + + if (c < 0xe0) { + // U+0080 - U+07FF: 2 bytes of UTF-8. + c -= 0xc0; + len = 2; + } else if (c < 0xf0) { + // U+0800 - U+FFFF: 3 bytes of UTF-8. + c -= 0xe0; + len = 3; + } else { + // U+10000 - U+10FFFF: 4 bytes of UTF-8. + c -= 0xf0; + len = 4; + } + + if ((e = p + len) > (uint8 *) end) { + // input too short + return 0; + } + + while (++p < e) { + if ((*p & 0xc0) != 0x80) { + // bad trailing byte + return 0; + } + c <<= 6; + c += *p - 0x80; + } + + /* + * Enforce shortest encoding. + * UTF-8 mandates that shortest possible encoding is used, + * as otherwise doing UTF-8 => anything => UTF-8 could bypass some + * important tests, like '/' for path separator or \0 for string + * termination. + * + * This test does not work for len == 2, but that case is handled + * by requiring the first byte to be 0xc2 or greater (see above). + */ + + if (c < 1U << (len * 5 - 4)) { + return 0; + } + +out: + if (uchar != NULL) { + *uchar = c; + } + + return len; +} + + /* *----------------------------------------------------------------------------- * @@ -1688,7 +1783,7 @@ CodeSet_LengthInCodePoints(const char *utf8) // IN: while (p < end) { uint32 utf32; - uint32 len = CodeSetOldGetUtf8(p, end, &utf32); + uint32 len = CodeSet_GetUtf8(p, end, &utf32); if (len == 0) { return -1; @@ -1751,7 +1846,7 @@ CodeSet_UTF8ToUTF32(const char *utf8, // IN: *utf32 = (char *) ptr; while (p < end) { - p += CodeSetOldGetUtf8(p, end, ptr++); + p += CodeSet_GetUtf8(p, end, ptr++); } *ptr = 0; diff --git a/open-vm-tools/lib/misc/codesetOld.c b/open-vm-tools/lib/misc/codesetOld.c index cdf567968..b56614a7f 100644 --- a/open-vm-tools/lib/misc/codesetOld.c +++ b/open-vm-tools/lib/misc/codesetOld.c @@ -81,100 +81,6 @@ static Bool CodeSetOldIso88591ToUtf8Db(char const *bufIn, size_t sizeIn, unsigned int flags, DynBuf *db); #endif -/* - *----------------------------------------------------------------------------- - * - * CodeSetOldGetUtf8 -- - * - * Parse the next UTF-8 sequence. - * - * Results: - * 0 on failure. - * Length of sequence and Unicode character in *uchar on success. - * - * Side effects: - * None. - * - *----------------------------------------------------------------------------- - */ - -int -CodeSetOldGetUtf8(const char *string, // IN: string - const char *end, // IN: end of string - uint32 *uchar) // OUT: the Unicode character -{ - uint8 *p = (uint8 *) string; - uint8 *e; - uint32 c; - int len; - ASSERT(string < end); - - c = *p; - - if (c < 0x80) { - // ASCII: U+0000 - U+007F: 1 byte of UTF-8. - len = 1; - goto out; - } - - if ((c < 0xc2) || (c > 0xf4)) { - // 0x81 to 0xbf are not valid first bytes - // 0xc0 and 0xc1 cannot appear in UTF-8, see below - // leading char can not be > 0xf4, illegal as well - return 0; - } - - if (c < 0xe0) { - // U+0080 - U+07FF: 2 bytes of UTF-8. - c -= 0xc0; - len = 2; - } else if (c < 0xf0) { - // U+0800 - U+FFFF: 3 bytes of UTF-8. - c -= 0xe0; - len = 3; - } else { - // U+10000 - U+10FFFF: 4 bytes of UTF-8. - c -= 0xf0; - len = 4; - } - - if ((e = p + len) > (uint8 *) end) { - // input too short - return 0; - } - - while (++p < e) { - if ((*p & 0xc0) != 0x80) { - // bad trailing byte - return 0; - } - c <<= 6; - c += *p - 0x80; - } - - /* - * Enforce shortest encoding. - * UTF-8 mandates that shortest possible encoding is used, - * as otherwise doing UTF-8 => anything => UTF-8 could bypass some - * important tests, like '/' for path separator or \0 for string - * termination. - * - * This test does not work for len == 2, but that case is handled - * by requiring the first byte to be 0xc2 or greater (see above). - */ - - if (c < 1U << (len * 5 - 4)) { - return 0; - } - -out: - if (uchar != NULL) { - *uchar = c; - } - - return len; -} - #if defined(CURRENT_IS_UTF8) || defined(_WIN32) /* @@ -301,7 +207,7 @@ CodeSetOldUtf8ToUtf16leDb(const char *bufIn, // IN: while (bufIn < bufEnd) { size_t neededSize; uint32 uniChar; - int n = CodeSetOldGetUtf8(bufIn, bufEnd, &uniChar); + int n = CodeSet_GetUtf8(bufIn, bufEnd, &uniChar); if (n <= 0) { return FALSE; @@ -2123,7 +2029,7 @@ CodeSetOld_Utf8ToAsciiDb(char const *bufIn, // IN: if ((flags & CSGTG_TRANSLIT) != 0) { DynBuf_Append(db, "\x1a", 1); } - if ((n = CodeSetOldGetUtf8((char *)p, (char *)end, NULL)) > 0) { + if ((n = CodeSet_GetUtf8((char *) p, (char *) end, NULL)) > 0) { p += n - 1; } last = p + 1; diff --git a/open-vm-tools/lib/misc/codesetOld.h b/open-vm-tools/lib/misc/codesetOld.h index 9c99cd4ef..bf640a547 100644 --- a/open-vm-tools/lib/misc/codesetOld.h +++ b/open-vm-tools/lib/misc/codesetOld.h @@ -206,10 +206,4 @@ CodeSetOld_Validate(const char *buf, // IN: the string Bool CodeSetOld_Init(const char *dataDir); // UNUSED -int -CodeSetOldGetUtf8(const char *string, // IN: string - const char *end, // IN: end of string - uint32 *uchar); // OUT: the Unicode character - - #endif /* __CODESET_OLD_H__ */