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; 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) { switch (choice_type) {
case SPA_CHOICE_Enum: case SPA_CHOICE_Enum:
return 2; *min = 2;
*max = UINT32_MAX;
break;
case SPA_CHOICE_Range: case SPA_CHOICE_Range:
return 3; *min = *max = 3;
break;
case SPA_CHOICE_Step: case SPA_CHOICE_Step:
return 4; *min = *max = 4;
break;
case SPA_CHOICE_None: case SPA_CHOICE_None:
case SPA_CHOICE_Flags: case SPA_CHOICE_Flags:
*min = *max = 1;
break;
default: default:
/* /*
* This must always return at least 1, because callers * 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. * 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, 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, const void *body, uint32_t *n_values, uint32_t *choice,
uint32_t *val_size, uint32_t *val_type) 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_size = child_size;
*val_type = pod->body.child.type; *val_type = pod->body.child.type;
*n_values = child_size ? (pod->pod.size - sizeof(pod->body)) / child_size : 0; *n_values = child_size ? (pod->pod.size - sizeof(pod->body)) / child_size : 0;
*choice = pod->body.type; *choice = pod->body.type;
if (*n_values < spa_pod_choice_min_values(*choice) || spa_pod_choice_n_values(*choice, &min, &max);
*val_size < spa_pod_type_size(*val_type)) if (*n_values < min || *val_size < spa_pod_type_size(*val_type))
*n_values = 0; *n_values = 0;
else if (*n_values > max)
*n_values = max;
return body; return body;
} }