mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-10-29 05:40:27 -04:00
pod: Check that choices have enough values for their kind
Prevent out of bounds reads when a choice is too small for the type of choice that it is. Add a utility function to help catch this case.
This commit is contained in:
parent
5853e1150b
commit
fcfe01a0be
3 changed files with 26 additions and 2 deletions
|
|
@ -116,6 +116,27 @@ SPA_API_POD_BODY uint32_t spa_pod_type_align(uint32_t type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SPA_API_POD_BODY uint32_t spa_pod_choice_min_values(uint32_t choice_type)
|
||||||
|
{
|
||||||
|
switch (choice_type) {
|
||||||
|
case SPA_CHOICE_Enum:
|
||||||
|
return 2;
|
||||||
|
case SPA_CHOICE_Range:
|
||||||
|
return 3;
|
||||||
|
case SPA_CHOICE_Step:
|
||||||
|
return 4;
|
||||||
|
case SPA_CHOICE_None:
|
||||||
|
case SPA_CHOICE_Flags:
|
||||||
|
default:
|
||||||
|
/*
|
||||||
|
* This must always return at least 1, because callers
|
||||||
|
* assume that n_vals >= spa_pod_choice_min_values()
|
||||||
|
* mean that n_vals is at least 1.
|
||||||
|
*/
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SPA_API_POD_BODY int spa_pod_body_from_data(void *data, size_t maxsize, off_t offset, size_t size,
|
SPA_API_POD_BODY int spa_pod_body_from_data(void *data, size_t maxsize, off_t offset, size_t size,
|
||||||
struct spa_pod *pod, const void **body)
|
struct spa_pod *pod, const void **body)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -226,6 +226,8 @@ SPA_API_POD_COMPARE int spa_pod_compare_is_in_range(uint32_t type, const void *v
|
||||||
SPA_API_POD_COMPARE int spa_pod_compare_is_valid_choice(uint32_t type, uint32_t size,
|
SPA_API_POD_COMPARE int spa_pod_compare_is_valid_choice(uint32_t type, uint32_t size,
|
||||||
const void *val, const void *vals, uint32_t n_vals, uint32_t choice)
|
const void *val, const void *vals, uint32_t n_vals, uint32_t choice)
|
||||||
{
|
{
|
||||||
|
if (n_vals < spa_pod_choice_min_values(choice))
|
||||||
|
return 0;
|
||||||
switch (choice) {
|
switch (choice) {
|
||||||
case SPA_CHOICE_None:
|
case SPA_CHOICE_None:
|
||||||
if (spa_pod_compare_value(type, val, vals, size) == 0)
|
if (spa_pod_compare_value(type, val, vals, size) == 0)
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,8 @@ spa_pod_filter_prop(struct spa_pod_builder *b,
|
||||||
v2 = spa_pod_get_values(&p2->value, &nalt2, &p2c);
|
v2 = spa_pod_get_values(&p2->value, &nalt2, &p2c);
|
||||||
|
|
||||||
/* empty or bogus choices */
|
/* empty or bogus choices */
|
||||||
if (nalt1 < 1 || nalt2 < 1)
|
if (nalt1 < spa_pod_choice_min_values(p1c) ||
|
||||||
|
nalt2 < spa_pod_choice_min_values(p2c))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
alt1 = SPA_POD_BODY(v1);
|
alt1 = SPA_POD_BODY(v1);
|
||||||
|
|
@ -403,7 +404,7 @@ SPA_API_POD_FILTER int spa_pod_filter_object_make(struct spa_pod_object *pod)
|
||||||
struct spa_pod *v = spa_pod_get_values(&res->value, &nvals, &choice);
|
struct spa_pod *v = spa_pod_get_values(&res->value, &nvals, &choice);
|
||||||
const void *vals = SPA_POD_BODY(v);
|
const void *vals = SPA_POD_BODY(v);
|
||||||
|
|
||||||
if (nvals < 1)
|
if (nvals < spa_pod_choice_min_values(choice))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (spa_pod_compare_is_valid_choice(v->type, v->size,
|
if (spa_pod_compare_is_valid_choice(v->type, v->size,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue