Bug #118 ยป 0027-Avoid-VLA-use-in-generic_iterate-in-C-code.patch
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)
|
||
/***************************************************************************
|