mirror of
https://github.com/json-c/json-c.git
synced 2026-03-24 07:29:07 +08:00
general callback, safer API & related tests
- Changed json_pointer_set_with_array_cb to json_pointer_set_with_cb, related cb updated - Added tests(test_safe_json_pointer_set.*) for new-exported funcs, also updated cmake & meson Signed-off-by: lone <lonechan314@qq.com>
This commit is contained in:
@@ -120,15 +120,9 @@ static int json_pointer_get_single_path(struct json_object *obj, char *path,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int json_object_array_put_idx_cb(struct json_object *parent, size_t idx,
|
||||
struct json_object *value, void *priv)
|
||||
{
|
||||
return json_object_array_put_idx(parent, idx, value);
|
||||
}
|
||||
|
||||
static int json_pointer_set_single_path(struct json_object *parent, const char *path,
|
||||
struct json_object *value,
|
||||
json_pointer_array_set_cb array_set_cb, void *priv)
|
||||
json_pointer_set_cb set_cb, int cb_handles_obj, void *priv)
|
||||
{
|
||||
if (json_object_is_type(parent, json_type_array))
|
||||
{
|
||||
@@ -138,14 +132,23 @@ static int json_pointer_set_single_path(struct json_object *parent, const char *
|
||||
return json_object_array_add(parent, value);
|
||||
if (!is_valid_index(path, &idx))
|
||||
return -1;
|
||||
return array_set_cb(parent, idx, value, priv);
|
||||
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))
|
||||
return json_object_object_add(parent, path, value);
|
||||
{
|
||||
if (cb_handles_obj)
|
||||
{
|
||||
return set_cb(parent, path, (size_t)-1, value, priv);
|
||||
}
|
||||
else
|
||||
{
|
||||
return json_object_object_add(parent, path, value);
|
||||
}
|
||||
}
|
||||
|
||||
/* Getting here means that we tried to "dereference" a primitive JSON type
|
||||
* (like string, int, bool).i.e. add a sub-object to it
|
||||
@@ -298,9 +301,9 @@ out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
int json_pointer_set_with_array_cb(struct json_object **obj, const char *path,
|
||||
int json_pointer_set_with_cb(struct json_object **obj, const char *path,
|
||||
struct json_object *value,
|
||||
json_pointer_array_set_cb array_set_cb, void *priv)
|
||||
json_pointer_set_cb set_cb, int cb_handles_obj, void *priv)
|
||||
{
|
||||
const char *endp;
|
||||
char *path_copy = NULL;
|
||||
@@ -330,7 +333,7 @@ int json_pointer_set_with_array_cb(struct json_object **obj, const char *path,
|
||||
if ((endp = strrchr(path, '/')) == path)
|
||||
{
|
||||
path++;
|
||||
return json_pointer_set_single_path(*obj, path, value, array_set_cb, priv);
|
||||
return json_pointer_set_single_path(*obj, path, value, set_cb, cb_handles_obj, priv);
|
||||
}
|
||||
|
||||
/* pass a working copy to the recursive call */
|
||||
@@ -347,12 +350,21 @@ int json_pointer_set_with_array_cb(struct json_object **obj, const char *path,
|
||||
return rc;
|
||||
|
||||
endp++;
|
||||
return json_pointer_set_single_path(set, endp, value, array_set_cb, priv);
|
||||
return json_pointer_set_single_path(set, endp, value, set_cb, cb_handles_obj, priv);
|
||||
}
|
||||
|
||||
static int default_put_cb(struct json_object *parent, const char *key, size_t idx,
|
||||
struct json_object *value, void *priv)
|
||||
{
|
||||
if (key == NULL)
|
||||
return json_object_array_put_idx(parent, idx, value);
|
||||
else
|
||||
return json_object_object_add(parent, key, value);
|
||||
}
|
||||
|
||||
int json_pointer_set(struct json_object **obj, const char *path, struct json_object *value)
|
||||
{
|
||||
return json_pointer_set_with_array_cb(obj, path, value, json_object_array_put_idx_cb, NULL);
|
||||
return json_pointer_set_with_cb(obj, path, value, default_put_cb, 1, NULL);
|
||||
}
|
||||
|
||||
int json_pointer_setf(struct json_object **obj, struct json_object *value, const char *path_fmt,
|
||||
@@ -407,8 +419,7 @@ int json_pointer_setf(struct json_object **obj, struct json_object *value, const
|
||||
|
||||
set_single_path:
|
||||
endp++;
|
||||
rc = json_pointer_set_single_path(set, endp, value,
|
||||
json_object_array_put_idx_cb, NULL);
|
||||
rc = json_pointer_set_single_path(set, endp, value, default_put_cb, 1, NULL);
|
||||
out:
|
||||
free(path_copy);
|
||||
return rc;
|
||||
@@ -420,33 +431,45 @@ int json_pointer_set_with_limit_index(struct json_object **obj, const char *path
|
||||
// -1 means no limits
|
||||
if (limit_index == (size_t)-1)
|
||||
{
|
||||
return json_pointer_set_with_array_cb(obj, path, value, json_object_array_put_idx_cb, NULL);
|
||||
return json_pointer_set_with_cb(obj, path, value, default_put_cb, 1, NULL);
|
||||
}
|
||||
return json_pointer_set_with_array_cb(obj, path, value,
|
||||
json_object_array_put_idx_with_limit_cb, &limit_index);
|
||||
return json_pointer_set_with_cb(obj, path, value,
|
||||
json_object_array_put_with_idx_limit_cb, 0, &limit_index);
|
||||
}
|
||||
|
||||
/* safe callback for array index limit */
|
||||
int json_object_array_put_idx_with_limit_cb(struct json_object *jso, size_t idx,
|
||||
struct json_object *jso_new, void *priv)
|
||||
int json_object_array_put_with_idx_limit_cb(struct json_object *jso, const char *key, size_t idx,
|
||||
struct json_object *jso_new, void *priv)
|
||||
{
|
||||
size_t max_idx;
|
||||
// use priv as a size_t pointer to pass in the maximum allowed index
|
||||
if (!priv)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
max_idx = *(size_t*)priv;
|
||||
|
||||
// Check against a maximum to prevent excessive memory allocations.
|
||||
// An extremely large index, even if it doesn't overflow size_t,
|
||||
// will cause a huge memory allocation request via realloc,
|
||||
// leading to an OOM.
|
||||
if (idx > max_idx)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
return json_object_array_put_idx(jso, idx, jso_new);
|
||||
if (key == NULL)
|
||||
{
|
||||
// array operation
|
||||
// use priv as a size_t pointer to pass in the maximum allowed index.
|
||||
// The priv is required context for this callback and must not be NULL.
|
||||
if (!priv)
|
||||
{
|
||||
errno = EFAULT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
max_idx = *(size_t*)priv;
|
||||
|
||||
// Check against a maximum to prevent excessive memory allocations.
|
||||
// An extremely large index, even if it doesn't overflow size_t,
|
||||
// will cause a huge memory allocation request via realloc,
|
||||
// leading to an OOM.
|
||||
if (idx > max_idx)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
return json_object_array_put_idx(jso, idx, jso_new);
|
||||
}
|
||||
else
|
||||
{
|
||||
// object operation
|
||||
return json_object_object_add(jso, key, jso_new);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user