From c64a34d93fd25e5bc134bb71aa1e4031891e283b Mon Sep 17 00:00:00 2001 From: Demi Marie Obenour Date: Thu, 24 Jul 2025 19:33:38 -0400 Subject: [PATCH] *: more type checks for POD Check that POD is correctly typed before using it. --- pipewire-alsa/alsa-plugins/ctl_pipewire.c | 5 +++++ spa/include/spa/param/audio/dsd-utils.h | 1 + spa/include/spa/param/audio/raw-utils.h | 1 + spa/include/spa/param/video/dsp-utils.h | 4 +++- spa/include/spa/param/video/raw-utils.h | 2 ++ spa/plugins/alsa/alsa-pcm-sink.c | 3 ++- spa/plugins/audioconvert/audioconvert.c | 10 ++++++++-- spa/plugins/audioconvert/test-source.c | 11 ++++++++++- spa/plugins/bluez5/media-sink.c | 2 ++ spa/plugins/bluez5/media-source.c | 2 ++ spa/plugins/filter-graph/filter-graph.c | 3 +++ spa/plugins/v4l2/v4l2-source.c | 2 ++ spa/plugins/videoconvert/videoadapter.c | 4 ++++ spa/plugins/videoconvert/videoconvert-ffmpeg.c | 18 ++++-------------- spa/plugins/videotestsrc/videotestsrc.c | 6 ++++-- spa/plugins/volume/volume.c | 6 ++++-- spa/plugins/vulkan/vulkan-compute-source.c | 6 ++++-- src/modules/module-filter-chain.c | 2 +- src/modules/module-protocol-pulse/collect.c | 4 ++-- src/modules/module-protocol-pulse/volume.c | 3 +++ 20 files changed, 67 insertions(+), 28 deletions(-) diff --git a/pipewire-alsa/alsa-plugins/ctl_pipewire.c b/pipewire-alsa/alsa-plugins/ctl_pipewire.c index 7fcfd5726..b492c7caf 100644 --- a/pipewire-alsa/alsa-plugins/ctl_pipewire.c +++ b/pipewire-alsa/alsa-plugins/ctl_pipewire.c @@ -834,6 +834,11 @@ static void parse_props(struct global *g, const struct spa_pod *param, bool devi struct spa_pod_object *obj = (struct spa_pod_object *) param; snd_ctl_pipewire_t *ctl = g->ctl; + if (!spa_pod_is_object_type(param, SPA_TYPE_OBJECT_Props)) { + pw_log_warn("cannot parse %d props", g->id); + return; + } + SPA_POD_OBJECT_FOREACH(obj, prop) { switch (prop->key) { case SPA_PROP_volume: diff --git a/spa/include/spa/param/audio/dsd-utils.h b/spa/include/spa/param/audio/dsd-utils.h index 980bdf971..c7407b6b6 100644 --- a/spa/include/spa/param/audio/dsd-utils.h +++ b/spa/include/spa/param/audio/dsd-utils.h @@ -42,6 +42,7 @@ spa_format_audio_dsd_parse(const struct spa_pod *format, struct spa_audio_info_d SPA_FORMAT_AUDIO_channels, SPA_POD_OPT_Int(&info->channels), SPA_FORMAT_AUDIO_position, SPA_POD_OPT_Pod(&position)); if (position == NULL || + !spa_pod_is_array(position) || !spa_pod_copy_array(position, SPA_TYPE_Id, info->position, SPA_AUDIO_MAX_CHANNELS)) SPA_FLAG_SET(info->flags, SPA_AUDIO_FLAG_UNPOSITIONED); diff --git a/spa/include/spa/param/audio/raw-utils.h b/spa/include/spa/param/audio/raw-utils.h index c36491445..e359a5592 100644 --- a/spa/include/spa/param/audio/raw-utils.h +++ b/spa/include/spa/param/audio/raw-utils.h @@ -41,6 +41,7 @@ spa_format_audio_raw_parse(const struct spa_pod *format, struct spa_audio_info_r SPA_FORMAT_AUDIO_channels, SPA_POD_OPT_Int(&info->channels), SPA_FORMAT_AUDIO_position, SPA_POD_OPT_Pod(&position)); if (position == NULL || + !spa_pod_is_array(position) || !spa_pod_copy_array(position, SPA_TYPE_Id, info->position, SPA_AUDIO_MAX_CHANNELS)) SPA_FLAG_SET(info->flags, SPA_AUDIO_FLAG_UNPOSITIONED); diff --git a/spa/include/spa/param/video/dsp-utils.h b/spa/include/spa/param/video/dsp-utils.h index 26018cab9..ed2432166 100644 --- a/spa/include/spa/param/video/dsp-utils.h +++ b/spa/include/spa/param/video/dsp-utils.h @@ -31,8 +31,10 @@ SPA_API_VIDEO_DSP_UTILS int spa_format_video_dsp_parse(const struct spa_pod *format, struct spa_video_info_dsp *info) { - info->flags = SPA_VIDEO_FLAG_NONE; const struct spa_pod_prop *mod_prop; + info->flags = SPA_VIDEO_FLAG_NONE; + if (!spa_pod_is_object_type(format, SPA_TYPE_OBJECT_Format)) + return -EINVAL; if ((mod_prop = spa_pod_find_prop (format, NULL, SPA_FORMAT_VIDEO_modifier)) != NULL) { info->flags |= SPA_VIDEO_FLAG_MODIFIER; if ((mod_prop->flags & SPA_POD_PROP_FLAG_DONT_FIXATE) == SPA_POD_PROP_FLAG_DONT_FIXATE) diff --git a/spa/include/spa/param/video/raw-utils.h b/spa/include/spa/param/video/raw-utils.h index 738f64cf4..6b2ee0292 100644 --- a/spa/include/spa/param/video/raw-utils.h +++ b/spa/include/spa/param/video/raw-utils.h @@ -33,6 +33,8 @@ spa_format_video_raw_parse(const struct spa_pod *format, { info->flags = SPA_VIDEO_FLAG_NONE; const struct spa_pod_prop *mod_prop; + if (!spa_pod_is_object_type(format, SPA_TYPE_OBJECT_Format)) + return -EINVAL; if ((mod_prop = spa_pod_find_prop (format, NULL, SPA_FORMAT_VIDEO_modifier)) != NULL) { info->flags |= SPA_VIDEO_FLAG_MODIFIER; if ((mod_prop->flags & SPA_POD_PROP_FLAG_DONT_FIXATE) == SPA_POD_PROP_FLAG_DONT_FIXATE) diff --git a/spa/plugins/alsa/alsa-pcm-sink.c b/spa/plugins/alsa/alsa-pcm-sink.c index 6c340cc6f..e8e621fa0 100644 --- a/spa/plugins/alsa/alsa-pcm-sink.c +++ b/spa/plugins/alsa/alsa-pcm-sink.c @@ -257,7 +257,8 @@ static int impl_node_set_param(void *object, uint32_t id, uint32_t flags, SPA_PROP_iec958Codecs, SPA_POD_OPT_Pod(&iec958_codecs), SPA_PROP_params, SPA_POD_OPT_Pod(¶ms)); - if ((this->is_iec958 || this->is_hdmi) && iec958_codecs != NULL) { + if ((this->is_iec958 || this->is_hdmi) && iec958_codecs != NULL && + spa_pod_is_array(iec958_codecs)) { uint32_t i, codecs[16], n_codecs; n_codecs = spa_pod_copy_array(iec958_codecs, SPA_TYPE_Id, codecs, SPA_N_ELEMENTS(codecs)); diff --git a/spa/plugins/audioconvert/audioconvert.c b/spa/plugins/audioconvert/audioconvert.c index 5c411efcf..10301b2d2 100644 --- a/spa/plugins/audioconvert/audioconvert.c +++ b/spa/plugins/audioconvert/audioconvert.c @@ -1657,6 +1657,9 @@ static int apply_props(struct impl *this, const struct spa_pod *param) spa_zero(vrp); + if (!spa_pod_is_object_type(param, SPA_TYPE_OBJECT_Props)) + return -EINVAL; + SPA_POD_OBJECT_FOREACH(obj, prop) { switch (prop->key) { case SPA_PROP_volume: @@ -1827,7 +1830,9 @@ static int apply_midi(struct impl *this, const struct spa_pod *value) uint8_t data[8]; int size; - size = spa_ump_to_midi(SPA_POD_BODY(value), SPA_POD_BODY_SIZE(value), + if (!spa_pod_is_bytes(value)) + return -EINVAL; + size = spa_ump_to_midi(SPA_POD_BODY(value), value->size, data, sizeof(data)); if (size < 3) return -EINVAL; @@ -1973,7 +1978,8 @@ static int node_set_param_props(struct impl *this, uint32_t flags, if (param == NULL) return 0; - + if (!spa_pod_is_object_type(param, SPA_TYPE_OBJECT_Props)) + return -EINVAL; this->filter_props_count = 0; spa_list_for_each_safe(g, t, &this->active_graphs, link) { diff --git a/spa/plugins/audioconvert/test-source.c b/spa/plugins/audioconvert/test-source.c index a11861c86..bd62c17b1 100644 --- a/spa/plugins/audioconvert/test-source.c +++ b/spa/plugins/audioconvert/test-source.c @@ -251,13 +251,19 @@ static int apply_props(struct impl *this, const struct spa_pod *param) struct props *p = &this->props; int changed = 0; + if (!spa_pod_is_object_type(param, SPA_TYPE_OBJECT_Props)) + return -EINVAL; SPA_POD_OBJECT_FOREACH(obj, prop) { switch (prop->key) { case SPA_PROP_volume: + if (!spa_pod_is_float(&prop->value)) + return -EINVAL; if (spa_pod_get_float(&prop->value, &p->volume) == 0) changed++; break; case SPA_PROP_mute: + if (!spa_pod_is_bool(&prop->value)) + return -EINVAL; if (spa_pod_get_bool(&prop->value, &p->mute) == 0) changed++; break; @@ -272,6 +278,7 @@ static int impl_node_set_param(void *object, uint32_t id, uint32_t flags, const struct spa_pod *param) { struct impl *this = object; + int res; spa_return_val_if_fail(this != NULL, -EINVAL); @@ -281,7 +288,9 @@ static int impl_node_set_param(void *object, uint32_t id, uint32_t flags, props_reset(&this->props); return 0; } - if (apply_props(this, param) > 0) { + if ((res = apply_props(this, param)) < 0) + return res; + if (res > 0) { this->info.change_mask = SPA_NODE_CHANGE_MASK_PARAMS; this->params[1].flags ^= SPA_PARAM_INFO_SERIAL; emit_info(this, false); diff --git a/spa/plugins/bluez5/media-sink.c b/spa/plugins/bluez5/media-sink.c index f5708d080..79ab61420 100644 --- a/spa/plugins/bluez5/media-sink.c +++ b/spa/plugins/bluez5/media-sink.c @@ -567,6 +567,8 @@ static int impl_node_set_param(void *object, uint32_t id, uint32_t flags, case SPA_PARAM_Props: { int res, codec_res = 0; + if (!spa_pod_is_object_type(param, SPA_TYPE_OBJECT_Props)) + return -EINVAL; res = apply_props(this, param); if (this->codec_props && this->codec->set_props) { codec_res = this->codec->set_props(this->codec_props, param); diff --git a/spa/plugins/bluez5/media-source.c b/spa/plugins/bluez5/media-source.c index dc3e53a7b..be508712a 100644 --- a/spa/plugins/bluez5/media-source.c +++ b/spa/plugins/bluez5/media-source.c @@ -383,6 +383,8 @@ static int impl_node_set_param(void *object, uint32_t id, uint32_t flags, case SPA_PARAM_Props: { int res, codec_res = 0; + if (!spa_pod_is_object_type(param, SPA_TYPE_OBJECT_Props)) + return -EINVAL; res = apply_props(this, param); if (this->codec_props && this->codec->set_props) { codec_res = this->codec->set_props(this->codec_props, param); diff --git a/spa/plugins/filter-graph/filter-graph.c b/spa/plugins/filter-graph/filter-graph.c index 718bc542d..3356ca6b2 100644 --- a/spa/plugins/filter-graph/filter-graph.c +++ b/spa/plugins/filter-graph/filter-graph.c @@ -714,6 +714,9 @@ static int impl_set_props(void *object, enum spa_direction direction, const stru struct volume *vol = &graph->volume[direction]; bool do_volume = false; + if (!spa_pod_is_object_type(props, SPA_TYPE_OBJECT_Props)) + return -EINVAL; + spa_pod_dynamic_builder_init(&b, buf, sizeof(buf), 1024); spa_pod_builder_push_object(&b.b, &f[0], SPA_TYPE_OBJECT_Props, SPA_PARAM_Props); diff --git a/spa/plugins/v4l2/v4l2-source.c b/spa/plugins/v4l2/v4l2-source.c index 2eb66b3da..2aad6905f 100644 --- a/spa/plugins/v4l2/v4l2-source.c +++ b/spa/plugins/v4l2/v4l2-source.c @@ -392,6 +392,8 @@ static int impl_node_set_param(void *object, struct spa_pod_object *obj = (struct spa_pod_object *) param; struct spa_pod_prop *prop; + if (!spa_pod_is_object_type(param, SPA_TYPE_OBJECT_Props)) + return -EINVAL; if (param == NULL) { reset_props(p); return 0; diff --git a/spa/plugins/videoconvert/videoadapter.c b/spa/plugins/videoconvert/videoadapter.c index ccf9365f3..1ec3017be 100644 --- a/spa/plugins/videoconvert/videoadapter.c +++ b/spa/plugins/videoconvert/videoadapter.c @@ -870,6 +870,8 @@ static int impl_node_set_param(void *object, uint32_t id, uint32_t flags, case SPA_PARAM_Props: { + if (!spa_pod_is_object_type(param, SPA_TYPE_OBJECT_Props)) + return -EINVAL; int in_set_param = ++this->in_set_param; res = spa_node_set_param(this->follower, id, flags, param); if (this->target != this->follower && this->in_set_param == in_set_param) @@ -880,6 +882,8 @@ static int impl_node_set_param(void *object, uint32_t id, uint32_t flags, break; } case SPA_PARAM_ProcessLatency: + if (!spa_pod_is_object_type(param, SPA_TYPE_OBJECT_ParamProcessLatency)) + return -EINVAL; res = spa_node_set_param(this->follower, id, flags, param); break; default: diff --git a/spa/plugins/videoconvert/videoconvert-ffmpeg.c b/spa/plugins/videoconvert/videoconvert-ffmpeg.c index 525b2c933..2aa1f621e 100644 --- a/spa/plugins/videoconvert/videoconvert-ffmpeg.c +++ b/spa/plugins/videoconvert/videoconvert-ffmpeg.c @@ -711,6 +711,8 @@ static int apply_props(struct impl *this, const struct spa_pod *param) struct spa_pod_object *obj = (struct spa_pod_object *) param; int changed = 0; + if (!spa_pod_is_object_type(param, SPA_TYPE_OBJECT_Props)) + return -EINVAL; SPA_POD_OBJECT_FOREACH(obj, prop) { switch (prop->key) { case SPA_PROP_params: @@ -807,9 +809,6 @@ static int node_set_param_port_config(struct impl *this, uint32_t flags, bool monitor = false, control = false; int res; - if (param == NULL) - return 0; - if (spa_pod_parse_object(param, SPA_TYPE_OBJECT_ParamPortConfig, NULL, SPA_PARAM_PORT_CONFIG_direction, SPA_POD_Id(&direction), @@ -831,15 +830,6 @@ static int node_set_param_port_config(struct impl *this, uint32_t flags, return reconfigure_mode(this, mode, direction, monitor, control, infop); } -static int node_set_param_props(struct impl *this, uint32_t flags, - const struct spa_pod *param) -{ - if (param == NULL) - return 0; - - apply_props(this, param); - return 0; -} static int impl_node_set_param(void *object, uint32_t id, uint32_t flags, const struct spa_pod *param) { @@ -850,10 +840,10 @@ static int impl_node_set_param(void *object, uint32_t id, uint32_t flags, switch (id) { case SPA_PARAM_PortConfig: - res = node_set_param_port_config(this, flags, param); + res = param ? node_set_param_port_config(this, flags, param) : 0; break; case SPA_PARAM_Props: - res = node_set_param_props(this, flags, param); + res = param ? apply_props(this, param) : 0; break; default: return -ENOENT; diff --git a/spa/plugins/videotestsrc/videotestsrc.c b/spa/plugins/videotestsrc/videotestsrc.c index db5c90113..dc37c9c19 100644 --- a/spa/plugins/videotestsrc/videotestsrc.c +++ b/spa/plugins/videotestsrc/videotestsrc.c @@ -232,15 +232,17 @@ static int impl_node_set_param(void *object, uint32_t id, uint32_t flags, { struct props *p = &this->props; struct port *port = &this->port; + int res; if (param == NULL) { reset_props(p); return 0; } - spa_pod_parse_object(param, + if ((res = spa_pod_parse_object(param, SPA_TYPE_OBJECT_Props, NULL, SPA_PROP_live, SPA_POD_OPT_Bool(&p->live), - SPA_PROP_patternType, SPA_POD_OPT_Int(&p->pattern)); + SPA_PROP_patternType, SPA_POD_OPT_Int(&p->pattern))) < 0) + return res; if (p->live) port->info.flags |= SPA_PORT_FLAG_LIVE; diff --git a/spa/plugins/volume/volume.c b/spa/plugins/volume/volume.c index 164e46a6a..8abe9a080 100644 --- a/spa/plugins/volume/volume.c +++ b/spa/plugins/volume/volume.c @@ -187,15 +187,17 @@ static int impl_node_set_param(void *object, uint32_t id, uint32_t flags, case SPA_PARAM_Props: { struct props *p = &this->props; + int res; if (param == NULL) { reset_props(p); return 0; } - spa_pod_parse_object(param, + if ((res = spa_pod_parse_object(param, SPA_TYPE_OBJECT_Props, NULL, SPA_PROP_volume, SPA_POD_OPT_Float(&p->volume), - SPA_PROP_mute, SPA_POD_OPT_Bool(&p->mute)); + SPA_PROP_mute, SPA_POD_OPT_Bool(&p->mute))) < 0) + return res; break; } default: diff --git a/spa/plugins/vulkan/vulkan-compute-source.c b/spa/plugins/vulkan/vulkan-compute-source.c index 1daf3b47c..d57c03a8b 100644 --- a/spa/plugins/vulkan/vulkan-compute-source.c +++ b/spa/plugins/vulkan/vulkan-compute-source.c @@ -218,14 +218,16 @@ static int impl_node_set_param(void *object, uint32_t id, uint32_t flags, { struct props *p = &this->props; struct port *port = &this->port; + int res; if (param == NULL) { reset_props(p); return 0; } - spa_pod_parse_object(param, + if ((res = spa_pod_parse_object(param, SPA_TYPE_OBJECT_Props, NULL, - SPA_PROP_live, SPA_POD_OPT_Bool(&p->live)); + SPA_PROP_live, SPA_POD_OPT_Bool(&p->live))) < 0) + return res; if (p->live) port->info.flags |= SPA_PORT_FLAG_LIVE; diff --git a/src/modules/module-filter-chain.c b/src/modules/module-filter-chain.c index 6c2f16200..a40457e6e 100644 --- a/src/modules/module-filter-chain.c +++ b/src/modules/module-filter-chain.c @@ -1476,7 +1476,7 @@ static void param_changed(struct impl *impl, uint32_t id, const struct spa_pod * break; } case SPA_PARAM_Props: - if (param != NULL) + if (param != NULL && spa_pod_is_object_type(param, SPA_TYPE_OBJECT_Props)) spa_filter_graph_set_props(impl->graph, direction, param); break; case SPA_PARAM_Latency: diff --git a/src/modules/module-protocol-pulse/collect.c b/src/modules/module-protocol-pulse/collect.c index 32e30d120..300eee262 100644 --- a/src/modules/module-protocol-pulse/collect.c +++ b/src/modules/module-protocol-pulse/collect.c @@ -169,7 +169,7 @@ uint32_t collect_profile_info(struct pw_manager_object *card, struct card_info * SPA_PARAM_PROFILE_description, SPA_POD_OPT_String(&pi->description), SPA_PARAM_PROFILE_priority, SPA_POD_OPT_Int(&pi->priority), SPA_PARAM_PROFILE_available, SPA_POD_OPT_Id(&pi->available), - SPA_PARAM_PROFILE_classes, SPA_POD_OPT_Pod(&classes)) < 0) { + SPA_PARAM_PROFILE_classes, SPA_POD_OPT_PodStruct(&classes)) < 0) { continue; } if (pi->description == NULL) @@ -246,7 +246,7 @@ static void collect_device_info(struct pw_manager_object *device, struct pw_mana SPA_TYPE_OBJECT_ParamRoute, NULL, SPA_PARAM_ROUTE_index, SPA_POD_Int(&index), SPA_PARAM_ROUTE_device, SPA_POD_Int(&dev), - SPA_PARAM_ROUTE_props, SPA_POD_OPT_Pod(&props)) < 0) + SPA_PARAM_ROUTE_props, SPA_POD_OPT_PodObject(&props)) < 0) continue; if (dev != dev_info->device) continue; diff --git a/src/modules/module-protocol-pulse/volume.c b/src/modules/module-protocol-pulse/volume.c index de71baa53..3dc7d2666 100644 --- a/src/modules/module-protocol-pulse/volume.c +++ b/src/modules/module-protocol-pulse/volume.c @@ -32,6 +32,9 @@ int volume_parse_param(const struct spa_pod *param, struct volume_info *info, bo struct spa_pod_object *obj = (struct spa_pod_object *) param; struct spa_pod_prop *prop; + if (!spa_pod_is_object_type(param, SPA_TYPE_OBJECT_Props)) + return -EINVAL; + SPA_POD_OBJECT_FOREACH(obj, prop) { switch (prop->key) { case SPA_PROP_volume: