treewide: access the position information using helpers

Make sure we don't access out of bounds and that we use the helpers
wherever we can to access the position information.
This commit is contained in:
Wim Taymans 2025-10-21 13:06:25 +02:00
parent 8bbca3b8f3
commit 818d1435ce
25 changed files with 155 additions and 114 deletions

View file

@ -882,7 +882,10 @@ static int create_stream(struct stream_info *info)
for (i = 0; i < remap_info.channels; i++) {
s->remap[i] = i;
for (j = 0; j < tmp_info.channels; j++) {
if (tmp_info.position[j] == remap_info.position[i]) {
uint32_t pj, pi;
pj = spa_format_audio_raw_get_position(&tmp_info, j);
pi = spa_format_audio_raw_get_position(&remap_info, i);
if (pj == pi) {
s->remap[i] = j;
break;
}

View file

@ -298,8 +298,7 @@ static void capture_param_changed(void *data, uint32_t id, const struct spa_pod
if (spa_format_audio_raw_parse(param, &info) < 0)
return;
if (info.rate == 0 ||
info.channels == 0 ||
info.channels > SPA_N_ELEMENTS(info.position))
info.channels == 0)
return;
break;
}

View file

@ -1229,7 +1229,7 @@ static int probe_ffado_device(struct impl *impl)
}
if (impl->source.info.channels != n_channels) {
impl->source.info.channels = n_channels;
for (i = 0; i < SPA_MIN(impl->source.info.channels, MAX_CHANNELS); i++)
for (i = 0; i < SPA_MIN(impl->source.info.channels, SPA_AUDIO_MAX_CHANNELS); i++)
impl->source.info.position[i] = SPA_AUDIO_CHANNEL_AUX0 + i;
}
@ -1255,7 +1255,7 @@ static int probe_ffado_device(struct impl *impl)
}
if (impl->sink.info.channels != n_channels) {
impl->sink.info.channels = n_channels;
for (i = 0; i < SPA_MIN(impl->sink.info.channels, MAX_CHANNELS); i++)
for (i = 0; i < SPA_MIN(impl->sink.info.channels, SPA_AUDIO_MAX_CHANNELS); i++)
impl->sink.info.position[i] = SPA_AUDIO_CHANNEL_AUX0 + i;
}

View file

@ -1691,7 +1691,7 @@ static void copy_position(struct spa_audio_info_raw *dst, const struct spa_audio
{
if (SPA_FLAG_IS_SET(dst->flags, SPA_AUDIO_FLAG_UNPOSITIONED) &&
!SPA_FLAG_IS_SET(src->flags, SPA_AUDIO_FLAG_UNPOSITIONED)) {
for (uint32_t i = 0; i < src->channels; i++)
for (uint32_t i = 0; i < SPA_MIN(src->channels, SPA_AUDIO_MAX_CHANNELS); i++)
dst->position[i] = src->position[i];
SPA_FLAG_CLEAR(dst->flags, SPA_AUDIO_FLAG_UNPOSITIONED);
}

View file

@ -524,7 +524,7 @@ static void make_stream_ports(struct stream *s)
if (i < s->info.channels) {
str = spa_debug_type_find_short_name(spa_type_audio_channel,
s->info.position[i]);
spa_format_audio_raw_get_position(&s->info, i));
if (str)
snprintf(name, sizeof(name), "%s_%s", prefix, str);
else

View file

@ -538,8 +538,7 @@ static void param_format_changed(struct impl *impl, const struct spa_pod *param,
spa_zero(info);
if (param != NULL) {
if (spa_format_audio_raw_parse(param, &info) < 0 ||
info.channels == 0 ||
info.channels > SPA_N_ELEMENTS(info.position))
info.channels == 0)
return;
if ((impl->info.format != 0 && impl->info.format != info.format) ||
@ -547,7 +546,7 @@ static void param_format_changed(struct impl *impl, const struct spa_pod *param,
(impl->info.channels != 0 &&
(impl->info.channels != info.channels ||
memcmp(impl->info.position, info.position,
info.channels * sizeof(uint32_t)) != 0))) {
SPA_MIN(info.channels, SPA_AUDIO_MAX_CHANNELS) * sizeof(uint32_t)) != 0))) {
uint8_t buffer[1024];
struct spa_pod_builder b;
const struct spa_pod *params[1];

View file

@ -442,7 +442,7 @@ static void make_stream_ports(struct stream *s)
if (i < s->info.channels) {
str = spa_debug_type_find_short_name(spa_type_audio_channel,
s->info.position[i % SPA_N_ELEMENTS(s->info.position)]);
spa_format_audio_raw_get_position(&s->info, i));
props = pw_properties_new(
PW_KEY_FORMAT_DSP, "32 bit float mono audio",
PW_KEY_AUDIO_CHANNEL, str ? str : "UNK",
@ -863,10 +863,10 @@ static int handle_follower_setup(struct impl *impl, struct nj2_session_params *p
}
impl->sink.info.rate = peer->params.sample_rate;
if ((uint32_t)peer->params.send_audio_channels != impl->sink.info.channels) {
impl->sink.info.channels = SPA_MIN(peer->params.send_audio_channels,
(int)SPA_N_ELEMENTS(impl->sink.info.position));
impl->sink.info.channels = peer->params.send_audio_channels;
for (i = 0; i < impl->sink.info.channels; i++)
impl->sink.info.position[i] = SPA_AUDIO_CHANNEL_AUX0 + i;
spa_format_audio_raw_set_position(&impl->sink.info, i,
SPA_AUDIO_CHANNEL_AUX0 + i);
}
impl->source.n_ports = peer->params.recv_audio_channels + peer->params.recv_midi_channels;
if (impl->source.n_ports > MAX_PORTS) {
@ -875,10 +875,10 @@ static int handle_follower_setup(struct impl *impl, struct nj2_session_params *p
}
impl->source.info.rate = peer->params.sample_rate;
if ((uint32_t)peer->params.recv_audio_channels != impl->source.info.channels) {
impl->source.info.channels = SPA_MIN(peer->params.recv_audio_channels,
(int)SPA_N_ELEMENTS(impl->source.info.position));
impl->source.info.channels = peer->params.recv_audio_channels;
for (i = 0; i < impl->source.info.channels; i++)
impl->source.info.position[i] = SPA_AUDIO_CHANNEL_AUX0 + i;
spa_format_audio_raw_set_position(&impl->source.info, i,
SPA_AUDIO_CHANNEL_AUX0 + i);
}
impl->samplerate = peer->params.sample_rate;
impl->period_size = peer->params.period_size;

View file

@ -602,7 +602,7 @@ static void make_stream_ports(struct stream *s)
if (i < s->info.channels) {
str = spa_debug_type_find_short_name(spa_type_audio_channel,
s->info.position[i]);
spa_format_audio_raw_get_position(&s->info, i));
props = pw_properties_new(
PW_KEY_FORMAT_DSP, "32 bit float mono audio",
@ -1026,18 +1026,18 @@ static int handle_follower_available(struct impl *impl, struct nj2_session_param
follower->source.n_ports = peer->params.recv_audio_channels + peer->params.recv_midi_channels;
follower->source.info.rate = peer->params.sample_rate;
if ((uint32_t)peer->params.recv_audio_channels != follower->source.info.channels) {
follower->source.info.channels = SPA_MIN(peer->params.recv_audio_channels,
(int)SPA_N_ELEMENTS(follower->source.info.position));
follower->source.info.channels = peer->params.recv_audio_channels;
for (i = 0; i < follower->source.info.channels; i++)
follower->source.info.position[i] = SPA_AUDIO_CHANNEL_AUX0 + i;
spa_format_audio_raw_set_position(&follower->source.info, i,
SPA_AUDIO_CHANNEL_AUX0 + i);
}
follower->sink.n_ports = peer->params.send_audio_channels + peer->params.send_midi_channels;
follower->sink.info.rate = peer->params.sample_rate;
if ((uint32_t)peer->params.send_audio_channels != follower->sink.info.channels) {
follower->sink.info.channels = SPA_MIN(peer->params.send_audio_channels,
(int)SPA_N_ELEMENTS(follower->sink.info.position));
follower->sink.info.channels = peer->params.send_audio_channels;
for (i = 0; i < follower->sink.info.channels; i++)
follower->sink.info.position[i] = SPA_AUDIO_CHANNEL_AUX0 + i;
spa_format_audio_raw_set_position(&follower->sink.info, i,
SPA_AUDIO_CHANNEL_AUX0 + i);
}
if (follower->source.n_ports > MAX_PORTS || follower->sink.n_ports > MAX_PORTS) {

View file

@ -348,9 +348,9 @@ uint32_t channel_paname2id(const char *name, size_t size)
}
void channel_map_to_positions(const struct channel_map *map, uint32_t *pos)
void channel_map_to_positions(const struct channel_map *map, uint32_t *pos, uint32_t max_pos)
{
uint32_t i, channels = SPA_MIN(map->channels, SPA_AUDIO_MAX_CHANNELS);
uint32_t i, channels = SPA_MIN(map->channels, max_pos);
for (i = 0; i < channels; i++)
pos[i] = map->map[i];
}
@ -535,8 +535,7 @@ int format_parse_param(const struct spa_pod *param, bool collect,
info.info.raw.rate = 48000;
if (info.info.raw.format == 0 ||
info.info.raw.rate == 0 ||
info.info.raw.channels == 0 ||
info.info.raw.channels > SPA_N_ELEMENTS(info.info.raw.position))
info.info.raw.channels == 0)
return -ENOTSUP;
}
break;
@ -586,7 +585,7 @@ int format_parse_param(const struct spa_pod *param, bool collect,
if (info.info.raw.channels) {
map->channels = SPA_MIN(info.info.raw.channels, CHANNELS_MAX);
for (i = 0; i < map->channels; i++)
map->map[i] = info.info.raw.position[i];
map->map[i] = spa_format_audio_raw_get_position(&info.info.raw, i);
}
}
return 0;
@ -634,8 +633,8 @@ const struct spa_pod *format_build_param(struct spa_pod_builder *b, uint32_t id,
SPA_FORMAT_AUDIO_channels, SPA_POD_Int(spec->channels), 0);
if (map && map->channels == spec->channels) {
uint32_t positions[SPA_AUDIO_MAX_CHANNELS];
channel_map_to_positions(map, positions);
uint32_t positions[spec->channels];
channel_map_to_positions(map, positions, spec->channels);
spa_pod_builder_add(b, SPA_FORMAT_AUDIO_position,
SPA_POD_Array(sizeof(uint32_t), SPA_TYPE_Id,
spec->channels, positions), 0);

View file

@ -196,7 +196,7 @@ enum channel_position channel_id2pa(uint32_t id, uint32_t *aux);
const char *channel_id2paname(uint32_t id, uint32_t *aux);
uint32_t channel_paname2id(const char *name, size_t size);
void channel_map_to_positions(const struct channel_map *map, uint32_t *pos);
void channel_map_to_positions(const struct channel_map *map, uint32_t *pos, uint32_t max_pos);
void channel_map_parse(const char *str, struct channel_map *map);
bool channel_map_valid(const struct channel_map *map);
void channel_map_parse_position(const char *str, struct channel_map *map);

View file

@ -12,6 +12,7 @@
#include <spa/utils/list.h>
#include <spa/utils/hook.h>
#include <spa/utils/string.h>
#include <spa/param/audio/raw-utils.h>
#include <pipewire/log.h>
#include <pipewire/map.h>
#include <pipewire/properties.h>
@ -226,14 +227,15 @@ int module_args_to_audioinfo_keys(struct impl *impl, struct pw_properties *props
info->channels, map.channels);
return -EINVAL;
}
channel_map_to_positions(&map, info->position);
channel_map_to_positions(&map, info->position, SPA_N_ELEMENTS(info->position));
pw_properties_set(props, key_channel_map, NULL);
} else {
if (info->channels == 0)
info->channels = impl->defs.sample_spec.channels;
if (info->channels == impl->defs.channel_map.channels) {
channel_map_to_positions(&impl->defs.channel_map, info->position);
channel_map_to_positions(&impl->defs.channel_map,
info->position, SPA_N_ELEMENTS(info->position));
} else if (info->channels == 1) {
info->position[0] = SPA_AUDIO_CHANNEL_MONO;
} else if (info->channels == 2) {
@ -242,7 +244,7 @@ int module_args_to_audioinfo_keys(struct impl *impl, struct pw_properties *props
} else {
/* FIXME add more mappings */
for (i = 0; i < info->channels; i++)
info->position[i] = SPA_AUDIO_CHANNEL_UNKNOWN;
spa_format_audio_raw_set_position(info, i, SPA_AUDIO_CHANNEL_UNKNOWN);
}
if (info->position[0] == SPA_AUDIO_CHANNEL_UNKNOWN)
info->flags |= SPA_AUDIO_FLAG_UNPOSITIONED;
@ -288,7 +290,7 @@ void audioinfo_to_properties(struct spa_audio_info_raw *info, struct pw_properti
p = s = alloca(info->channels * 8);
for (i = 0; i < info->channels; i++)
p += spa_scnprintf(p, 8, "%s%s", i == 0 ? "" : ", ",
channel_id2name(info->position[i]));
channel_id2name(spa_format_audio_raw_get_position(info, i)));
pw_properties_setf(props, SPA_KEY_AUDIO_POSITION, "[ %s ]", s);
}
}

View file

@ -754,7 +754,8 @@ static int create_pulse_stream(struct impl *impl)
map.channels = impl->info.channels;
for (i = 0; i < map.channels; i++)
map.map[i] = (pa_channel_position_t)channel_id2pa(impl->info.position[i], &aux);
map.map[i] = (pa_channel_position_t)channel_id2pa(
spa_format_audio_raw_get_position(&impl->info, i), &aux);
snprintf(stream_name, sizeof(stream_name), _("Tunnel for %s@%s"),
pw_get_user_name(), pw_get_host_name());

View file

@ -215,16 +215,16 @@ static const struct spa_audio_layout_info layouts[] = {
{ SPA_AUDIO_LAYOUT_7_1 },
};
static void default_layout(uint32_t channels, uint32_t *position)
static void default_layout(uint32_t channels, uint32_t *position, uint32_t max_position)
{
SPA_FOR_EACH_ELEMENT_VAR(layouts, l) {
if (l->n_channels == channels) {
for (uint32_t i = 0; i < l->n_channels; i++)
for (uint32_t i = 0; i < l->n_channels && i < max_position; i++)
position[i] = l->position[i];
return;
}
}
for (uint32_t i = 0; i < channels; i++)
for (uint32_t i = 0; i < channels && i < max_position; i++)
position[i] = SPA_AUDIO_CHANNEL_AUX0 + i;
}
@ -276,7 +276,9 @@ struct vban_stream *vban_stream_new(struct pw_core *core,
case SPA_MEDIA_SUBTYPE_raw:
parse_audio_info(props, &impl->info.info.raw);
if (SPA_FLAG_IS_SET(impl->info.info.raw.flags, SPA_AUDIO_FLAG_UNPOSITIONED))
default_layout(impl->info.info.raw.channels, impl->info.info.raw.position);
default_layout(impl->info.info.raw.channels,
impl->info.info.raw.position,
SPA_N_ELEMENTS(impl->info.info.raw.position));
impl->stream_info = impl->info;
impl->format_info = find_audio_format_info(&impl->info);
if (impl->format_info == NULL) {

View file

@ -192,7 +192,7 @@ static void pw_properties_from_avahi_string(const char *key, const char *value,
spa_zero(channel_map);
channel_map_parse(value, &channel_map);
channel_map_to_positions(&channel_map, pos);
channel_map_to_positions(&channel_map, pos, CHANNELS_MAX);
p = s = alloca(4 + channel_map.channels * 8);
p += spa_scnprintf(p, 2, "[");