mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-10-29 05:40:27 -04:00
*: Missing bounds checks in POD handling
There were missing bounds checks for ill-formed POD all over the place.
This commit is contained in:
parent
7ac94f1a69
commit
fb315b9050
7 changed files with 104 additions and 19 deletions
|
|
@ -39,10 +39,14 @@ spa_debug_strbuf_format_value(struct spa_strbuf *buffer, const struct spa_type_i
|
|||
|
||||
switch (type) {
|
||||
case SPA_TYPE_Bool:
|
||||
if (size < sizeof(int32_t))
|
||||
goto bad_body;
|
||||
spa_strbuf_append(buffer, "%s", *(int32_t *) body ? "true" : "false");
|
||||
break;
|
||||
case SPA_TYPE_Id:
|
||||
{
|
||||
if (size < sizeof(uint32_t))
|
||||
goto bad_body;
|
||||
uint32_t value = *(uint32_t *) body;
|
||||
const char *str = spa_debug_type_find_short_name(info, value);
|
||||
char tmp[64];
|
||||
|
|
@ -54,28 +58,42 @@ spa_debug_strbuf_format_value(struct spa_strbuf *buffer, const struct spa_type_i
|
|||
break;
|
||||
}
|
||||
case SPA_TYPE_Int:
|
||||
if (size < sizeof(int32_t))
|
||||
goto bad_body;
|
||||
spa_strbuf_append(buffer, "%d", *(int32_t *) body);
|
||||
break;
|
||||
case SPA_TYPE_Long:
|
||||
if (size < sizeof(int64_t))
|
||||
goto bad_body;
|
||||
spa_strbuf_append(buffer, "%" PRIi64, *(int64_t *) body);
|
||||
break;
|
||||
case SPA_TYPE_Float:
|
||||
if (size < sizeof(float))
|
||||
goto bad_body;
|
||||
spa_strbuf_append(buffer, "%f", *(float *) body);
|
||||
break;
|
||||
case SPA_TYPE_Double:
|
||||
if (size < sizeof(double))
|
||||
goto bad_body;
|
||||
spa_strbuf_append(buffer, "%f", *(double *) body);
|
||||
break;
|
||||
case SPA_TYPE_String:
|
||||
if (size < 1 || ((const char *)body)[size - 1] != '\0')
|
||||
goto bad_body;
|
||||
spa_strbuf_append(buffer, "%s", (char *) body);
|
||||
break;
|
||||
case SPA_TYPE_Rectangle:
|
||||
{
|
||||
if (size < sizeof(struct spa_rectangle))
|
||||
goto bad_body;
|
||||
struct spa_rectangle *r = (struct spa_rectangle *)body;
|
||||
spa_strbuf_append(buffer, "%" PRIu32 "x%" PRIu32, r->width, r->height);
|
||||
break;
|
||||
}
|
||||
case SPA_TYPE_Fraction:
|
||||
{
|
||||
if (size < sizeof(struct spa_fraction))
|
||||
goto bad_body;
|
||||
struct spa_fraction *f = (struct spa_fraction *)body;
|
||||
spa_strbuf_append(buffer, "%" PRIu32 "/%" PRIu32, f->num, f->denom);
|
||||
break;
|
||||
|
|
@ -91,6 +109,8 @@ spa_debug_strbuf_format_value(struct spa_strbuf *buffer, const struct spa_type_i
|
|||
void *p;
|
||||
struct spa_pod_array_body *b = (struct spa_pod_array_body *)body;
|
||||
int i = 0;
|
||||
if (size < sizeof(*b))
|
||||
goto bad_body;
|
||||
info = info && info->values ? info->values : info;
|
||||
spa_strbuf_append(buffer, "< ");
|
||||
SPA_POD_ARRAY_BODY_FOREACH(b, size, p) {
|
||||
|
|
@ -105,6 +125,8 @@ spa_debug_strbuf_format_value(struct spa_strbuf *buffer, const struct spa_type_i
|
|||
spa_strbuf_append(buffer, "INVALID type %d", type);
|
||||
break;
|
||||
}
|
||||
bad_body:
|
||||
spa_strbuf_append(buffer, "INVALID BODY type %d", type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -186,8 +186,12 @@ SPA_API_POD_COMPARE int spa_pod_compare_is_compatible_flags(uint32_t type, const
|
|||
{
|
||||
switch (type) {
|
||||
case SPA_TYPE_Int:
|
||||
if (size < sizeof(int32_t))
|
||||
return -EINVAL;
|
||||
return ((*(int32_t *) r1) & (*(int32_t *) r2)) != 0;
|
||||
case SPA_TYPE_Long:
|
||||
if (size < sizeof(int64_t))
|
||||
return -EINVAL;
|
||||
return ((*(int64_t *) r1) & (*(int64_t *) r2)) != 0;
|
||||
default:
|
||||
return -ENOTSUP;
|
||||
|
|
@ -197,18 +201,24 @@ SPA_API_POD_COMPARE int spa_pod_compare_is_compatible_flags(uint32_t type, const
|
|||
|
||||
|
||||
SPA_API_POD_COMPARE int spa_pod_compare_is_step_of(uint32_t type, const void *r1,
|
||||
const void *r2, uint32_t size SPA_UNUSED)
|
||||
const void *r2, uint32_t size)
|
||||
{
|
||||
switch (type) {
|
||||
case SPA_TYPE_Int:
|
||||
if (size < sizeof(int32_t))
|
||||
return -EINVAL;
|
||||
return *(int32_t *) r1 % *(int32_t *) r2 == 0;
|
||||
case SPA_TYPE_Long:
|
||||
if (size < sizeof(int64_t))
|
||||
return -EINVAL;
|
||||
return *(int64_t *) r1 % *(int64_t *) r2 == 0;
|
||||
case SPA_TYPE_Rectangle:
|
||||
{
|
||||
const struct spa_rectangle *rec1 = (struct spa_rectangle *) r1,
|
||||
*rec2 = (struct spa_rectangle *) r2;
|
||||
|
||||
if (size < sizeof(struct spa_rectangle))
|
||||
return -EINVAL;
|
||||
return (rec1->width % rec2->width == 0 &&
|
||||
rec1->height % rec2->height == 0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,9 +43,8 @@ spa_pod_simplify_merge(struct spa_pod_builder *b, const struct spa_pod *pod1, co
|
|||
struct spa_pod_frame f[2];
|
||||
int res = 0, count = 0;
|
||||
|
||||
if (pod1->type != pod2->type)
|
||||
return -ENOTSUP;
|
||||
if (pod1->type != SPA_TYPE_Object)
|
||||
if (!spa_pod_is_object(pod1) ||
|
||||
!spa_pod_is_object(pod2))
|
||||
return -ENOTSUP;
|
||||
|
||||
o1 = (const struct spa_pod_object*) pod1;
|
||||
|
|
|
|||
|
|
@ -1229,29 +1229,50 @@ static int diff_value(struct impl *impl, uint32_t type, uint32_t size, const voi
|
|||
{
|
||||
switch (type) {
|
||||
case SPA_TYPE_None:
|
||||
return 0;
|
||||
return INT_MAX;
|
||||
case SPA_TYPE_Bool:
|
||||
if (size < sizeof(int32_t))
|
||||
return INT_MAX;
|
||||
return (!!*(int32_t *)v1) - (!!*(int32_t *)v2);
|
||||
case SPA_TYPE_Id:
|
||||
if (size < sizeof(uint32_t))
|
||||
return INT_MAX;
|
||||
return (*(uint32_t *)v1) != (*(uint32_t *)v2);
|
||||
case SPA_TYPE_Int:
|
||||
if (size < sizeof(int32_t))
|
||||
return INT_MAX;
|
||||
return *(int32_t *)v1 - *(int32_t *)v2;
|
||||
case SPA_TYPE_Long:
|
||||
if (size < sizeof(int64_t))
|
||||
return INT_MAX;
|
||||
return *(int64_t *)v1 - *(int64_t *)v2;
|
||||
case SPA_TYPE_Float:
|
||||
if (size < sizeof(float))
|
||||
return INT_MAX;
|
||||
return (int)(*(float *)v1 - *(float *)v2);
|
||||
case SPA_TYPE_Double:
|
||||
if (size < sizeof(double))
|
||||
return INT_MAX;
|
||||
return (int)(*(double *)v1 - *(double *)v2);
|
||||
case SPA_TYPE_String:
|
||||
if (size < 1 ||
|
||||
((const char *)v1)[size - 1] != 0 ||
|
||||
((const char *)v2)[size - 1] != 0)
|
||||
return INT_MAX;
|
||||
return strcmp((char *)v1, (char *)v2);
|
||||
case SPA_TYPE_Bytes:
|
||||
return memcmp((char *)v1, (char *)v2, size);
|
||||
case SPA_TYPE_Rectangle:
|
||||
{
|
||||
const struct spa_rectangle *rec1 = (struct spa_rectangle *) v1,
|
||||
*rec2 = (struct spa_rectangle *) v2;
|
||||
uint64_t n1 = ((uint64_t) rec1->width) * rec1->height;
|
||||
uint64_t n2 = ((uint64_t) rec2->width) * rec2->height;
|
||||
const struct spa_rectangle *rec1, *rec2;
|
||||
uint64_t n1, n2;
|
||||
|
||||
if (size < sizeof(*rec1))
|
||||
return INT_MAX;
|
||||
rec1 = (struct spa_rectangle *) v1;
|
||||
rec2 = (struct spa_rectangle *) v2;
|
||||
n1 = ((uint64_t) rec1->width) * rec1->height;
|
||||
n2 = ((uint64_t) rec2->width) * rec2->height;
|
||||
if (rec1->width == rec2->width && rec1->height == rec2->height)
|
||||
return 0;
|
||||
else if (n1 < n2)
|
||||
|
|
@ -1259,15 +1280,19 @@ static int diff_value(struct impl *impl, uint32_t type, uint32_t size, const voi
|
|||
else if (n1 > n2)
|
||||
return n1 - n2;
|
||||
else if (rec1->width == rec2->width)
|
||||
return (int)rec1->height - (int)rec2->height;
|
||||
return (int32_t)rec1->height - (int32_t)rec2->height;
|
||||
else
|
||||
return (int)rec1->width - (int)rec2->width;
|
||||
return (int32_t)rec1->width - (int32_t)rec2->width;
|
||||
}
|
||||
case SPA_TYPE_Fraction:
|
||||
{
|
||||
const struct spa_fraction *f1 = (struct spa_fraction *) v1,
|
||||
*f2 = (struct spa_fraction *) v2;
|
||||
const struct spa_fraction *f1, *f2;
|
||||
uint64_t n1, n2;
|
||||
|
||||
if (size < sizeof(*f1))
|
||||
return INT_MAX;
|
||||
f1 = (struct spa_fraction *) v1;
|
||||
f2 = (struct spa_fraction *) v2;
|
||||
n1 = ((uint64_t) f1->num) * f2->denom;
|
||||
n2 = ((uint64_t) f2->num) * f1->denom;
|
||||
return (int) (n1 - n2);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue