spa: add and use spa_overflow macros

This commit is contained in:
Wim Taymans 2026-04-24 15:54:15 +02:00
parent 84f8230a47
commit 0f8d5c6e57
16 changed files with 149 additions and 50 deletions

View file

@ -0,0 +1,40 @@
/* Simple Plugin API */
/* SPDX-FileCopyrightText: Copyright © 2026 Wim Taymans */
/* SPDX-License-Identifier: MIT */
#ifndef SPA_UTILS_OVERFLOW_H
#define SPA_UTILS_OVERFLOW_H
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief Check for addition overflow
*
* Computes \a a + \a b and stores the result in \a *res.
* \return true if the addition overflowed, false otherwise
*/
#define spa_overflow_add(a, b, res) __builtin_add_overflow(a, b, res)
/**
* \brief Check for subtraction overflow
*
* Computes \a a - \a b and stores the result in \a *res.
* \return true if the subtraction overflowed, false otherwise
*/
#define spa_overflow_sub(a, b, res) __builtin_sub_overflow(a, b, res)
/**
* \brief Check for multiplication overflow
*
* Computes \a a * \a b and stores the result in \a *res.
* \return true if the multiplication overflowed, false otherwise
*/
#define spa_overflow_mul(a, b, res) __builtin_mul_overflow(a, b, res)
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* SPA_UTILS_OVERFLOW_H */

View file

@ -5,6 +5,7 @@
#include <errno.h>
#include <spa/param/audio/format.h>
#include <spa/utils/overflow.h>
#include "resample-native-impl.h"
#ifndef RESAMPLE_DISABLE_PRECOMP
@ -470,8 +471,9 @@ int resample_native_init(struct resample *r)
struct native_data *d;
const struct quality *q;
double scale, cutoff;
uint32_t i, n_taps, n_phases, filter_size, in_rate, out_rate, gcd, filter_stride;
uint32_t history_stride, history_size, oversample;
uint32_t i, n_taps, n_phases, in_rate, out_rate, gcd, filter_stride;
uint32_t history_stride, oversample;
size_t filter_size, history_size, alloc_size;
struct resample_config *c = &r->config;
#ifndef RESAMPLE_DISABLE_PRECOMP
struct resample_config def = { 0 };
@ -515,17 +517,21 @@ int resample_native_init(struct resample *r)
n_phases *= oversample;
filter_stride = SPA_ROUND_UP_N(n_taps * sizeof(float), 64);
filter_size = filter_stride * (n_phases + 1);
if (spa_overflow_mul((size_t)filter_stride, (size_t)(n_phases + 1), &filter_size))
return -ENOMEM;
history_stride = SPA_ROUND_UP_N(2 * n_taps * sizeof(float), 64);
history_size = r->channels * history_stride;
if (spa_overflow_mul((size_t)r->channels, (size_t)history_stride, &history_size))
return -ENOMEM;
d = calloc(1, sizeof(struct native_data) +
filter_size +
history_size +
(r->channels * sizeof(float*)) +
64);
alloc_size = sizeof(struct native_data);
if (spa_overflow_add(alloc_size, filter_size, &alloc_size) ||
spa_overflow_add(alloc_size, history_size, &alloc_size) ||
spa_overflow_add(alloc_size, (size_t)r->channels * sizeof(float*), &alloc_size) ||
spa_overflow_add(alloc_size, (size_t)64, &alloc_size))
return -ENOMEM;
d = calloc(1, alloc_size);
if (d == NULL)
return -errno;

View file

@ -6,6 +6,7 @@
#include <errno.h>
#include <spa/param/audio/format.h>
#include <spa/utils/overflow.h>
#include "peaks-ops.h"
#include "resample.h"
@ -113,7 +114,12 @@ int resample_peaks_init(struct resample *r)
r->free = impl_peaks_free;
r->update_rate = impl_peaks_update_rate;
d = calloc(1, sizeof(struct peaks_data) + sizeof(float) * r->channels);
size_t alloc_size;
if (spa_overflow_mul(sizeof(float), (size_t)r->channels, &alloc_size) ||
spa_overflow_add(alloc_size, sizeof(struct peaks_data), &alloc_size))
return -ENOMEM;
d = calloc(1, alloc_size);
if (d == NULL)
return -errno;

View file

@ -39,6 +39,7 @@
#include <bluetooth/bluetooth.h>
#include <spa/utils/defs.h>
#include <spa/utils/overflow.h>
#include <spa/support/log.h>
#include "rate-control.h"
@ -107,9 +108,12 @@ static inline int spa_bt_decode_buffer_init(struct spa_bt_decode_buffer *this, s
this->frame_size = frame_size;
this->rate = rate;
this->log = log;
this->buffer_reserve = this->frame_size * reserve;
this->buffer_size = this->frame_size * quantum_limit * 2;
this->buffer_size += this->buffer_reserve;
if (spa_overflow_mul(this->frame_size, reserve, &this->buffer_reserve))
return -ENOMEM;
if (spa_overflow_mul(this->frame_size, quantum_limit, &this->buffer_size) ||
spa_overflow_mul(this->buffer_size, 2u, &this->buffer_size) ||
spa_overflow_add(this->buffer_size, this->buffer_reserve, &this->buffer_size))
return -ENOMEM;
this->corr = 1.0;
this->prev_match_rate = 1.0;
this->target = 0;

View file

@ -12,6 +12,7 @@
#include <spa/utils/list.h>
#include <spa/utils/string.h>
#include <spa/utils/overflow.h>
#define PW_TELEPHONY_SERVICE "org.pipewire.Telephony"
@ -1100,10 +1101,11 @@ telephony_ag_new(struct spa_bt_telephony *telephony, size_t user_data_size)
{
struct impl *impl = SPA_CONTAINER_OF(telephony, struct impl, this);
struct agimpl *agimpl;
size_t alloc_size;
spa_assert(user_data_size < SIZE_MAX - sizeof(*agimpl));
spa_assert(!spa_overflow_add(sizeof(*agimpl), user_data_size, &alloc_size));
agimpl = calloc(1, sizeof(*agimpl) + user_data_size);
agimpl = calloc(1, alloc_size);
if (agimpl == NULL)
return NULL;
@ -1334,10 +1336,11 @@ struct spa_bt_telephony_call *
telephony_call_new(struct spa_bt_telephony_ag *ag, size_t user_data_size)
{
struct callimpl *callimpl;
size_t alloc_size;
spa_assert(user_data_size < SIZE_MAX - sizeof(*callimpl));
spa_assert(!spa_overflow_add(sizeof(*callimpl), user_data_size, &alloc_size));
callimpl = calloc(1, sizeof(*callimpl) + user_data_size);
callimpl = calloc(1, alloc_size);
if (callimpl == NULL)
return NULL;

View file

@ -19,6 +19,7 @@
#include <spa/utils/json.h>
#include <spa/utils/result.h>
#include <spa/utils/cleanup.h>
#include <spa/utils/overflow.h>
#include <spa/support/cpu.h>
#include <spa/support/log.h>
#include <spa/support/loop.h>
@ -1533,7 +1534,13 @@ static void *delay_instantiate(const struct spa_fga_plugin *plugin, const struct
spa_log_info(impl->log, "max-delay:%f seconds rate:%lu samples:%d latency:%f",
max_delay, impl->rate, impl->buffer_samples, impl->latency);
impl->buffer = calloc(impl->buffer_samples * 2 + 64, sizeof(float));
size_t buf_count;
if (spa_overflow_mul((size_t)impl->buffer_samples, (size_t)2, &buf_count) ||
spa_overflow_add(buf_count, (size_t)64, &buf_count)) {
delay_cleanup(impl);
return NULL;
}
impl->buffer = calloc(buf_count, sizeof(float));
if (impl->buffer == NULL) {
delay_cleanup(impl);
return NULL;