json: fix \uXXXX parsing

We need exactly 4 hex characters, everything else is refused. We
also copy those characters directly to the output string without
assuming any encoding.

See #2337
This commit is contained in:
Wim Taymans 2022-04-26 11:01:33 +02:00
parent d9871f36c1
commit f2cdb15e0c
2 changed files with 10 additions and 7 deletions

View file

@ -355,15 +355,15 @@ static inline int spa_json_parse_stringn(const char *val, int len, char *result,
else if (*p == 'f') else if (*p == 'f')
*result++ = '\f'; *result++ = '\f';
else if (*p == 'u') { else if (*p == 'u') {
char *end; uint8_t v[2];
uint16_t v = strtol(p+1, &end, 16); if (p + 5 > val + len ||
if (p+1 == end) { sscanf(p+1, "%02hhx%02hhx", &v[0], &v[1]) != 2) {
*result++ = *p; *result++ = *p;
} else { } else {
p = end-1; p += 4;
if (v > 0xff) if (v[0] != 0)
*result++ = (v >> 8) & 0xff; *result++ = v[0];
*result++ = v & 0xff; *result++ = v[1];
} }
} else } else
*result++ = *p; *result++ = *p;

View file

@ -176,6 +176,9 @@ PWTEST(json_encode)
pwtest_str_eq(dst, "\"\\u0004\\u0005\\u001f \\u0001\x7f\x90\""); pwtest_str_eq(dst, "\"\\u0004\\u0005\\u001f \\u0001\x7f\x90\"");
pwtest_int_eq(spa_json_parse_stringn(dst, sizeof(dst), result, sizeof(result)), 1); pwtest_int_eq(spa_json_parse_stringn(dst, sizeof(dst), result, sizeof(result)), 1);
pwtest_str_eq(result, "\x04\x05\x1f\x20\x01\x7f\x90"); pwtest_str_eq(result, "\x04\x05\x1f\x20\x01\x7f\x90");
strcpy(dst, "\"\\u03b2a\"");
pwtest_int_eq(spa_json_parse_stringn(dst, sizeof(dst), result, sizeof(result)), 1);
pwtest_str_eq(result, "\003\262a");
return PWTEST_PASS; return PWTEST_PASS;
} }