spa: add some more POD tests

Check if the pod size is at least big enough to hold 1 item when getting
array or choice items.

Check that the number of choice values is at least enough to handle the
given choice type. Remove some redundant checks.
This commit is contained in:
Wim Taymans 2025-10-31 11:39:41 +01:00
parent 77a5100280
commit 95fb03c8e3
4 changed files with 30 additions and 9 deletions

View file

@ -164,8 +164,7 @@ SPA_API_DEBUG_FORMAT int spa_debugc_format(struct spa_debug_context *ctx, int in
type = val->type; type = val->type;
size = val->size; size = val->size;
if (type < SPA_TYPE_None || type >= _SPA_TYPE_LAST || n_vals < 1 || if (type < SPA_TYPE_None || type >= _SPA_TYPE_LAST || n_vals < 1)
size < spa_pod_type_size(type))
continue; continue;
vals = SPA_POD_BODY(val); vals = SPA_POD_BODY(val);

View file

@ -78,6 +78,27 @@ 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)
{
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)
{ {
@ -333,6 +354,8 @@ SPA_API_POD_BODY const void *spa_pod_array_body_get_values(const struct spa_pod_
*n_values = child_size ? (arr->pod.size - sizeof(arr->body)) / child_size : 0; *n_values = child_size ? (arr->pod.size - sizeof(arr->body)) / child_size : 0;
*val_size = child_size; *val_size = child_size;
*val_type = arr->body.child.type; *val_type = arr->body.child.type;
if (*val_size < spa_pod_type_size(*val_type))
*n_values = 0;
return body; return body;
} }
@ -371,8 +394,9 @@ SPA_API_POD_BODY const void *spa_pod_choice_body_get_values(const struct spa_pod
*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 (*choice == SPA_CHOICE_None) if (*n_values < spa_pod_choice_min_values(*choice) ||
*n_values = SPA_MIN(1u, *n_values); *val_size < spa_pod_type_size(*val_type))
*n_values = 0;
return body; return body;
} }

View file

@ -82,7 +82,7 @@ spa_pod_filter_prop(struct spa_pod_builder *b,
v1 = spa_pod_get_values(&p1->value, &nalt1, &p1c); v1 = spa_pod_get_values(&p1->value, &nalt1, &p1c);
v2 = spa_pod_get_values(&p2->value, &nalt2, &p2c); v2 = spa_pod_get_values(&p2->value, &nalt2, &p2c);
/* empty choices */ /* empty/invalid choices */
if (nalt1 < 1 || nalt2 < 1) if (nalt1 < 1 || nalt2 < 1)
return -EINVAL; return -EINVAL;
@ -95,8 +95,6 @@ spa_pod_filter_prop(struct spa_pod_builder *b,
/* incompatible property types */ /* incompatible property types */
if (type != v2->type || size != v2->size || p1->key != p2->key) if (type != v2->type || size != v2->size || p1->key != p2->key)
return -EINVAL; return -EINVAL;
if (size < spa_pod_type_size(type))
return -EINVAL;
/* start with copying the property */ /* start with copying the property */
spa_pod_builder_prop(b, p1->key, p1->flags & p2->flags); spa_pod_builder_prop(b, p1->key, p1->flags & p2->flags);
@ -406,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 (v->size < spa_pod_type_size(v->type)) if (nvals < 1)
continue; continue;
if (spa_pod_compare_is_valid_choice(v->type, v->size, if (spa_pod_compare_is_valid_choice(v->type, v->size,

View file

@ -228,7 +228,7 @@ SPA_API_POD_ITER struct spa_pod *spa_pod_get_values(const struct spa_pod *pod,
spa_pod_choice_body_get_values(p, SPA_POD_BODY_CONST(p), n_vals, choice, &size, &type); spa_pod_choice_body_get_values(p, SPA_POD_BODY_CONST(p), n_vals, choice, &size, &type);
return (struct spa_pod*)&p->body.child; return (struct spa_pod*)&p->body.child;
} else { } else {
*n_vals = 1; *n_vals = pod->size < spa_pod_type_size(pod->type) ? 0 : 1;
*choice = SPA_CHOICE_None; *choice = SPA_CHOICE_None;
return (struct spa_pod*)pod; return (struct spa_pod*)pod;
} }