From 62eb004ccbd4b3d759bda96f7a0c6d072b23ffa9 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Fri, 20 May 2022 12:00:08 -0400 Subject: [PATCH] Fix: Pointers are rejected by integer element compile time assertion for array and sequence commit 2df82195d140b ("Add compile time assertion that array and sequence have integer elements") introduced a check to validate that sequences and arrays only contain integers. This was meant to refuse arrays of double/float which are not supported. However, as a side-effect, this also refuses arrays and sequences of pointers, which were accepted prior to lttng-ust 2.13. Introduce a lttng_ust_is_pointer_type() and use it in the array/sequence type validation. The trick here is to use the fact that a difference between two pointers in C is an integer. Therefore, we can validate that an argument type is a pointer similarly to C++ is_pointer. Signed-off-by: Mathieu Desnoyers Fixes: #1355 Change-Id: I7c96d24ab68fb711f85eccdb781a3c513b45c5dc --- include/lttng/ust-utils.h | 20 +++++++-- tests/unit/ust-utils/ust-utils-common.h | 58 ++++++++++++++++++++++++- 2 files changed, 74 insertions(+), 4 deletions(-) diff --git a/include/lttng/ust-utils.h b/include/lttng/ust-utils.h index cbd1f66a..25b8c7fd 100644 --- a/include/lttng/ust-utils.h +++ b/include/lttng/ust-utils.h @@ -58,15 +58,29 @@ __builtin_types_compatible_p(type, unsigned long long)) #endif +/** + * lttng_ust_is_pointer_type - check if type is a pointer + * + * Returns true if the type of @type is a pointer. + */ +#if defined(__cplusplus) +#define lttng_ust_is_pointer_type(type) (std::is_pointer::value) +#else +/* The difference between two pointers is an integer. */ +#define lttng_ust_is_pointer_type(type) \ + (lttng_ust_is_integer_type(typeof(((type)0 - (type)0))) && !lttng_ust_is_integer_type(type)) +#endif + + /** * lttng_ust_field_array_element_type_is_supported - * * Adds a compilation assertion that array and sequence fields declared by the - * user are of an integral type. + * user are of an integral or pointer type. */ #define lttng_ust_field_array_element_type_is_supported(type, item) \ - lttng_ust_static_assert(lttng_ust_is_integer_type(type), \ - "Non-integer type `" #item "` not supported as element of LTTNG_UST_FIELD_ARRAY or LTTNG_UST_FIELD_SEQUENCE", \ + lttng_ust_static_assert(lttng_ust_is_integer_type(type) || lttng_ust_is_pointer_type(type), \ + "Non-integer, non-pointer type `" #item "` not supported as element of LTTNG_UST_FIELD_ARRAY or LTTNG_UST_FIELD_SEQUENCE", \ Non_integer_type__##item##__not_supported_as_element_of_LTTNG_UST_FIELD_ARRAY_or_LTTNG_UST_FIELD_SEQUENCE) diff --git a/tests/unit/ust-utils/ust-utils-common.h b/tests/unit/ust-utils/ust-utils-common.h index 0792a10e..0dd15d19 100644 --- a/tests/unit/ust-utils/ust-utils-common.h +++ b/tests/unit/ust-utils/ust-utils-common.h @@ -6,7 +6,7 @@ #include "tap.h" -#define NUM_TESTS 60 +#define NUM_TESTS 94 static void test_ust_stringify(void) @@ -116,6 +116,61 @@ void test_ust_is_integer_type(void) ok_is_not_integer_type(void *); } +#define ok_is_pointer_type(_type) \ + ok(lttng_ust_is_pointer_type(_type) == true, "lttng_ust_is_pointer_type - '" lttng_ust_stringify(_type) "' is a pointer") + +#define ok_is_not_pointer_type(_type) \ + ok(lttng_ust_is_pointer_type(_type) == false, "lttng_ust_is_pointer_type - '" lttng_ust_stringify(_type) "' is not a pointer") + +struct dummy { + int a; +}; + +static +void test_ust_is_pointer_type(void) +{ + ok_is_not_pointer_type(char); + ok_is_not_pointer_type(short); + ok_is_not_pointer_type(int); + ok_is_not_pointer_type(long); + ok_is_not_pointer_type(long long); + + ok_is_not_pointer_type(signed char); + ok_is_not_pointer_type(signed short); + ok_is_not_pointer_type(signed int); + ok_is_not_pointer_type(signed long); + ok_is_not_pointer_type(signed long long); + + ok_is_not_pointer_type(unsigned char); + ok_is_not_pointer_type(unsigned short); + ok_is_not_pointer_type(unsigned int); + ok_is_not_pointer_type(unsigned long); + ok_is_not_pointer_type(unsigned long long); + + ok_is_not_pointer_type(int8_t); + ok_is_not_pointer_type(int16_t); + ok_is_not_pointer_type(int32_t); + ok_is_not_pointer_type(int64_t); + ok_is_not_pointer_type(intmax_t); + + ok_is_not_pointer_type(uint8_t); + ok_is_not_pointer_type(uint16_t); + ok_is_not_pointer_type(uint32_t); + ok_is_not_pointer_type(uint64_t); + ok_is_not_pointer_type(uintmax_t); + + ok_is_not_pointer_type(float); + ok_is_not_pointer_type(double); + ok_is_not_pointer_type(long double); + + ok_is_pointer_type(void *); + ok_is_pointer_type(void **); + ok_is_pointer_type(struct dummy *); + ok_is_pointer_type(int *); + ok_is_pointer_type(float *); + ok_is_pointer_type(double *); +} + int main(void) { plan_tests(NUM_TESTS); @@ -123,6 +178,7 @@ int main(void) test_ust_stringify(); test_ust_is_signed(); test_ust_is_integer_type(); + test_ust_is_pointer_type(); return exit_status(); } -- 2.34.1