From 93ee7c4775fa4715ff8ef69c476bf433370cc1a7 Mon Sep 17 00:00:00 2001 From: Norihiro Kamae Date: Fri, 1 Oct 2021 12:35:59 +0900 Subject: [PATCH] libobs/util: Add type test in darray macros for GCC Previously darray macros did not test the types of arguments so that developers cannot notice even if a wrong type of a variable is passed. This commit add a type test that relys on GCC's extension. Since OBS Studio is built with GCC for Ubuntu, testing only under GCC is sufficient to catch future bugs. --- CMakeLists.txt | 9 +++++ libobs/util/darray.h | 93 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 101 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a906bd19f..7edf307f7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -207,6 +207,11 @@ if(APPLE) elseif(UNIX) option(USE_XDG "Utilize XDG Base Directory Specification" ON) option(ENABLE_WAYLAND "Build support for Wayland" ON) + if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) + option(ENABLE_DARRAY_TYPE_TEST "Test types of darray argument" ON) + else() + option(ENABLE_DARRAY_TYPE_TEST "Test types of darray argument" OFF) + endif() if(USE_XDG) add_definitions(-DUSE_XDG) @@ -215,6 +220,10 @@ elseif(UNIX) if(NOT UNIX_STRUCTURE) list(APPEND CMAKE_INSTALL_RPATH "$ORIGIN") endif() + + if(ENABLE_DARRAY_TYPE_TEST) + add_definitions(-DENABLE_DARRAY_TYPE_TEST) + endif() endif() if(LOWERCASE_CMAKE_SYSTEM_PROCESSOR MATCHES "e2k") diff --git a/libobs/util/darray.h b/libobs/util/darray.h index a4a0e2931..b18d86614 100644 --- a/libobs/util/darray.h +++ b/libobs/util/darray.h @@ -494,33 +494,124 @@ static inline void darray_swap(const size_t element_size, struct darray *dst, #define da_move(dst, src) darray_move(&dst.da, &src.da) -#define da_find(v, item, idx) darray_find(sizeof(*v.array), &v.da, item, idx) +#ifdef ENABLE_DARRAY_TYPE_TEST +#ifdef __cplusplus +#define da_type_test(v, item) \ + ({ \ + if (false) { \ + auto _t = v.array; \ + _t = (item); \ + (void)_t; \ + *(v).array = *(item); \ + } \ + }) +#else +#define da_type_test(v, item) \ + ({ \ + if (false) { \ + const typeof(*v.array) *_t; \ + _t = (item); \ + (void)_t; \ + *(v).array = *(item); \ + } \ + }) +#endif +#endif // ENABLE_DARRAY_TYPE_TEST +#ifdef ENABLE_DARRAY_TYPE_TEST +#define da_find(v, item, idx) \ + ({ \ + da_type_test(v, item); \ + darray_find(sizeof(*v.array), &v.da, item, idx); \ + }) +#else +#define da_find(v, item, idx) darray_find(sizeof(*v.array), &v.da, item, idx) +#endif + +#ifdef ENABLE_DARRAY_TYPE_TEST +#define da_push_back(v, item) \ + ({ \ + da_type_test(v, item); \ + darray_push_back(sizeof(*v.array), &v.da, item); \ + }) +#else #define da_push_back(v, item) darray_push_back(sizeof(*v.array), &v.da, item) +#endif #define da_push_back_new(v) darray_push_back_new(sizeof(*v.array), &v.da) +#ifdef ENABLE_DARRAY_TYPE_TEST +#define da_push_back_array(dst, src_array, n) \ + ({ \ + da_type_test(dst, src_array); \ + darray_push_back_array(sizeof(*dst.array), &dst.da, src_array, \ + n); \ + }) +#else #define da_push_back_array(dst, src_array, n) \ darray_push_back_array(sizeof(*dst.array), &dst.da, src_array, n) +#endif +#ifdef ENABLE_DARRAY_TYPE_TEST +#define da_push_back_da(dst, src) \ + ({ \ + da_type_test(dst, src.array); \ + darray_push_back_darray(sizeof(*dst.array), &dst.da, &src.da); \ + }) +#else #define da_push_back_da(dst, src) \ darray_push_back_darray(sizeof(*dst.array), &dst.da, &src.da) +#endif +#ifdef ENABLE_DARRAY_TYPE_TEST +#define da_insert(v, idx, item) \ + ({ \ + da_type_test(v, item); \ + darray_insert(sizeof(*v.array), &v.da, idx, item); \ + }) +#else #define da_insert(v, idx, item) \ darray_insert(sizeof(*v.array), &v.da, idx, item) +#endif #define da_insert_new(v, idx) darray_insert_new(sizeof(*v.array), &v.da, idx) +#ifdef ENABLE_DARRAY_TYPE_TEST +#define da_insert_array(dst, idx, src_array, n) \ + ({ \ + da_type_test(dst, src_array); \ + darray_insert_array(sizeof(*dst.array), &dst.da, idx, \ + src_array, n); \ + }) +#else #define da_insert_array(dst, idx, src_array, n) \ darray_insert_array(sizeof(*dst.array), &dst.da, idx, src_array, n) +#endif +#ifdef ENABLE_DARRAY_TYPE_TEST +#define da_insert_da(dst, idx, src) \ + ({ \ + da_type_test(dst, src.array); \ + darray_insert_darray(sizeof(*dst.array), &dst.da, idx, \ + &src.da); \ + }) +#else #define da_insert_da(dst, idx, src) \ darray_insert_darray(sizeof(*dst.array), &dst.da, idx, &src.da) +#endif #define da_erase(dst, idx) darray_erase(sizeof(*dst.array), &dst.da, idx) +#ifdef ENABLE_DARRAY_TYPE_TEST +#define da_erase_item(dst, item) \ + ({ \ + da_type_test(dst, item); \ + darray_erase_item(sizeof(*dst.array), &dst.da, item); \ + }) +#else #define da_erase_item(dst, item) \ darray_erase_item(sizeof(*dst.array), &dst.da, item) +#endif #define da_erase_range(dst, from, to) \ darray_erase_range(sizeof(*dst.array), &dst.da, from, to)