Project

General

Profile

Bug #118 ยป 0027-Avoid-VLA-use-in-generic_iterate-in-C-code.patch

Marko Lindqvist, 01/04/2024 12:09 AM

View differences:

utility/iterator.h
#ifdef __cplusplus
extern "C" {
#include "mem.h"
#endif /* __cplusplus */
/* utility */
......
first element in the sequence, or an invalid iterator.
... - Zero or more extra arguments that 'FUNC_init' expects.
***************************************************************************/
#define generic_iterate(TYPE_it, TYPE_a, NAME_a, FUNC_size, FUNC_init, ...)\
do {\
char MY_mem_##NAME_a[FUNC_size()];\
struct iterator *MY_it_##NAME_a;\
TYPE_a NAME_a;\
MY_it_##NAME_a =\
FUNC_init((TYPE_it *) (void *) MY_mem_##NAME_a , ## __VA_ARGS__);\
for (; iterator_valid(MY_it_##NAME_a); iterator_next(MY_it_##NAME_a)) {\
NAME_a = (TYPE_a) iterator_get(MY_it_##NAME_a);\
#define generic_iterate_end\
}\
#ifdef __cplusplus
/* C++ does not have VLA, except as compiler extension in case of
some compilers. Thus we need to fc_malloc() correct size array.
Wrap the allocated array within a class, so it will get freed
by the destructor when it goes out of scope. */
class gi_mem
{
public:
void *array;
gi_mem(int size) {
array = fc_malloc(size);
}
~gi_mem() {
free(array);
}
};
#define generic_iterate(TYPE_it, TYPE_a, NAME_a, FUNC_size, FUNC_init, ...) \
do { \
gi_mem MY_mem_##NAME_a(FUNC_size()); \
struct iterator *MY_it_##NAME_a; \
TYPE_a NAME_a; \
MY_it_##NAME_a = \
FUNC_init((TYPE_it *) MY_mem_##NAME_a.array , ## __VA_ARGS__); \
for (; iterator_valid(MY_it_##NAME_a); iterator_next(MY_it_##NAME_a)) { \
NAME_a = (TYPE_a) iterator_get(MY_it_##NAME_a);
#else // __cplusplus
#define generic_iterate(TYPE_it, TYPE_a, NAME_a, FUNC_size, FUNC_init, ...) \
do { \
char MY_mem_##NAME_a[FUNC_size()]; \
struct iterator *MY_it_##NAME_a; \
TYPE_a NAME_a; \
MY_it_##NAME_a = \
FUNC_init((TYPE_it *) (void *) MY_mem_##NAME_a , ## __VA_ARGS__); \
for (; iterator_valid(MY_it_##NAME_a); iterator_next(MY_it_##NAME_a)) { \
NAME_a = (TYPE_a) iterator_get(MY_it_##NAME_a);
#endif // __cplusplus
#define generic_iterate_end \
} \
} while (FALSE)
/***************************************************************************
    (1-1/1)