spa: add spa_alloca that does overflow and limit checks

Make a function like alloca but with overflow checks and a max
allocation size.

Use this function where we can and also make sure that all alloca calls
are in some way limited.
This commit is contained in:
Wim Taymans 2026-04-27 10:53:44 +02:00
parent a9f1ad414e
commit ed2c0ad4ee
10 changed files with 84 additions and 51 deletions

View file

@ -457,6 +457,16 @@ struct spa_error_location {
_strp; \
})
#define spa_alloca(n, size, max_size) \
({ \
void *_res = NULL; \
if ((size_t)n > (size_t)max_size / (size_t)size) \
errno = ENOMEM; \
else \
_res = alloca((size_t)n * (size_t)size); \
_res; \
})
/**
* \}
*/

View file

@ -35,6 +35,7 @@ SPA_LOG_TOPIC_DEFINE_STATIC(log_topic, "spa.audioadapter");
#define MAX_PORTS (SPA_AUDIO_MAX_CHANNELS+1)
#define MAX_RETRY 64
#define MAX_BLOCKS 4096
/** \cond */
@ -356,6 +357,7 @@ static void emit_node_info(struct impl *this, bool full)
if (this->info.props)
n_items = this->info.props->n_items;
n_items = SPA_MIN(n_items, 1024u);
items = alloca((n_items + 2) * sizeof(struct spa_dict_item));
for (i = 0; i < n_items; i++)
items[i] = this->info.props->items[i];
@ -513,6 +515,9 @@ static int negotiate_buffers(struct impl *this)
align = SPA_MAX(align, this->max_align);
if (blocks > MAX_BLOCKS)
return -ENOMEM;
datas = alloca(sizeof(struct spa_data) * blocks);
memset(datas, 0, sizeof(struct spa_data) * blocks);
aligns = alloca(sizeof(uint32_t) * blocks);
@ -1942,11 +1947,12 @@ static int load_converter(struct impl *this, const struct spa_dict *info,
struct spa_dict_item *items;
struct spa_dict cinfo;
char direction[16];
uint32_t i;
uint32_t i, n_items;
items = alloca((info->n_items + 1) * sizeof(struct spa_dict_item));
n_items = SPA_MIN(info->n_items, 1024u);
items = alloca((n_items + 1) * sizeof(struct spa_dict_item));
cinfo = SPA_DICT(items, 0);
for (i = 0; i < info->n_items; i++)
for (i = 0; i < n_items; i++)
items[cinfo.n_items++] = info->items[i];
snprintf(direction, sizeof(direction), "%s",