decode ~1/~0 escapes when setting an object member in json_pointer

This commit is contained in:
Javid Khan
2026-08-22 12:01:01 +05:30
parent d17ad9d186
commit dcdea4e906
3 changed files with 38 additions and 9 deletions
+18 -9
View File
@@ -141,19 +141,28 @@ static int json_pointer_set_single_path(struct json_object *parent, const char *
return set_cb(parent, NULL, idx, value, priv);
}
/* path replacements should have been done in json_pointer_get_single_path(),
* and we should still be good here
*/
if (json_object_is_type(parent, json_type_object))
{
/* Unlike the getter, which decodes the reference token in
* json_pointer_get_single_path(), nothing had decoded the '~1'/'~0'
* escapes on the way here, so a member whose name contains '/' or '~'
* was addressed under its still-escaped spelling. Decode a copy per
* RFC 6901 (first '~1' then '~0') before using it as the key.
*/
char *key = strdup(path);
int rc;
if (key == NULL)
return -1;
string_replace_all_occurrences_with_char(key, "~1", '/');
string_replace_all_occurrences_with_char(key, "~0", '~');
if (cb_handles_obj)
{
return set_cb(parent, path, (size_t)-1, value, priv);
}
rc = set_cb(parent, key, (size_t)-1, value, priv);
else
{
return json_object_object_add(parent, path, value);
}
rc = json_object_object_add(parent, key, value);
free(key);
return rc;
}
/* Getting here means that we tried to "dereference" a primitive JSON type
+19
View File
@@ -268,6 +268,25 @@ static void test_example_set(void)
printf("PASSED - SET - Final JSON is: %s\n", json_object_get_string(jo1));
json_object_put(jo2);
/* RFC 6901 escapes must be decoded on the set path too, just as the
* getter does, so "/a~1b" addresses the member "a/b" and "/m~0n"
* addresses "m~n" rather than creating keys spelled "a~1b"/"m~0n". */
{
struct json_object *esc = json_tokener_parse("{ 'a/b': 1, 'm~n': 2 }");
struct json_object *v = NULL;
assert(0 == json_pointer_set(&esc, "/a~1b", json_object_new_int(11)));
assert(0 == json_pointer_setf(&esc, json_object_new_int(22), "/m~0n"));
assert(0 == json_pointer_get(esc, "/a~1b", &v));
assert(11 == json_object_get_int(v));
assert(0 == json_pointer_get(esc, "/m~0n", &v));
assert(22 == json_object_get_int(v));
assert(NULL == json_object_object_get(esc, "a~1b"));
assert(NULL == json_object_object_get(esc, "m~0n"));
assert(2 == json_object_object_length(esc));
printf("PASSED - SET - escaped keys /a~1b and /m~0n\n");
json_object_put(esc);
}
assert(0 == json_pointer_set(&jo1, "", json_object_new_int(10)));
assert(10 == json_object_get_int(jo1));
printf("%s\n", json_object_get_string(jo1));
+1
View File
@@ -29,6 +29,7 @@ PASSED - SET - /fug/gaw == [0,2,3]
PASSED - SET - /fug/gaw == [0,2,3,4]
PASSED - SET - / == 9
PASSED - SET - Final JSON is: { "foo": [ "bar", "cod" ], "": 9, "a\/b": 1, "c%d": 2, "e^f": 3, "g|h": 4, "i\\j": 5, "k\"l": 6, " ": 7, "m~n": 8, "fud": { "gaw": [ 0, 2, 3, 4 ] } }
PASSED - SET - escaped keys /a~1b and /m~0n
10
PASSED - SET - LOADED TEST JSON
{ "foo": [ "bar", "baz" ], "": 0, "a\/b": 1, "c%d": 2, "e^f": 3, "g|h": 4, "i\\j": 5, "k\"l": 6, " ": 7, "m~n": 8 }