spa: enforce max values for choice as well

Make sure we don't return more values than expected for the choice
type.

Fixes #4964
This commit is contained in:
Wim Taymans 2025-11-06 12:25:55 +01:00
parent 1191c18641
commit f4b3536b9b

View file

@ -78,25 +78,34 @@ SPA_API_POD_BODY uint32_t spa_pod_type_size(uint32_t type)
return 0;
}
SPA_API_POD_BODY uint32_t spa_pod_choice_min_values(uint32_t choice_type)
SPA_API_POD_BODY int spa_pod_choice_n_values(uint32_t choice_type, uint32_t *min, uint32_t *max)
{
switch (choice_type) {
case SPA_CHOICE_Enum:
return 2;
*min = 2;
*max = UINT32_MAX;
break;
case SPA_CHOICE_Range:
return 3;
*min = *max = 3;
break;
case SPA_CHOICE_Step:
return 4;
*min = *max = 4;
break;
case SPA_CHOICE_None:
case SPA_CHOICE_Flags:
*min = *max = 1;
break;
default:
/*
* This must always return at least 1, because callers
* assume that n_vals >= spa_pod_choice_min_values()
* assume that n_vals >= spa_pod_choice_n_values()
* mean that n_vals is at least 1.
*/
return 1;
*min = 1;
*max = UINT32_MAX;
return 0;
}
return 1;
}
SPA_API_POD_BODY int spa_pod_body_from_data(void *data, size_t maxsize, off_t offset, size_t size,
@ -389,14 +398,16 @@ SPA_API_POD_BODY const void *spa_pod_choice_body_get_values(const struct spa_pod
const void *body, uint32_t *n_values, uint32_t *choice,
uint32_t *val_size, uint32_t *val_type)
{
uint32_t child_size = pod->body.child.size;
uint32_t child_size = pod->body.child.size, min, max;
*val_size = child_size;
*val_type = pod->body.child.type;
*n_values = child_size ? (pod->pod.size - sizeof(pod->body)) / child_size : 0;
*choice = pod->body.type;
if (*n_values < spa_pod_choice_min_values(*choice) ||
*val_size < spa_pod_type_size(*val_type))
spa_pod_choice_n_values(*choice, &min, &max);
if (*n_values < min || *val_size < spa_pod_type_size(*val_type))
*n_values = 0;
else if (*n_values > max)
*n_values = max;
return body;
}