Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

json: Fix multidimensional array support #50816

Merged
merged 6 commits into from
Jun 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 44 additions & 23 deletions lib/os/json.c
Original file line number Diff line number Diff line change
Expand Up @@ -519,19 +519,26 @@ static ptrdiff_t get_elem_size(const struct json_obj_descr *descr)
case JSON_TOK_TRUE:
case JSON_TOK_FALSE:
return sizeof(bool);
case JSON_TOK_ARRAY_START:
return descr->array.n_elements * get_elem_size(descr->array.element_descr);
case JSON_TOK_ARRAY_START: {
ptrdiff_t size;

size = descr->array.n_elements * get_elem_size(descr->array.element_descr);
/* Consider additional item count field for array objects */
if (descr->field_name_len > 0) {
size = size + sizeof(size_t);
}

return size;
}
case JSON_TOK_OBJECT_START: {
ptrdiff_t total = 0;
size_t i;

for (i = 0; i < descr->object.sub_descr_len; i++) {
ptrdiff_t s = get_elem_size(&descr->object.sub_descr[i]);

total += ROUND_UP(s, 1 << descr->align_shift);
total += get_elem_size(&descr->object.sub_descr[i]);
}

return total;
return ROUND_UP(total, 1 << descr->align_shift);
}
default:
return -EINVAL;
Expand All @@ -542,37 +549,44 @@ static int arr_parse(struct json_obj *obj,
const struct json_obj_descr *elem_descr,
size_t max_elements, void *field, void *val)
{
ptrdiff_t elem_size = get_elem_size(elem_descr);
void *last_elem = (char *)field + elem_size * max_elements;
size_t *elements = NULL;
struct json_token value;
void *value = val;
size_t *elements = (size_t *)((char *)value + elem_descr->offset);
ptrdiff_t elem_size;
void *last_elem;
struct json_token tok;

if (val) {
elements = (size_t *)((char *)val + elem_descr->offset);
/* For nested arrays, skip parent descriptor to get elements */
if (elem_descr->type == JSON_TOK_ARRAY_START) {
elem_descr = elem_descr->array.element_descr;
}

__ASSERT_NO_MSG(elem_size > 0);
*elements = 0;
elem_size = get_elem_size(elem_descr);
last_elem = (char *)field + elem_size * max_elements;

if (elements) {
*elements = 0;
}
__ASSERT_NO_MSG(elem_size > 0);

while (!arr_next(obj, &value)) {
if (value.type == JSON_TOK_ARRAY_END) {
while (!arr_next(obj, &tok)) {
if (tok.type == JSON_TOK_ARRAY_END) {
return 0;
}

if (field == last_elem) {
return -ENOSPC;
}

if (decode_value(obj, elem_descr, &value, field, NULL) < 0) {
return -EINVAL;
/* For nested arrays, update value to current field,
* so it matches descriptor's offset to length field
*/
if (elem_descr->type == JSON_TOK_ARRAY_START) {
value = field;
}

if (elements) {
(*elements)++;
if (decode_value(obj, elem_descr, &tok, field, value) < 0) {
return -EINVAL;
}

(*elements)++;
field = (char *)field + elem_size;
}

Expand Down Expand Up @@ -835,7 +849,7 @@ static int arr_encode(const struct json_obj_descr *elem_descr,
const void *field, const void *val,
json_append_bytes_t append_bytes, void *data)
{
ptrdiff_t elem_size = get_elem_size(elem_descr);
ptrdiff_t elem_size;
/*
* NOTE: Since an element descriptor's offset isn't meaningful
* (array elements occur at multiple offsets in `val'), we use
Expand All @@ -851,6 +865,13 @@ static int arr_encode(const struct json_obj_descr *elem_descr,
return ret;
}

/* For nested arrays, skip parent descriptor to get elements */
if (elem_descr->type == JSON_TOK_ARRAY_START) {
elem_descr = elem_descr->array.element_descr;
}

elem_size = get_elem_size(elem_descr);

for (i = 0; i < n_elem; i++) {
/*
* Though "field" points at the next element in the
Expand Down
Loading
Loading