diff --git a/spa/include/spa/pod/iter.h b/spa/include/spa/pod/iter.h index 6cd1f89b6..e2dad74fc 100644 --- a/spa/include/spa/pod/iter.h +++ b/spa/include/spa/pod/iter.h @@ -28,7 +28,10 @@ struct spa_pod_frame { static inline bool spa_pod_is_inside(const void *pod, uint32_t size, const void *iter) { - return spa_ptrinside(pod, size, iter, SPA_POD_SIZE(iter)); + size_t remaining; + + return spa_ptr_type_inside(pod, size, iter, struct spa_pod, &remaining) && + remaining >= SPA_POD_BODY_SIZE(iter); } static inline void *spa_pod_next(const void *iter) @@ -44,7 +47,10 @@ static inline struct spa_pod_prop *spa_pod_prop_first(const struct spa_pod_objec static inline bool spa_pod_prop_is_inside(const struct spa_pod_object_body *body, uint32_t size, const struct spa_pod_prop *iter) { - return spa_ptrinside(body, size, iter, SPA_POD_PROP_SIZE(iter)); + size_t remaining; + + return spa_ptr_type_inside(body, size, iter, struct spa_pod_prop, &remaining) && + remaining >= iter->value.size; } static inline struct spa_pod_prop *spa_pod_prop_next(const struct spa_pod_prop *iter) @@ -60,7 +66,10 @@ static inline struct spa_pod_control *spa_pod_control_first(const struct spa_pod static inline bool spa_pod_control_is_inside(const struct spa_pod_sequence_body *body, uint32_t size, const struct spa_pod_control *iter) { - return spa_ptrinside(body, size, iter, SPA_POD_CONTROL_SIZE(iter)); + size_t remaining; + + return spa_ptr_type_inside(body, size, iter, struct spa_pod_control, &remaining) && + remaining >= iter->value.size; } static inline struct spa_pod_control *spa_pod_control_next(const struct spa_pod_control *iter) @@ -70,7 +79,7 @@ static inline struct spa_pod_control *spa_pod_control_next(const struct spa_pod_ #define SPA_POD_ARRAY_BODY_FOREACH(body, _size, iter) \ for ((iter) = (__typeof__(iter))SPA_PTROFF((body), sizeof(struct spa_pod_array_body), void); \ - spa_ptrinside(body, _size, iter, (body)->child.size); \ + spa_ptrinside(body, _size, iter, (body)->child.size, NULL); \ (iter) = (__typeof__(iter))SPA_PTROFF((iter), (body)->child.size, void)) #define SPA_POD_ARRAY_FOREACH(obj, iter) \ @@ -78,7 +87,7 @@ static inline struct spa_pod_control *spa_pod_control_next(const struct spa_pod_ #define SPA_POD_CHOICE_BODY_FOREACH(body, _size, iter) \ for ((iter) = (__typeof__(iter))SPA_PTROFF((body), sizeof(struct spa_pod_choice_body), void); \ - spa_ptrinside(body, _size, iter, (body)->child.size); \ + spa_ptrinside(body, _size, iter, (body)->child.size, NULL); \ (iter) = (__typeof__(iter))SPA_PTROFF((iter), (body)->child.size, void)) #define SPA_POD_CHOICE_FOREACH(obj, iter) \ diff --git a/spa/include/spa/utils/defs.h b/spa/include/spa/utils/defs.h index ae8cbf05d..3444a5aed 100644 --- a/spa/include/spa/utils/defs.h +++ b/spa/include/spa/utils/defs.h @@ -9,17 +9,25 @@ extern "C" { # if __cplusplus >= 201103L # define SPA_STATIC_ASSERT_IMPL(expr, msg, ...) static_assert(expr, msg) +# define SPA_ALIGNOF alignof # endif +#elif __STDC_VERSION__ >= 202311L +# define SPA_STATIC_ASSERT_IMPL(expr, msg, ...) static_assert(expr, msg) +# define SPA_ALIGNOF alignof #else # include # if __STDC_VERSION__ >= 201112L # define SPA_STATIC_ASSERT_IMPL(expr, msg, ...) _Static_assert(expr, msg) +# define SPA_ALIGNOF _Alignof # endif #endif #ifndef SPA_STATIC_ASSERT_IMPL #define SPA_STATIC_ASSERT_IMPL(expr, ...) \ ((void)sizeof(struct { int spa_static_assertion_failed : 2 * !!(expr) - 1; })) #endif +#ifndef SPA_ALIGNOF +#define SPA_ALIGNOF __alignof__ +#endif #define SPA_STATIC_ASSERT(expr, ...) SPA_STATIC_ASSERT_IMPL(expr, ## __VA_ARGS__, "`" #expr "` evaluated to false") @@ -191,15 +199,6 @@ struct spa_fraction { #define SPA_PTRDIFF(p1,p2) ((intptr_t)(p1) - (intptr_t)(p2)) -static inline bool spa_ptrinside(const void *p1, size_t s1, const void *p2, size_t s2) -{ - return (uintptr_t)p1 <= (uintptr_t)p2 && s2 <= s1 && - (uintptr_t)p2 - (uintptr_t)p1 <= s1 - s2; -} - -#define SPA_PTR_TO_INT(p) ((int) ((intptr_t) (p))) -#define SPA_INT_TO_PTR(u) ((void*) ((intptr_t) (u))) - #define SPA_PTR_TO_UINT32(p) ((uint32_t) ((uintptr_t) (p))) #define SPA_UINT32_TO_PTR(u) ((void*) ((uintptr_t) (u))) @@ -287,6 +286,40 @@ static inline bool spa_ptrinside(const void *p1, size_t s1, const void *p2, size #endif #endif +static inline bool spa_ptrinside(const void *p1, size_t s1, const void *p2, size_t s2, + size_t *remaining) +{ + if (SPA_LIKELY((uintptr_t)p1 <= (uintptr_t)p2 && s2 <= s1 && + (uintptr_t)p2 - (uintptr_t)p1 <= s1 - s2)) { + if (remaining != NULL) + *remaining = ((uintptr_t)p1 + s1) - ((uintptr_t)p2 + s2); + return true; + } else { + if (remaining != NULL) + *remaining = 0; + return false; + } +} + +static inline bool spa_ptr_inside_and_aligned(const void *p1, size_t s1, + const void *p2, size_t s2, size_t align, + size_t *remaining) +{ + if (SPA_IS_ALIGNED(p2, align)) { + return spa_ptrinside(p1, s1, p2, s2, remaining); + } else { + if (remaining != NULL) + *remaining = 0; + return false; + } +} + +#define spa_ptr_type_inside(p1, s1, p2, type, remaining) \ + spa_ptr_inside_and_aligned(p1, s1, p2, sizeof(type), SPA_ALIGNOF(type), remaining) + +#define SPA_PTR_TO_INT(p) ((int) ((intptr_t) (p))) +#define SPA_INT_TO_PTR(u) ((void*) ((intptr_t) (u))) + #define SPA_STRINGIFY_1(...) #__VA_ARGS__ #define SPA_STRINGIFY(...) SPA_STRINGIFY_1(__VA_ARGS__)