Skip to content

Commit 061e345

Browse files
cjwinklhoferkartben
authored andcommitted
json: Fix calculation of object size
The calculation of the object size may be incorrect when the size of a field is smaller than the struct alignment. When such a struct is used in an array field, the decoded object contains wrong values. The alignment influences the object size. For example the following struct has a calculated object size of 8 bytes, however due to alignment the real size of the struct is 12 bytes: struct test_bool { bool b1; /* offset 0, size 1 */ /* 3-byte padding */ int i1; /* offset 4, size 4 */ bool b2; /* offset 8, size 1 */ /* 3-byte padding */ }; This commit changes the object size calculation and computes the size with the offset and size of the last field in the struct (rounded up by the struct alignment). Fixes: #85121 Signed-off-by: Christoph Winklhofer <[email protected]>
1 parent 1415796 commit 061e345

File tree

2 files changed

+50
-2
lines changed

2 files changed

+50
-2
lines changed

lib/utils/json.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -635,13 +635,17 @@ static ptrdiff_t get_elem_size(const struct json_obj_descr *descr)
635635
size_t i;
636636

637637
for (i = 0; i < descr->object.sub_descr_len; i++) {
638-
total += get_elem_size(&descr->object.sub_descr[i]);
639-
640638
if (descr->object.sub_descr[i].align_shift > align_shift) {
641639
align_shift = descr->object.sub_descr[i].align_shift;
642640
}
643641
}
644642

643+
i = descr->object.sub_descr_len;
644+
if (i > 0) {
645+
total = descr->object.sub_descr[i - 1].offset +
646+
get_elem_size(&descr->object.sub_descr[i - 1]);
647+
}
648+
645649
return ROUND_UP(total, 1 << align_shift);
646650
}
647651
default:

tests/lib/json/src/main.c

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,27 @@ static const struct json_obj_descr outer_descr[] = {
205205
num_elements, element_descr, ARRAY_SIZE(element_descr))
206206
};
207207

208+
struct test_alignment_nested {
209+
bool bool1;
210+
int int1;
211+
bool bool2;
212+
};
213+
214+
struct test_alignment_bool {
215+
struct test_alignment_nested array[3];
216+
size_t num_elements;
217+
};
218+
219+
static const struct json_obj_descr alignment_nested_descr[] = {
220+
JSON_OBJ_DESCR_PRIM(struct test_alignment_nested, bool1, JSON_TOK_TRUE),
221+
JSON_OBJ_DESCR_PRIM(struct test_alignment_nested, int1, JSON_TOK_NUMBER),
222+
JSON_OBJ_DESCR_PRIM(struct test_alignment_nested, bool2, JSON_TOK_TRUE),
223+
};
224+
225+
static const struct json_obj_descr alignment_bool_descr[] = {
226+
JSON_OBJ_DESCR_OBJ_ARRAY(struct test_alignment_bool, array, 3, num_elements,
227+
alignment_nested_descr, ARRAY_SIZE(alignment_nested_descr)) };
228+
208229
ZTEST(lib_json_test, test_json_encoding)
209230
{
210231
struct test_struct ts = {
@@ -1362,4 +1383,27 @@ ZTEST(lib_json_test, test_json_array_alignment)
13621383
zassert_equal(o.array[1].int3, 6, "Element 1 int3 not decoded correctly");
13631384
}
13641385

1386+
ZTEST(lib_json_test, test_json_array_alignment_bool)
1387+
{
1388+
char encoded[] = "{\"array\":["
1389+
"{\"bool1\":true,\"int1\":1,\"bool2\":false},"
1390+
"{\"bool1\":true,\"int1\":2,\"bool2\":false}"
1391+
"]}";
1392+
1393+
struct test_alignment_bool o = { 0 };
1394+
int64_t ret = json_obj_parse(encoded, sizeof(encoded) - 1, alignment_bool_descr,
1395+
ARRAY_SIZE(alignment_bool_descr), &o);
1396+
1397+
zassert_false(ret < 0, "json_obj_parse returned error %d", ret);
1398+
zassert_equal(o.num_elements, 2, "Number of elements not decoded correctly");
1399+
1400+
zassert_equal(o.array[0].bool1, true, "Element 0 bool1 not decoded correctly");
1401+
zassert_equal(o.array[0].int1, 1, "Element 0 int1 not decoded correctly");
1402+
zassert_equal(o.array[0].bool2, false, "Element 0 bool2 not decoded correctly");
1403+
1404+
zassert_equal(o.array[1].bool1, true, "Element 1 bool1 not decoded correctly");
1405+
zassert_equal(o.array[1].int1, 2, "Element 1 int1 not decoded correctly");
1406+
zassert_equal(o.array[1].bool2, false, "Element 1 bool2 not decoded correctly");
1407+
}
1408+
13651409
ZTEST_SUITE(lib_json_test, NULL, NULL, NULL, NULL, NULL);

0 commit comments

Comments
 (0)