From aa2289a25bf1d8130e22e3bc2569de946fdaca2b Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Thu, 3 Jul 2025 14:53:07 +0200 Subject: [PATCH] pod: check pod alignment Make a SPA_POD_ALIGN = 8 and make sure all pods are aligned to it. Use the new constant to pad and check alignment. Make some new macros to check for the pod type, alignment and minimal size. --- spa/include/spa/pod/builder.h | 2 +- spa/include/spa/pod/iter.h | 54 +++++++++++++++++------------------ spa/include/spa/pod/parser.h | 8 +++--- spa/include/spa/pod/pod.h | 4 ++- test/test-spa-pod.c | 22 ++++++++++++++ 5 files changed, 56 insertions(+), 34 deletions(-) diff --git a/spa/include/spa/pod/builder.h b/spa/include/spa/pod/builder.h index f4b68fd63..f3277d40a 100644 --- a/spa/include/spa/pod/builder.h +++ b/spa/include/spa/pod/builder.h @@ -167,7 +167,7 @@ SPA_API_POD_BUILDER void spa_pod_builder_remove(struct spa_pod_builder *builder, SPA_API_POD_BUILDER int spa_pod_builder_pad(struct spa_pod_builder *builder, uint32_t size) { uint64_t zeroes = 0; - size = SPA_ROUND_UP_N(size, 8) - size; + size = SPA_ROUND_UP_N(size, SPA_POD_ALIGN) - size; return size ? spa_pod_builder_raw(builder, &zeroes, size) : 0; } diff --git a/spa/include/spa/pod/iter.h b/spa/include/spa/pod/iter.h index f77f47e70..87c5b17a3 100644 --- a/spa/include/spa/pod/iter.h +++ b/spa/include/spa/pod/iter.h @@ -44,7 +44,7 @@ SPA_API_POD_ITER bool spa_pod_is_inside(const void *pod, uint32_t size, const vo SPA_API_POD_ITER void *spa_pod_next(const void *iter) { - return SPA_PTROFF(iter, SPA_ROUND_UP_N(SPA_POD_SIZE(iter), 8), void); + return SPA_PTROFF(iter, SPA_ROUND_UP_N(SPA_POD_SIZE(iter), SPA_POD_ALIGN), void); } SPA_API_POD_ITER struct spa_pod_prop *spa_pod_prop_first(const struct spa_pod_object_body *body) @@ -63,7 +63,7 @@ SPA_API_POD_ITER bool spa_pod_prop_is_inside(const struct spa_pod_object_body *b SPA_API_POD_ITER struct spa_pod_prop *spa_pod_prop_next(const struct spa_pod_prop *iter) { - return SPA_PTROFF(iter, SPA_ROUND_UP_N(SPA_POD_PROP_SIZE(iter), 8), struct spa_pod_prop); + return SPA_PTROFF(iter, SPA_ROUND_UP_N(SPA_POD_PROP_SIZE(iter), SPA_POD_ALIGN), struct spa_pod_prop); } SPA_API_POD_ITER struct spa_pod_control *spa_pod_control_first(const struct spa_pod_sequence_body *body) @@ -82,7 +82,7 @@ SPA_API_POD_ITER bool spa_pod_control_is_inside(const struct spa_pod_sequence_bo SPA_API_POD_ITER struct spa_pod_control *spa_pod_control_next(const struct spa_pod_control *iter) { - return SPA_PTROFF(iter, SPA_ROUND_UP_N(SPA_POD_CONTROL_SIZE(iter), 8), struct spa_pod_control); + return SPA_PTROFF(iter, SPA_ROUND_UP_N(SPA_POD_CONTROL_SIZE(iter), SPA_POD_ALIGN), struct spa_pod_control); } #define SPA_POD_ARRAY_BODY_FOREACH(body, _size, iter) \ @@ -136,19 +136,25 @@ SPA_API_POD_ITER void *spa_pod_from_data(void *data, size_t maxsize, off_t offse maxsize - size < (uint32_t)offset) return NULL; pod = SPA_PTROFF(data, offset, void); + if (!SPA_IS_ALIGNED(pod, SPA_POD_ALIGN)) + return NULL; if (SPA_POD_BODY_SIZE(pod) > size - sizeof(struct spa_pod)) return NULL; return pod; } +#define SPA_POD_CHECK_0(pod,_type) ((pod)->type == (_type) && SPA_IS_ALIGNED(pod, SPA_POD_ALIGN)) +#define SPA_POD_CHECK(pod,_type,_size) \ + (SPA_POD_CHECK_0(pod,_type) && (pod)->size >= (_size)) + SPA_API_POD_ITER int spa_pod_is_none(const struct spa_pod *pod) { - return (SPA_POD_TYPE(pod) == SPA_TYPE_None); + return SPA_POD_CHECK_0(pod, SPA_TYPE_None); } SPA_API_POD_ITER int spa_pod_is_bool(const struct spa_pod *pod) { - return (SPA_POD_TYPE(pod) == SPA_TYPE_Bool && SPA_POD_BODY_SIZE(pod) >= sizeof(int32_t)); + return SPA_POD_CHECK(pod, SPA_TYPE_Bool, sizeof(int32_t)); } SPA_API_POD_ITER int spa_pod_get_bool(const struct spa_pod *pod, bool *value) @@ -161,7 +167,7 @@ SPA_API_POD_ITER int spa_pod_get_bool(const struct spa_pod *pod, bool *value) SPA_API_POD_ITER int spa_pod_is_id(const struct spa_pod *pod) { - return (SPA_POD_TYPE(pod) == SPA_TYPE_Id && SPA_POD_BODY_SIZE(pod) >= sizeof(uint32_t)); + return SPA_POD_CHECK(pod, SPA_TYPE_Id, sizeof(uint32_t)); } SPA_API_POD_ITER int spa_pod_get_id(const struct spa_pod *pod, uint32_t *value) @@ -174,7 +180,7 @@ SPA_API_POD_ITER int spa_pod_get_id(const struct spa_pod *pod, uint32_t *value) SPA_API_POD_ITER int spa_pod_is_int(const struct spa_pod *pod) { - return (SPA_POD_TYPE(pod) == SPA_TYPE_Int && SPA_POD_BODY_SIZE(pod) >= sizeof(int32_t)); + return SPA_POD_CHECK(pod, SPA_TYPE_Int, sizeof(int32_t)); } SPA_API_POD_ITER int spa_pod_get_int(const struct spa_pod *pod, int32_t *value) @@ -187,7 +193,7 @@ SPA_API_POD_ITER int spa_pod_get_int(const struct spa_pod *pod, int32_t *value) SPA_API_POD_ITER int spa_pod_is_long(const struct spa_pod *pod) { - return (SPA_POD_TYPE(pod) == SPA_TYPE_Long && SPA_POD_BODY_SIZE(pod) >= sizeof(int64_t)); + return SPA_POD_CHECK(pod, SPA_TYPE_Long, sizeof(int64_t)); } SPA_API_POD_ITER int spa_pod_get_long(const struct spa_pod *pod, int64_t *value) @@ -200,7 +206,7 @@ SPA_API_POD_ITER int spa_pod_get_long(const struct spa_pod *pod, int64_t *value) SPA_API_POD_ITER int spa_pod_is_float(const struct spa_pod *pod) { - return (SPA_POD_TYPE(pod) == SPA_TYPE_Float && SPA_POD_BODY_SIZE(pod) >= sizeof(float)); + return SPA_POD_CHECK(pod, SPA_TYPE_Float, sizeof(float)); } SPA_API_POD_ITER int spa_pod_get_float(const struct spa_pod *pod, float *value) @@ -213,7 +219,7 @@ SPA_API_POD_ITER int spa_pod_get_float(const struct spa_pod *pod, float *value) SPA_API_POD_ITER int spa_pod_is_double(const struct spa_pod *pod) { - return (SPA_POD_TYPE(pod) == SPA_TYPE_Double && SPA_POD_BODY_SIZE(pod) >= sizeof(double)); + return SPA_POD_CHECK(pod, SPA_TYPE_Double, sizeof(double)); } SPA_API_POD_ITER int spa_pod_get_double(const struct spa_pod *pod, double *value) @@ -227,9 +233,8 @@ SPA_API_POD_ITER int spa_pod_get_double(const struct spa_pod *pod, double *value SPA_API_POD_ITER int spa_pod_is_string(const struct spa_pod *pod) { const char *s = (const char *)SPA_POD_CONTENTS(struct spa_pod_string, pod); - return (SPA_POD_TYPE(pod) == SPA_TYPE_String && - SPA_POD_BODY_SIZE(pod) > 0 && - s[SPA_POD_BODY_SIZE(pod)-1] == '\0'); + return SPA_POD_CHECK(pod, SPA_TYPE_String, 1) && + s[pod->size-1] == '\0'; } SPA_API_POD_ITER int spa_pod_get_string(const struct spa_pod *pod, const char **value) @@ -252,7 +257,7 @@ SPA_API_POD_ITER int spa_pod_copy_string(const struct spa_pod *pod, size_t maxle SPA_API_POD_ITER int spa_pod_is_bytes(const struct spa_pod *pod) { - return SPA_POD_TYPE(pod) == SPA_TYPE_Bytes; + return SPA_POD_CHECK_0(pod, SPA_TYPE_Bytes); } SPA_API_POD_ITER int spa_pod_get_bytes(const struct spa_pod *pod, const void **value, uint32_t *len) @@ -266,8 +271,7 @@ SPA_API_POD_ITER int spa_pod_get_bytes(const struct spa_pod *pod, const void **v SPA_API_POD_ITER int spa_pod_is_pointer(const struct spa_pod *pod) { - return (SPA_POD_TYPE(pod) == SPA_TYPE_Pointer && - SPA_POD_BODY_SIZE(pod) >= sizeof(struct spa_pod_pointer_body)); + return SPA_POD_CHECK(pod, SPA_TYPE_Pointer, sizeof(struct spa_pod_pointer_body)); } SPA_API_POD_ITER int spa_pod_get_pointer(const struct spa_pod *pod, uint32_t *type, const void **value) @@ -281,8 +285,7 @@ SPA_API_POD_ITER int spa_pod_get_pointer(const struct spa_pod *pod, uint32_t *ty SPA_API_POD_ITER int spa_pod_is_fd(const struct spa_pod *pod) { - return (SPA_POD_TYPE(pod) == SPA_TYPE_Fd && - SPA_POD_BODY_SIZE(pod) >= sizeof(int64_t)); + return SPA_POD_CHECK(pod, SPA_TYPE_Fd, sizeof(int64_t)); } SPA_API_POD_ITER int spa_pod_get_fd(const struct spa_pod *pod, int64_t *value) @@ -295,8 +298,7 @@ SPA_API_POD_ITER int spa_pod_get_fd(const struct spa_pod *pod, int64_t *value) SPA_API_POD_ITER int spa_pod_is_rectangle(const struct spa_pod *pod) { - return (SPA_POD_TYPE(pod) == SPA_TYPE_Rectangle && - SPA_POD_BODY_SIZE(pod) >= sizeof(struct spa_rectangle)); + return SPA_POD_CHECK(pod, SPA_TYPE_Rectangle, sizeof(struct spa_rectangle)); } SPA_API_POD_ITER int spa_pod_get_rectangle(const struct spa_pod *pod, struct spa_rectangle *value) @@ -309,8 +311,7 @@ SPA_API_POD_ITER int spa_pod_get_rectangle(const struct spa_pod *pod, struct spa SPA_API_POD_ITER int spa_pod_is_fraction(const struct spa_pod *pod) { - return (SPA_POD_TYPE(pod) == SPA_TYPE_Fraction && - SPA_POD_BODY_SIZE(pod) >= sizeof(struct spa_fraction)); + return SPA_POD_CHECK(pod, SPA_TYPE_Fraction, sizeof(struct spa_fraction)); } SPA_API_POD_ITER int spa_pod_get_fraction(const struct spa_pod *pod, struct spa_fraction *value) @@ -322,14 +323,12 @@ SPA_API_POD_ITER int spa_pod_get_fraction(const struct spa_pod *pod, struct spa_ SPA_API_POD_ITER int spa_pod_is_bitmap(const struct spa_pod *pod) { - return (SPA_POD_TYPE(pod) == SPA_TYPE_Bitmap && - SPA_POD_BODY_SIZE(pod) >= sizeof(uint8_t)); + return SPA_POD_CHECK(pod, SPA_TYPE_Bitmap, sizeof(uint8_t)); } SPA_API_POD_ITER int spa_pod_is_array(const struct spa_pod *pod) { - return (SPA_POD_TYPE(pod) == SPA_TYPE_Array && - SPA_POD_BODY_SIZE(pod) >= sizeof(struct spa_pod_array_body)); + return SPA_POD_CHECK(pod, SPA_TYPE_Array, sizeof(struct spa_pod_array_body)); } SPA_API_POD_ITER void *spa_pod_get_array(const struct spa_pod *pod, uint32_t *n_values) @@ -353,8 +352,7 @@ SPA_API_POD_ITER uint32_t spa_pod_copy_array(const struct spa_pod *pod, uint32_t SPA_API_POD_ITER int spa_pod_is_choice(const struct spa_pod *pod) { - return (SPA_POD_TYPE(pod) == SPA_TYPE_Choice && - SPA_POD_BODY_SIZE(pod) >= sizeof(struct spa_pod_choice_body)); + return SPA_POD_CHECK(pod, SPA_TYPE_Choice, sizeof(struct spa_pod_choice_body)); } SPA_API_POD_ITER struct spa_pod *spa_pod_get_values(const struct spa_pod *pod, uint32_t *n_vals, uint32_t *choice) diff --git a/spa/include/spa/pod/parser.h b/spa/include/spa/pod/parser.h index 922992e92..a3a5527bc 100644 --- a/spa/include/spa/pod/parser.h +++ b/spa/include/spa/pod/parser.h @@ -79,8 +79,8 @@ spa_pod_parser_deref(struct spa_pod_parser *parser, uint32_t offset, uint32_t si * Check that the pointer is aligned and that the size (rounded * to the next multiple of 8) is in bounds. */ - if (SPA_IS_ALIGNED(pod, __alignof__(struct spa_pod)) && - long_offset + SPA_ROUND_UP_N((uint64_t)SPA_POD_BODY_SIZE(pod), 8) <= size) + if (SPA_IS_ALIGNED(pod, SPA_POD_ALIGN) && + long_offset + SPA_ROUND_UP_N((uint64_t)SPA_POD_BODY_SIZE(pod), SPA_POD_ALIGN) <= size) return (struct spa_pod *)pod; } return NULL; @@ -110,7 +110,7 @@ SPA_API_POD_PARSER struct spa_pod *spa_pod_parser_current(struct spa_pod_parser SPA_API_POD_PARSER void spa_pod_parser_advance(struct spa_pod_parser *parser, const struct spa_pod *pod) { - parser->state.offset += SPA_ROUND_UP_N(SPA_POD_SIZE(pod), 8); + parser->state.offset += SPA_ROUND_UP_N(SPA_POD_SIZE(pod), SPA_POD_ALIGN); } SPA_API_POD_PARSER struct spa_pod *spa_pod_parser_next(struct spa_pod_parser *parser) @@ -125,7 +125,7 @@ SPA_API_POD_PARSER int spa_pod_parser_pop(struct spa_pod_parser *parser, struct spa_pod_frame *frame) { parser->state.frame = frame->parent; - parser->state.offset = frame->offset + SPA_ROUND_UP_N(SPA_POD_SIZE(&frame->pod), 8); + parser->state.offset = frame->offset + SPA_ROUND_UP_N(SPA_POD_SIZE(&frame->pod), SPA_POD_ALIGN); return 0; } diff --git a/spa/include/spa/pod/pod.h b/spa/include/spa/pod/pod.h index 398236e79..854a65abc 100644 --- a/spa/include/spa/pod/pod.h +++ b/spa/include/spa/pod/pod.h @@ -17,6 +17,8 @@ extern "C" { * \{ */ +#define SPA_POD_ALIGN 8 + #define SPA_POD_BODY_SIZE(pod) (((struct spa_pod*)(pod))->size) #define SPA_POD_TYPE(pod) (((struct spa_pod*)(pod))->type) #define SPA_POD_SIZE(pod) ((uint64_t)sizeof(struct spa_pod) + SPA_POD_BODY_SIZE(pod)) @@ -30,7 +32,7 @@ extern "C" { struct spa_pod { uint32_t size; /* size of the body */ uint32_t type; /* a basic id of enum spa_type */ -}; +} SPA_ALIGNED(SPA_POD_ALIGN); #define SPA_POD_VALUE(type,pod) (((type*)(pod))->value) diff --git a/test/test-spa-pod.c b/test/test-spa-pod.c index e84b5a18e..f499e818b 100644 --- a/test/test-spa-pod.c +++ b/test/test-spa-pod.c @@ -524,6 +524,8 @@ PWTEST(pod_build) spa_assert_se(memcmp(&val.F, &SPA_FRACTION(25,1), sizeof(struct spa_fraction)) == 0); spa_assert_se((pod = spa_pod_next(pod)) != NULL && spa_pod_is_inside(head, len, pod)); + spa_assert_se(array->type == SPA_TYPE_Array); + spa_assert_se(array->size >= sizeof(struct spa_pod_array_body)); spa_assert_se(spa_pod_is_array(pod)); spa_assert_se(SPA_POD_ARRAY_VALUE_TYPE(pod) == SPA_TYPE_Int); spa_assert_se(SPA_POD_ARRAY_VALUE_SIZE(pod) == sizeof(int32_t)); @@ -542,6 +544,8 @@ PWTEST(pod_build) } spa_assert_se((pod = spa_pod_next(pod)) != NULL && spa_pod_is_inside(head, len, pod)); + spa_assert_se(array->type == SPA_TYPE_Array); + spa_assert_se(array->size >= sizeof(struct spa_pod_array_body)); spa_assert_se(spa_pod_is_array(pod)); spa_assert_se(SPA_POD_ARRAY_VALUE_TYPE(pod) == SPA_TYPE_Long); spa_assert_se(SPA_POD_ARRAY_VALUE_SIZE(pod) == sizeof(int64_t)); @@ -691,6 +695,10 @@ PWTEST(pod_empty) array = spa_pod_builder_pop(&b, &f); spa_assert_se(array != NULL); spa_debug_mem(0, array, 16); + spa_assert_se(array->type == SPA_TYPE_Array); + spa_assert_se(array->size == sizeof(struct spa_pod_array_body)); + spa_assert_se(SPA_POD_ARRAY_VALUE_TYPE(array) == SPA_TYPE_Id); + spa_assert_se(SPA_POD_ARRAY_VALUE_SIZE(array) == 4); spa_assert_se(spa_pod_is_array(array)); a2 = spa_pod_get_array(array, &n_vals); spa_assert_se(a2 != NULL); @@ -700,6 +708,8 @@ PWTEST(pod_empty) spa_assert_se(spa_pod_builder_push_array(&b, &f) == 0); array = spa_pod_builder_pop(&b, &f); spa_assert_se(array != NULL); + spa_assert_se(array->type == SPA_TYPE_Array); + spa_assert_se(array->size >= sizeof(struct spa_pod_array_body)); spa_assert_se(spa_pod_is_array(array)); a2 = spa_pod_get_array(array, &n_vals); spa_assert_se(a2 != NULL); @@ -710,6 +720,8 @@ PWTEST(pod_empty) spa_assert_se(spa_pod_builder_none(&b) == 0); array = spa_pod_builder_pop(&b, &f); spa_assert_se(array != NULL); + spa_assert_se(array->type == SPA_TYPE_Array); + spa_assert_se(array->size >= sizeof(struct spa_pod_array_body)); spa_assert_se(spa_pod_is_array(array)); a2 = spa_pod_get_array(array, &n_vals); spa_assert_se(a2 != NULL); @@ -718,6 +730,8 @@ PWTEST(pod_empty) spa_pod_builder_init(&b, buffer, sizeof(buffer)); spa_assert_se(spa_pod_builder_array(&b, 4, SPA_TYPE_Id, 0, NULL) == 0); array = (struct spa_pod*)buffer; + spa_assert_se(array->type == SPA_TYPE_Array); + spa_assert_se(array->size >= sizeof(struct spa_pod_array_body)); spa_assert_se(spa_pod_is_array(array)); a2 = spa_pod_get_array(array, &n_vals); spa_assert_se(a2 != NULL); @@ -730,6 +744,10 @@ PWTEST(pod_empty) choice = spa_pod_builder_pop(&b, &f); spa_assert_se(choice != NULL); spa_debug_mem(0, choice, 32); + spa_assert_se(choice->type == SPA_TYPE_Choice); + spa_assert_se(choice->size == sizeof(struct spa_pod_choice_body)); + spa_assert_se(SPA_POD_CHOICE_TYPE(choice) == SPA_CHOICE_None); + spa_assert_se(SPA_POD_CHOICE_CHILD(choice)->size == 4); spa_assert_se(spa_pod_is_choice(choice)); ch2 = spa_pod_get_values(choice, &n_vals, &ch); spa_assert_se(ch2 != NULL); @@ -739,6 +757,8 @@ PWTEST(pod_empty) spa_assert_se(spa_pod_builder_push_choice(&b, &f, 0, 0) == 0); choice = spa_pod_builder_pop(&b, &f); spa_assert_se(choice != NULL); + spa_assert_se(SPA_POD_CHOICE_TYPE(choice) == SPA_CHOICE_None); + spa_assert_se(SPA_POD_CHOICE_CHILD(choice)->size == 0); spa_assert_se(spa_pod_is_choice(choice)); ch2 = spa_pod_get_values(choice, &n_vals, &ch); spa_assert_se(ch2 != NULL); @@ -749,6 +769,8 @@ PWTEST(pod_empty) spa_assert_se(spa_pod_builder_none(&b) == 0); choice = spa_pod_builder_pop(&b, &f); spa_assert_se(choice != NULL); + spa_assert_se(SPA_POD_CHOICE_TYPE(choice) == SPA_CHOICE_None); + spa_assert_se(SPA_POD_CHOICE_CHILD(choice)->size == 0); spa_assert_se(spa_pod_is_choice(choice)); ch2 = spa_pod_get_values(choice, &n_vals, &ch); spa_assert_se(ch2 != NULL);