From 7a72ecd3148ab91d942c7a360e76e6b68f5985b4 Mon Sep 17 00:00:00 2001 From: Leandro Pereira Date: Tue, 5 Sep 2017 16:32:27 -0700 Subject: [PATCH] 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 --- lib/json/json.c | 11 ++++++++--- lib/json/json.h | 13 +++++++++++++ 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/lib/json/json.c b/lib/json/json.c index 411a708f5fd..576e55f5623 100644 --- a/lib/json/json.c +++ b/lib/json/json.c @@ -9,10 +9,11 @@ #include #include #include +#include #include -#include #include #include +#include #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) { + assert(descr->alignment); + switch (descr->type) { case JSON_TOK_NUMBER: return sizeof(s32_t); @@ -489,8 +492,10 @@ static ptrdiff_t get_elem_size(const struct json_obj_descr *descr) ptrdiff_t total = 0; size_t i; - for (i = 0; i < descr->sub_descr_len; i++) { - total += get_elem_size(&descr->object.sub_descr[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, descr->alignment); } return total; diff --git a/lib/json/json.h b/lib/json/json.h index 84d2f36b7ac..55198131389 100644 --- a/lib/json/json.h +++ b/lib/json/json.h @@ -33,6 +33,7 @@ struct json_obj_descr { const char *field_name; size_t field_name_len; size_t offset; + size_t alignment; /* Valid values here: JSON_TOK_STRING, JSON_TOK_NUMBER, * 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_len = sizeof(#field_name_) - 1, \ .offset = offsetof(struct_, field_name_), \ + .alignment = __alignof__(struct_), \ .type = type_, \ } @@ -128,6 +130,7 @@ typedef int (*json_append_bytes_t)(const char *bytes, size_t len, .field_name = (#field_name_), \ .field_name_len = (sizeof(#field_name_) - 1), \ .offset = offsetof(struct_, field_name_), \ + .alignment = __alignof__(struct_), \ .type = JSON_TOK_OBJECT_START, \ .object = { \ .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_len = sizeof(#field_name_) - 1, \ .offset = offsetof(struct_, field_name_), \ + .alignment = __alignof__(struct_), \ .type = JSON_TOK_LIST_START, \ .array = { \ .element_descr = &(struct json_obj_descr) { \ .type = elem_type_, \ .offset = offsetof(struct_, len_field_), \ + .alignment = __alignof__(struct_), \ }, \ .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_len = sizeof(#field_name_) - 1, \ .offset = offsetof(struct_, field_name_), \ + .alignment = __alignof__(struct_), \ .type = JSON_TOK_LIST_START, \ .array = { \ .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_, \ }, \ .offset = offsetof(struct_, len_field_), \ + .alignment = __alignof__(struct_), \ }, \ .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_len = sizeof(json_field_name_) - 1, \ .offset = offsetof(struct_, struct_field_name_), \ + .alignment = __alignof__(struct_), \ .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_len = (sizeof(json_field_name_) - 1), \ .offset = offsetof(struct_, struct_field_name_), \ + .alignment = __alignof__(struct_), \ .type = JSON_TOK_OBJECT_START, \ .object = { \ .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_len = sizeof(json_field_name_) - 1, \ .offset = offsetof(struct_, struct_field_name_), \ + .alignment = __alignof__(struct_), \ .type = JSON_TOK_LIST_START, \ .array = { \ .element_descr = &(struct json_obj_descr) { \ .type = elem_type_, \ .offset = offsetof(struct_, len_field_), \ + .alignment = __alignof__(struct_), \ }, \ .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_len = sizeof(json_field_name_) - 1, \ .offset = offsetof(struct_, struct_field_name_), \ + .alignment = __alignof__(struct_), \ .type = JSON_TOK_LIST_START, \ .element_descr = &(struct json_obj_descr) { \ .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_, \ }, \ .offset = offsetof(struct_, len_field_), \ + .alignment = __alignof__(struct_), \ }, \ .n_elements = (max_len_), \ }