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 <leandro.pereira@intel.com>
This commit is contained in:
parent
3384262827
commit
7a72ecd314
2 changed files with 21 additions and 3 deletions
|
@ -9,10 +9,11 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <misc/printk.h>
|
#include <misc/printk.h>
|
||||||
|
#include <misc/util.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <zephyr/types.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <zephyr/types.h>
|
||||||
|
|
||||||
#include "json.h"
|
#include "json.h"
|
||||||
|
|
||||||
|
@ -475,6 +476,8 @@ static int decode_value(struct json_obj *obj,
|
||||||
|
|
||||||
static ptrdiff_t get_elem_size(const struct json_obj_descr *descr)
|
static ptrdiff_t get_elem_size(const struct json_obj_descr *descr)
|
||||||
{
|
{
|
||||||
|
assert(descr->alignment);
|
||||||
|
|
||||||
switch (descr->type) {
|
switch (descr->type) {
|
||||||
case JSON_TOK_NUMBER:
|
case JSON_TOK_NUMBER:
|
||||||
return sizeof(s32_t);
|
return sizeof(s32_t);
|
||||||
|
@ -489,8 +492,10 @@ static ptrdiff_t get_elem_size(const struct json_obj_descr *descr)
|
||||||
ptrdiff_t total = 0;
|
ptrdiff_t total = 0;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
for (i = 0; i < descr->sub_descr_len; i++) {
|
for (i = 0; i < descr->object.sub_descr_len; i++) {
|
||||||
total += get_elem_size(&descr->object.sub_descr[i]);
|
ptrdiff_t s = get_elem_size(&descr->object.sub_descr[i]);
|
||||||
|
|
||||||
|
total += ROUND_UP(s, descr->alignment);
|
||||||
}
|
}
|
||||||
|
|
||||||
return total;
|
return total;
|
||||||
|
|
|
@ -33,6 +33,7 @@ struct json_obj_descr {
|
||||||
const char *field_name;
|
const char *field_name;
|
||||||
size_t field_name_len;
|
size_t field_name_len;
|
||||||
size_t offset;
|
size_t offset;
|
||||||
|
size_t alignment;
|
||||||
|
|
||||||
/* Valid values here: JSON_TOK_STRING, JSON_TOK_NUMBER,
|
/* Valid values here: JSON_TOK_STRING, JSON_TOK_NUMBER,
|
||||||
* JSON_TOK_TRUE, JSON_TOK_FALSE, JSON_TOK_OBJECT_START,
|
* 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,
|
||||||
.field_name = (#field_name_), \
|
.field_name = (#field_name_), \
|
||||||
.field_name_len = sizeof(#field_name_) - 1, \
|
.field_name_len = sizeof(#field_name_) - 1, \
|
||||||
.offset = offsetof(struct_, field_name_), \
|
.offset = offsetof(struct_, field_name_), \
|
||||||
|
.alignment = __alignof__(struct_), \
|
||||||
.type = type_, \
|
.type = type_, \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,6 +130,7 @@ typedef int (*json_append_bytes_t)(const char *bytes, size_t len,
|
||||||
.field_name = (#field_name_), \
|
.field_name = (#field_name_), \
|
||||||
.field_name_len = (sizeof(#field_name_) - 1), \
|
.field_name_len = (sizeof(#field_name_) - 1), \
|
||||||
.offset = offsetof(struct_, field_name_), \
|
.offset = offsetof(struct_, field_name_), \
|
||||||
|
.alignment = __alignof__(struct_), \
|
||||||
.type = JSON_TOK_OBJECT_START, \
|
.type = JSON_TOK_OBJECT_START, \
|
||||||
.object = { \
|
.object = { \
|
||||||
.sub_descr = sub_descr_, \
|
.sub_descr = sub_descr_, \
|
||||||
|
@ -166,11 +169,13 @@ typedef int (*json_append_bytes_t)(const char *bytes, size_t len,
|
||||||
.field_name = (#field_name_), \
|
.field_name = (#field_name_), \
|
||||||
.field_name_len = sizeof(#field_name_) - 1, \
|
.field_name_len = sizeof(#field_name_) - 1, \
|
||||||
.offset = offsetof(struct_, field_name_), \
|
.offset = offsetof(struct_, field_name_), \
|
||||||
|
.alignment = __alignof__(struct_), \
|
||||||
.type = JSON_TOK_LIST_START, \
|
.type = JSON_TOK_LIST_START, \
|
||||||
.array = { \
|
.array = { \
|
||||||
.element_descr = &(struct json_obj_descr) { \
|
.element_descr = &(struct json_obj_descr) { \
|
||||||
.type = elem_type_, \
|
.type = elem_type_, \
|
||||||
.offset = offsetof(struct_, len_field_), \
|
.offset = offsetof(struct_, len_field_), \
|
||||||
|
.alignment = __alignof__(struct_), \
|
||||||
}, \
|
}, \
|
||||||
.n_elements = (max_len_), \
|
.n_elements = (max_len_), \
|
||||||
}, \
|
}, \
|
||||||
|
@ -221,6 +226,7 @@ typedef int (*json_append_bytes_t)(const char *bytes, size_t len,
|
||||||
.field_name = (#field_name_), \
|
.field_name = (#field_name_), \
|
||||||
.field_name_len = sizeof(#field_name_) - 1, \
|
.field_name_len = sizeof(#field_name_) - 1, \
|
||||||
.offset = offsetof(struct_, field_name_), \
|
.offset = offsetof(struct_, field_name_), \
|
||||||
|
.alignment = __alignof__(struct_), \
|
||||||
.type = JSON_TOK_LIST_START, \
|
.type = JSON_TOK_LIST_START, \
|
||||||
.array = { \
|
.array = { \
|
||||||
.element_descr = &(struct json_obj_descr) { \
|
.element_descr = &(struct json_obj_descr) { \
|
||||||
|
@ -230,6 +236,7 @@ typedef int (*json_append_bytes_t)(const char *bytes, size_t len,
|
||||||
.sub_descr_len = elem_descr_len_, \
|
.sub_descr_len = elem_descr_len_, \
|
||||||
}, \
|
}, \
|
||||||
.offset = offsetof(struct_, len_field_), \
|
.offset = offsetof(struct_, len_field_), \
|
||||||
|
.alignment = __alignof__(struct_), \
|
||||||
}, \
|
}, \
|
||||||
.n_elements = (max_len_), \
|
.n_elements = (max_len_), \
|
||||||
}, \
|
}, \
|
||||||
|
@ -258,6 +265,7 @@ typedef int (*json_append_bytes_t)(const char *bytes, size_t len,
|
||||||
.field_name = (json_field_name_), \
|
.field_name = (json_field_name_), \
|
||||||
.field_name_len = sizeof(json_field_name_) - 1, \
|
.field_name_len = sizeof(json_field_name_) - 1, \
|
||||||
.offset = offsetof(struct_, struct_field_name_), \
|
.offset = offsetof(struct_, struct_field_name_), \
|
||||||
|
.alignment = __alignof__(struct_), \
|
||||||
.type = type_, \
|
.type = type_, \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -283,6 +291,7 @@ typedef int (*json_append_bytes_t)(const char *bytes, size_t len,
|
||||||
.field_name = (json_field_name_), \
|
.field_name = (json_field_name_), \
|
||||||
.field_name_len = (sizeof(json_field_name_) - 1), \
|
.field_name_len = (sizeof(json_field_name_) - 1), \
|
||||||
.offset = offsetof(struct_, struct_field_name_), \
|
.offset = offsetof(struct_, struct_field_name_), \
|
||||||
|
.alignment = __alignof__(struct_), \
|
||||||
.type = JSON_TOK_OBJECT_START, \
|
.type = JSON_TOK_OBJECT_START, \
|
||||||
.object = { \
|
.object = { \
|
||||||
.sub_descr = sub_descr_, \
|
.sub_descr = sub_descr_, \
|
||||||
|
@ -318,11 +327,13 @@ typedef int (*json_append_bytes_t)(const char *bytes, size_t len,
|
||||||
.field_name = (json_field_name_), \
|
.field_name = (json_field_name_), \
|
||||||
.field_name_len = sizeof(json_field_name_) - 1, \
|
.field_name_len = sizeof(json_field_name_) - 1, \
|
||||||
.offset = offsetof(struct_, struct_field_name_), \
|
.offset = offsetof(struct_, struct_field_name_), \
|
||||||
|
.alignment = __alignof__(struct_), \
|
||||||
.type = JSON_TOK_LIST_START, \
|
.type = JSON_TOK_LIST_START, \
|
||||||
.array = { \
|
.array = { \
|
||||||
.element_descr = &(struct json_obj_descr) { \
|
.element_descr = &(struct json_obj_descr) { \
|
||||||
.type = elem_type_, \
|
.type = elem_type_, \
|
||||||
.offset = offsetof(struct_, len_field_), \
|
.offset = offsetof(struct_, len_field_), \
|
||||||
|
.alignment = __alignof__(struct_), \
|
||||||
}, \
|
}, \
|
||||||
.n_elements = (max_len_), \
|
.n_elements = (max_len_), \
|
||||||
}, \
|
}, \
|
||||||
|
@ -382,6 +393,7 @@ typedef int (*json_append_bytes_t)(const char *bytes, size_t len,
|
||||||
.field_name = json_field_name_, \
|
.field_name = json_field_name_, \
|
||||||
.field_name_len = sizeof(json_field_name_) - 1, \
|
.field_name_len = sizeof(json_field_name_) - 1, \
|
||||||
.offset = offsetof(struct_, struct_field_name_), \
|
.offset = offsetof(struct_, struct_field_name_), \
|
||||||
|
.alignment = __alignof__(struct_), \
|
||||||
.type = JSON_TOK_LIST_START, \
|
.type = JSON_TOK_LIST_START, \
|
||||||
.element_descr = &(struct json_obj_descr) { \
|
.element_descr = &(struct json_obj_descr) { \
|
||||||
.type = JSON_TOK_OBJECT_START, \
|
.type = JSON_TOK_OBJECT_START, \
|
||||||
|
@ -390,6 +402,7 @@ typedef int (*json_append_bytes_t)(const char *bytes, size_t len,
|
||||||
.sub_descr_len = elem_descr_len_, \
|
.sub_descr_len = elem_descr_len_, \
|
||||||
}, \
|
}, \
|
||||||
.offset = offsetof(struct_, len_field_), \
|
.offset = offsetof(struct_, len_field_), \
|
||||||
|
.alignment = __alignof__(struct_), \
|
||||||
}, \
|
}, \
|
||||||
.n_elements = (max_len_), \
|
.n_elements = (max_len_), \
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue