summaryrefslogtreecommitdiff
path: root/devices/vector/gdevpdfe.c
diff options
context:
space:
mode:
Diffstat (limited to 'devices/vector/gdevpdfe.c')
-rw-r--r--devices/vector/gdevpdfe.c41
1 files changed, 31 insertions, 10 deletions
diff --git a/devices/vector/gdevpdfe.c b/devices/vector/gdevpdfe.c
index db0c0b883..35ebdee01 100644
--- a/devices/vector/gdevpdfe.c
+++ b/devices/vector/gdevpdfe.c
@@ -359,6 +359,7 @@ static const char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC
static int gs_ConvertUTF16(unsigned char *UTF16, size_t UTF16Len, unsigned char **UTF8Start, int UTF8Len)
{
size_t i, bytes = 0;
+ uint32_t U32 = 0;
unsigned short U16;
unsigned char *UTF8 = *UTF8Start;
unsigned char *UTF8End = UTF8 + UTF8Len;
@@ -372,21 +373,38 @@ static int gs_ConvertUTF16(unsigned char *UTF16, size_t UTF16Len, unsigned char
U16 += *UTF16++;
if (U16 >= 0xD800 && U16 <= 0xDBFF) {
- return gs_note_error(gs_error_rangecheck);
- }
- if (U16 >= 0xDC00 && U16 <= 0xDFFF) {
- return gs_note_error(gs_error_rangecheck);
- }
+ /* Ensure at least two bytes of input left */
+ if (i == (UTF16Len / sizeof(short)) - 1)
+ return gs_note_error(gs_error_rangecheck);
+
+ U32 += (U16 & 0x3FF) << 10;
+ U16 = (*(UTF16++) << 8);
+ U16 += *(UTF16++);
+ i++;
- if(U16 < 0x80) {
- bytes = 1;
+ /* Ensure a high order surrogate is followed by a low order surrogate */
+ if (U16 < 0xDC00 || U16 > 0xDFFF)
+ return gs_note_error(gs_error_rangecheck);
+
+ U32 += (U16 & 0x3FF) | 0x10000;
+ bytes = 4;
} else {
- if (U16 < 0x800) {
- bytes = 2;
+ if (U16 >= 0xDC00 && U16 <= 0xDFFF) {
+ /* We got a low order surrogate without a preceding high-order */
+ return gs_note_error(gs_error_rangecheck);
+ }
+
+ if(U16 < 0x80) {
+ bytes = 1;
} else {
- bytes = 3;
+ if (U16 < 0x800) {
+ bytes = 2;
+ } else {
+ bytes = 3;
+ }
}
}
+
if (UTF8 + bytes > UTF8End)
return gs_note_error(gs_error_VMerror);
@@ -394,6 +412,9 @@ static int gs_ConvertUTF16(unsigned char *UTF16, size_t UTF16Len, unsigned char
UTF8 += bytes;
switch(bytes) {
+ case 4:
+ *--UTF8 = (unsigned char)((U32 | 0x80) & 0xBF);
+ U16 = U32 >> 6;
case 3:
*--UTF8 = (unsigned char)((U16 | 0x80) & 0xBF);
U16 >>= 6;