json: escape and unescape invalid unicode chars

This commit is contained in:
Wim Taymans 2021-03-11 19:03:42 +01:00
parent 22f6e8e36d
commit f41de50b28
2 changed files with 25 additions and 2 deletions

View file

@ -324,7 +324,18 @@ static inline int spa_json_parse_string(const char *val, int len, char *result)
*result++ = '\t';
else if (*p == 'f')
*result++ = '\f';
else
else if (*p == 'u') {
char *end;
uint16_t v = strtol(p+1, &end, 16);
if (p+1 == end) {
*result++ = *p;
} else {
p = end-1;
if (v > 0xff)
*result++ = (v >> 8) & 0xff;
*result++ = v & 0xff;
}
} else
*result++ = *p;
} else if (*p == '\"') {
break;
@ -348,6 +359,7 @@ static inline int spa_json_get_string(struct spa_json *iter, char *res, int maxl
static inline int spa_json_encode_string(char *str, int size, const char *val)
{
int len = 0;
static const char hex[] = { "0123456789abcdef" };
#define __PUT(c) { if (len < size) *str++ = c; len++; }
__PUT('"');
while (*val) {
@ -371,7 +383,13 @@ static inline int spa_json_encode_string(char *str, int size, const char *val)
__PUT('\\'); __PUT('"');
break;
default:
__PUT(*val);
if (*val > 0 && *val < 0x20) {
__PUT('\\'); __PUT('u');
__PUT('0'); __PUT('0');
__PUT(hex[((*val)>>4)&0xf]); __PUT(hex[(*val)&0xf]);
} else {
__PUT(*val);
}
break;
}
val++;

View file

@ -154,6 +154,7 @@ static void test_encode(void)
char dst[1024];
char dst4[4];
char dst6[6];
char result[1024];
spa_assert(spa_json_encode_string(dst, sizeof(dst), "test") == 6);
spa_assert(strcmp(dst, "\"test\"") == 0);
spa_assert(spa_json_encode_string(dst4, sizeof(dst4), "test") == 6);
@ -162,6 +163,10 @@ static void test_encode(void)
spa_assert(strncmp(dst6, "\"test\"", 6) == 0);
spa_assert(spa_json_encode_string(dst, sizeof(dst), "test\"\n\r \t\b\f\'") == 20);
spa_assert(strcmp(dst, "\"test\\\"\\n\\r \\t\\b\\f'\"") == 0);
spa_assert(spa_json_encode_string(dst, sizeof(dst), "\x04\x05\x1f\x20\x01\x7f\x90") == 29);
spa_assert(strcmp(dst, "\"\\u0004\\u0005\\u001f \\u0001\x7f\x90\"") == 0);
spa_assert(spa_json_parse_string(dst, sizeof(dst), result) == 1);
spa_assert(strcmp(result, "\x04\x05\x1f\x20\x01\x7f\x90") == 0);
}
int main(int argc, char *argv[])