Called when index pointing to beginning of UTF-16 code escape: \uXXXX * \u is guaranteed to exist, but the remaining hex characters may be * missing. * Translate to UTF-8 and append to temporary token string. * Must advance index to the next character to be processed. * Returns: 0 success * -1 error */
| 1098 | * -1 error |
| 1099 | */ |
| 1100 | static int json_append_unicode_escape(json_parse_t *json) |
| 1101 | { |
| 1102 | char utf8[4]; /* Surrogate pairs require 4 UTF-8 bytes */ |
| 1103 | int codepoint; |
| 1104 | int surrogate_low; |
| 1105 | int len; |
| 1106 | int escape_len = 6; |
| 1107 | |
| 1108 | /* Fetch UTF-16 code unit */ |
| 1109 | codepoint = decode_hex4(json->ptr + 2); |
| 1110 | if (codepoint < 0) |
| 1111 | return -1; |
| 1112 | |
| 1113 | /* UTF-16 surrogate pairs take the following 2 byte form: |
| 1114 | * 11011 x yyyyyyyyyy |
| 1115 | * When x = 0: y is the high 10 bits of the codepoint |
| 1116 | * x = 1: y is the low 10 bits of the codepoint |
| 1117 | * |
| 1118 | * Check for a surrogate pair (high or low) */ |
| 1119 | if ((codepoint & 0xF800) == 0xD800) { |
| 1120 | /* Error if the 1st surrogate is not high */ |
| 1121 | if (codepoint & 0x400) |
| 1122 | return -1; |
| 1123 | |
| 1124 | /* Ensure the next code is a unicode escape */ |
| 1125 | if (*(json->ptr + escape_len) != '\\' || |
| 1126 | *(json->ptr + escape_len + 1) != 'u') { |
| 1127 | return -1; |
| 1128 | } |
| 1129 | |
| 1130 | /* Fetch the next codepoint */ |
| 1131 | surrogate_low = decode_hex4(json->ptr + 2 + escape_len); |
| 1132 | if (surrogate_low < 0) |
| 1133 | return -1; |
| 1134 | |
| 1135 | /* Error if the 2nd code is not a low surrogate */ |
| 1136 | if ((surrogate_low & 0xFC00) != 0xDC00) |
| 1137 | return -1; |
| 1138 | |
| 1139 | /* Calculate Unicode codepoint */ |
| 1140 | codepoint = (codepoint & 0x3FF) << 10; |
| 1141 | surrogate_low &= 0x3FF; |
| 1142 | codepoint = (codepoint | surrogate_low) + 0x10000; |
| 1143 | escape_len = 12; |
| 1144 | } |
| 1145 | |
| 1146 | /* Convert codepoint to UTF-8 */ |
| 1147 | len = codepoint_to_utf8(utf8, codepoint); |
| 1148 | if (!len) |
| 1149 | return -1; |
| 1150 | |
| 1151 | /* Append bytes and advance parse index */ |
| 1152 | strbuf_append_mem_unsafe(json->tmp, utf8, len); |
| 1153 | json->ptr += escape_len; |
| 1154 | |
| 1155 | return 0; |
| 1156 | } |
| 1157 |
no test coverage detected