Skip to content

Commit

Permalink
Fix the string unescape logic for multiple escaped characters. Add
Browse files Browse the repository at this point in the history
a unit test.


git-svn-id: https://svn.apache.org/repos/asf/apr/apr/trunk@1835360 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information
minfrin committed Jul 8, 2018
1 parent 759826d commit 124da28
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 13 deletions.
26 changes: 13 additions & 13 deletions json/apr_json_decode.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ static apr_status_t apr_json_decode_string(apr_json_scanner_t * self, apr_json_s
const char *p = self->p;
const char *e;
char *q;
apr_size_t len;

if (self->p >= self->e) {
status = APR_EOF;
Expand All @@ -92,7 +93,7 @@ static apr_status_t apr_json_decode_string(apr_json_scanner_t * self, apr_json_s
self->p++; /* eat the leading '"' */

/* advance past the \ " */
string.len = 0;
len = 0;
for (p = self->p, e = self->e; p < e;) {
if (*p == '"')
break;
Expand All @@ -108,21 +109,20 @@ static apr_status_t apr_json_decode_string(apr_json_scanner_t * self, apr_json_s
goto out;
}
p += 5;
string.len += 4;/* an UTF-8 character spans at most 4 bytes */
break;
len += 4;/* an UTF-8 character spans at most 4 bytes */
}
else {
string.len++;
len++;
p++;
}
}
else {
string.len++;
len++;
p++;
}
}

string.p = q = apr_pcalloc(self->pool, string.len + 1);
string.p = q = apr_pcalloc(self->pool, len + 1);
e = p;

#define VALIDATE_UTF8_SUCCEEDING_BYTE(p) \
Expand All @@ -139,15 +139,14 @@ static apr_status_t apr_json_decode_string(apr_json_scanner_t * self, apr_json_s
case 'u':
/* THIS IS REQUIRED TO BE A 4 DIGIT HEX NUMBER */
{
int cp = 0;
while (p < e) {
int d = hex_to_int(*p);
int i, d, cp = 0;
for (i = 0, p++; i < 4 && p < e; i++, p++) {
d = hex_to_int(*p);
if (d < 0) {
status = APR_BADCH;
goto out;
}
cp = (cp << 4) | d;
p++;
}
if (cp >= 0xd800 && cp < 0xdc00) {
/* surrogate pair */
Expand All @@ -160,14 +159,13 @@ static apr_status_t apr_json_decode_string(apr_json_scanner_t * self, apr_json_s
status = APR_BADCH;
goto out;
}
while (p < e) {
int d = hex_to_int(*p);
for (i = 0, p += 2; i < 4 && p < e; i++, p++) {
d = hex_to_int(*p);
if (d < 0) {
status = APR_BADCH;
goto out;
}
sc = (sc << 4) | d;
p++;
}
cp = ((cp & 0x3ff) << 10) | (sc & 0x3ff);
if ((cp >= 0xd800 && cp < 0xe000) || (cp >= 0x110000)) {
Expand Down Expand Up @@ -340,6 +338,8 @@ static apr_status_t apr_json_decode_string(apr_json_scanner_t * self, apr_json_s
}
#undef VALIDATE_UTF8_SUCCEEDING_BYTE
p++; /* eat the trailing '"' */
*q = 0;
string.len = q - string.p;
*retval = string;
out:
self->p = p;
Expand Down
23 changes: 23 additions & 0 deletions test/testjson.c
Original file line number Diff line number Diff line change
Expand Up @@ -127,13 +127,36 @@ static void test_json_eof(abts_case * tc, void *data)

}

static void test_json_string(abts_case * tc, void *data)
{
apr_json_value_t *json = NULL;
apr_status_t status;
const char *src;
apr_off_t offset = 0;

/* "턞\"\t/\b\f\n\r\t"; */
const unsigned char expected[] = {237, 132, 158, 34, 9, 47, 8, 12, 10, 13, 9, 0};

src = "\"\\uD834\\uDD1E\\\"\\t\\/\\b\\f\\n\\r\\t\"";

status = apr_json_decode(&json, src, APR_JSON_VALUE_STRING, &offset,
APR_JSON_FLAGS_WHITESPACE, 10, p);

ABTS_INT_EQUAL(tc, APR_SUCCESS, status);
ABTS_INT_EQUAL(tc, APR_JSON_STRING, json->type);

ABTS_ASSERT(tc, "check for string unescape match",
(memcmp(expected, json->value.string.p, json->value.string.len) == 0));
}

abts_suite *testjson(abts_suite * suite)
{
suite = ADD_SUITE(suite);

abts_run_test(suite, test_json_identity, NULL);
abts_run_test(suite, test_json_level, NULL);
abts_run_test(suite, test_json_eof, NULL);
abts_run_test(suite, test_json_string, NULL);

return suite;
}

0 comments on commit 124da28

Please sign in to comment.