diff options
| -rw-r--r-- | src/bplist.c | 41 |
1 files changed, 37 insertions, 4 deletions
diff --git a/src/bplist.c b/src/bplist.c index 5db7096..d825fc8 100644 --- a/src/bplist.c +++ b/src/bplist.c | |||
| @@ -286,15 +286,38 @@ static plist_t parse_string_node(char *bnode, uint64_t size) | |||
| 286 | static char *plist_utf16_to_utf8(uint16_t *unistr, long len, long *items_read, long *items_written) | 286 | static char *plist_utf16_to_utf8(uint16_t *unistr, long len, long *items_read, long *items_written) |
| 287 | { | 287 | { |
| 288 | if (!unistr || (len <= 0)) return NULL; | 288 | if (!unistr || (len <= 0)) return NULL; |
| 289 | char *outbuf = (char*)malloc(3*(len+1)); | 289 | char *outbuf = (char*)malloc(4*(len+1)); |
| 290 | int p = 0; | 290 | int p = 0; |
| 291 | int i = 0; | 291 | int i = 0; |
| 292 | 292 | ||
| 293 | uint16_t wc; | 293 | uint16_t wc; |
| 294 | uint32_t w; | ||
| 295 | int read_lead_surrogate = 0; | ||
| 294 | 296 | ||
| 295 | while (i < len) { | 297 | while (i < len) { |
| 296 | wc = unistr[i++]; | 298 | wc = unistr[i++]; |
| 297 | if (wc >= 0x800) { | 299 | if (wc >= 0xD800 && wc <= 0xDBFF) { |
| 300 | if (!read_lead_surrogate) { | ||
| 301 | read_lead_surrogate = 1; | ||
| 302 | w = 0x010000 + ((wc & 0x3FF) << 10); | ||
| 303 | } else { | ||
| 304 | // This is invalid, the next 16 bit char should be a trail surrogate. | ||
| 305 | // Handling error by skipping. | ||
| 306 | read_lead_surrogate = 0; | ||
| 307 | } | ||
| 308 | } else if (wc >= 0xDC00 && wc <= 0xDFFF) { | ||
| 309 | if (read_lead_surrogate) { | ||
| 310 | read_lead_surrogate = 0; | ||
| 311 | w = w | (wc & 0x3FF); | ||
| 312 | outbuf[p++] = (char)(0xF0 + ((w >> 18) & 0x3)); | ||
| 313 | outbuf[p++] = (char)(0x80 + ((w >> 12) & 0x3F)); | ||
| 314 | outbuf[p++] = (char)(0x80 + ((w >> 6) & 0x3F)); | ||
| 315 | outbuf[p++] = (char)(0x80 + (w & 0x3F)); | ||
| 316 | } else { | ||
| 317 | // This is invalid. A trail surrogate should always follow a lead surrogate. | ||
| 318 | // Handling error by skipping | ||
| 319 | } | ||
| 320 | } else if (wc >= 0x800) { | ||
| 298 | outbuf[p++] = (char)(0xE0 + ((wc >> 12) & 0xF)); | 321 | outbuf[p++] = (char)(0xE0 + ((wc >> 12) & 0xF)); |
| 299 | outbuf[p++] = (char)(0x80 + ((wc >> 6) & 0x3F)); | 322 | outbuf[p++] = (char)(0x80 + ((wc >> 6) & 0x3F)); |
| 300 | outbuf[p++] = (char)(0x80 + (wc & 0x3F)); | 323 | outbuf[p++] = (char)(0x80 + (wc & 0x3F)); |
| @@ -988,19 +1011,29 @@ static int is_ascii_string(char* s, int len) | |||
| 988 | 1011 | ||
| 989 | uint16_t *plist_utf8_to_utf16(char *unistr, long size, long *items_read, long *items_written) | 1012 | uint16_t *plist_utf8_to_utf16(char *unistr, long size, long *items_read, long *items_written) |
| 990 | { | 1013 | { |
| 991 | uint16_t *outbuf = (uint16_t*)malloc((size+1)*sizeof(uint16_t)); | 1014 | uint16_t *outbuf = (uint16_t*)malloc(((size*2)+1)*sizeof(uint16_t)); |
| 992 | int p = 0; | 1015 | int p = 0; |
| 993 | int i = 0; | 1016 | int i = 0; |
| 994 | 1017 | ||
| 995 | unsigned char c0; | 1018 | unsigned char c0; |
| 996 | unsigned char c1; | 1019 | unsigned char c1; |
| 997 | unsigned char c2; | 1020 | unsigned char c2; |
| 1021 | unsigned char c3; | ||
| 1022 | |||
| 1023 | uint32_t w; | ||
| 998 | 1024 | ||
| 999 | while (i < size) { | 1025 | while (i < size) { |
| 1000 | c0 = unistr[i]; | 1026 | c0 = unistr[i]; |
| 1001 | c1 = (i < size-1) ? unistr[i+1] : 0; | 1027 | c1 = (i < size-1) ? unistr[i+1] : 0; |
| 1002 | c2 = (i < size-2) ? unistr[i+2] : 0; | 1028 | c2 = (i < size-2) ? unistr[i+2] : 0; |
| 1003 | if ((c0 >= 0xE0) && (i < size-2) && (c1 >= 0x80) && (c2 >= 0x80)) { | 1029 | c3 = (i < size-3) ? unistr[i+3] : 0; |
| 1030 | if ((c0 >= 0xF0) && (i < size-3) && (c1 >= 0x80) && (c2 >= 0x80) && (c3 >= 0x80)) { | ||
| 1031 | // 4 byte sequence. Need to generate UTF-16 surrogate pair | ||
| 1032 | w = ((((c0 & 7) << 18) + ((c1 & 0x3F) << 12) + ((c2 & 0x3F) << 6) + (c3 & 0x3F)) & 0x0FFFFF) - 0x010000; | ||
| 1033 | outbuf[p++] = 0xD800 + (w >> 10); | ||
| 1034 | outbuf[p++] = 0xDC00 + (w & 0x3FF); | ||
| 1035 | i+=4; | ||
| 1036 | } else if ((c0 >= 0xE0) && (i < size-2) && (c1 >= 0x80) && (c2 >= 0x80)) { | ||
| 1004 | // 3 byte sequence | 1037 | // 3 byte sequence |
| 1005 | outbuf[p++] = ((c2 & 0x3F) + ((c1 & 3) << 6)) + (((c1 >> 2) & 15) << 8) + ((c0 & 15) << 12); | 1038 | outbuf[p++] = ((c2 & 0x3F) + ((c1 & 3) << 6)) + (((c1 >> 2) & 15) << 8) + ((c0 & 15) << 12); |
| 1006 | i+=3; | 1039 | i+=3; |
