Skip to content

Commit 7a72ecd

Browse files
lpereiraAnas Nashif
authored andcommitted
lib: json: Alignment should be considered when calculating struct size
This was causing an unaligned pointer read on some architectures, leading to crashes. This could be alternatively solved by rounding the size to the nearest power of 2, but this wouldn't work with packed structs. Signed-off-by: Leandro Pereira <[email protected]>
1 parent 3384262 commit 7a72ecd

File tree

2 files changed

+21
-3
lines changed

2 files changed

+21
-3
lines changed

lib/json/json.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,11 @@
99
#include <errno.h>
1010
#include <limits.h>
1111
#include <misc/printk.h>
12+
#include <misc/util.h>
1213
#include <stdbool.h>
13-
#include <zephyr/types.h>
1414
#include <stdlib.h>
1515
#include <string.h>
16+
#include <zephyr/types.h>
1617

1718
#include "json.h"
1819

@@ -475,6 +476,8 @@ static int decode_value(struct json_obj *obj,
475476

476477
static ptrdiff_t get_elem_size(const struct json_obj_descr *descr)
477478
{
479+
assert(descr->alignment);
480+
478481
switch (descr->type) {
479482
case JSON_TOK_NUMBER:
480483
return sizeof(s32_t);
@@ -489,8 +492,10 @@ static ptrdiff_t get_elem_size(const struct json_obj_descr *descr)
489492
ptrdiff_t total = 0;
490493
size_t i;
491494

492-
for (i = 0; i < descr->sub_descr_len; i++) {
493-
total += get_elem_size(&descr->object.sub_descr[i]);
495+
for (i = 0; i < descr->object.sub_descr_len; i++) {
496+
ptrdiff_t s = get_elem_size(&descr->object.sub_descr[i]);
497+
498+
total += ROUND_UP(s, descr->alignment);
494499
}
495500

496501
return total;

lib/json/json.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ struct json_obj_descr {
3333
const char *field_name;
3434
size_t field_name_len;
3535
size_t offset;
36+
size_t alignment;
3637

3738
/* Valid values here: JSON_TOK_STRING, JSON_TOK_NUMBER,
3839
* JSON_TOK_TRUE, JSON_TOK_FALSE, JSON_TOK_OBJECT_START,
@@ -95,6 +96,7 @@ typedef int (*json_append_bytes_t)(const char *bytes, size_t len,
9596
.field_name = (#field_name_), \
9697
.field_name_len = sizeof(#field_name_) - 1, \
9798
.offset = offsetof(struct_, field_name_), \
99+
.alignment = __alignof__(struct_), \
98100
.type = type_, \
99101
}
100102

@@ -128,6 +130,7 @@ typedef int (*json_append_bytes_t)(const char *bytes, size_t len,
128130
.field_name = (#field_name_), \
129131
.field_name_len = (sizeof(#field_name_) - 1), \
130132
.offset = offsetof(struct_, field_name_), \
133+
.alignment = __alignof__(struct_), \
131134
.type = JSON_TOK_OBJECT_START, \
132135
.object = { \
133136
.sub_descr = sub_descr_, \
@@ -166,11 +169,13 @@ typedef int (*json_append_bytes_t)(const char *bytes, size_t len,
166169
.field_name = (#field_name_), \
167170
.field_name_len = sizeof(#field_name_) - 1, \
168171
.offset = offsetof(struct_, field_name_), \
172+
.alignment = __alignof__(struct_), \
169173
.type = JSON_TOK_LIST_START, \
170174
.array = { \
171175
.element_descr = &(struct json_obj_descr) { \
172176
.type = elem_type_, \
173177
.offset = offsetof(struct_, len_field_), \
178+
.alignment = __alignof__(struct_), \
174179
}, \
175180
.n_elements = (max_len_), \
176181
}, \
@@ -221,6 +226,7 @@ typedef int (*json_append_bytes_t)(const char *bytes, size_t len,
221226
.field_name = (#field_name_), \
222227
.field_name_len = sizeof(#field_name_) - 1, \
223228
.offset = offsetof(struct_, field_name_), \
229+
.alignment = __alignof__(struct_), \
224230
.type = JSON_TOK_LIST_START, \
225231
.array = { \
226232
.element_descr = &(struct json_obj_descr) { \
@@ -230,6 +236,7 @@ typedef int (*json_append_bytes_t)(const char *bytes, size_t len,
230236
.sub_descr_len = elem_descr_len_, \
231237
}, \
232238
.offset = offsetof(struct_, len_field_), \
239+
.alignment = __alignof__(struct_), \
233240
}, \
234241
.n_elements = (max_len_), \
235242
}, \
@@ -258,6 +265,7 @@ typedef int (*json_append_bytes_t)(const char *bytes, size_t len,
258265
.field_name = (json_field_name_), \
259266
.field_name_len = sizeof(json_field_name_) - 1, \
260267
.offset = offsetof(struct_, struct_field_name_), \
268+
.alignment = __alignof__(struct_), \
261269
.type = type_, \
262270
}
263271

@@ -283,6 +291,7 @@ typedef int (*json_append_bytes_t)(const char *bytes, size_t len,
283291
.field_name = (json_field_name_), \
284292
.field_name_len = (sizeof(json_field_name_) - 1), \
285293
.offset = offsetof(struct_, struct_field_name_), \
294+
.alignment = __alignof__(struct_), \
286295
.type = JSON_TOK_OBJECT_START, \
287296
.object = { \
288297
.sub_descr = sub_descr_, \
@@ -318,11 +327,13 @@ typedef int (*json_append_bytes_t)(const char *bytes, size_t len,
318327
.field_name = (json_field_name_), \
319328
.field_name_len = sizeof(json_field_name_) - 1, \
320329
.offset = offsetof(struct_, struct_field_name_), \
330+
.alignment = __alignof__(struct_), \
321331
.type = JSON_TOK_LIST_START, \
322332
.array = { \
323333
.element_descr = &(struct json_obj_descr) { \
324334
.type = elem_type_, \
325335
.offset = offsetof(struct_, len_field_), \
336+
.alignment = __alignof__(struct_), \
326337
}, \
327338
.n_elements = (max_len_), \
328339
}, \
@@ -382,6 +393,7 @@ typedef int (*json_append_bytes_t)(const char *bytes, size_t len,
382393
.field_name = json_field_name_, \
383394
.field_name_len = sizeof(json_field_name_) - 1, \
384395
.offset = offsetof(struct_, struct_field_name_), \
396+
.alignment = __alignof__(struct_), \
385397
.type = JSON_TOK_LIST_START, \
386398
.element_descr = &(struct json_obj_descr) { \
387399
.type = JSON_TOK_OBJECT_START, \
@@ -390,6 +402,7 @@ typedef int (*json_append_bytes_t)(const char *bytes, size_t len,
390402
.sub_descr_len = elem_descr_len_, \
391403
}, \
392404
.offset = offsetof(struct_, len_field_), \
405+
.alignment = __alignof__(struct_), \
393406
}, \
394407
.n_elements = (max_len_), \
395408
}

0 commit comments

Comments
 (0)