diff --git a/spa/include/spa/debug/format.h b/spa/include/spa/debug/format.h index 856e9954c..4abd36b1e 100644 --- a/spa/include/spa/debug/format.h +++ b/spa/include/spa/debug/format.h @@ -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; } diff --git a/spa/include/spa/pod/compare.h b/spa/include/spa/pod/compare.h index 84cc3eafd..6ac6b0799 100644 --- a/spa/include/spa/pod/compare.h +++ b/spa/include/spa/pod/compare.h @@ -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); } diff --git a/spa/include/spa/pod/simplify.h b/spa/include/spa/pod/simplify.h index dc7803194..8fbe7153c 100644 --- a/spa/include/spa/pod/simplify.h +++ b/spa/include/spa/pod/simplify.h @@ -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; diff --git a/spa/plugins/videoconvert/videoconvert-ffmpeg.c b/spa/plugins/videoconvert/videoconvert-ffmpeg.c index 3a0f3903c..2b2c62e83 100644 --- a/spa/plugins/videoconvert/videoconvert-ffmpeg.c +++ b/spa/plugins/videoconvert/videoconvert-ffmpeg.c @@ -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); diff --git a/src/modules/module-protocol-pulse/collect.c b/src/modules/module-protocol-pulse/collect.c index 720577216..1f0578026 100644 --- a/src/modules/module-protocol-pulse/collect.c +++ b/src/modules/module-protocol-pulse/collect.c @@ -524,8 +524,11 @@ uint32_t collect_transport_codec_info(struct pw_manager_object *card, if (iid != SPA_PROP_bluetoothAudioCodec) continue; - if (type->body.type != SPA_CHOICE_Enum || - type->body.child.type != SPA_TYPE_Int) + if (type->pod.size < sizeof(struct spa_pod_choice_body) + + 2 * sizeof(int32_t) || + type->body.type != SPA_CHOICE_Enum || + type->body.child.type != SPA_TYPE_Int || + type->body.child.size != sizeof(int32_t)) continue; /* diff --git a/src/modules/module-protocol-pulse/format.c b/src/modules/module-protocol-pulse/format.c index 34a835ef8..e3d438c93 100644 --- a/src/modules/module-protocol-pulse/format.c +++ b/src/modules/module-protocol-pulse/format.c @@ -683,7 +683,7 @@ static int add_int(struct format_info *info, const char *k, struct spa_pod *para return -ENOENT; val = spa_pod_get_values(&prop->value, &n_values, &choice); - if (val->type != SPA_TYPE_Int) + if (!spa_pod_is_int(val)) return -ENOTSUP; if (n_values == 0) diff --git a/src/tools/pw-dump.c b/src/tools/pw-dump.c index e04cf74e1..6b4e7b5ef 100644 --- a/src/tools/pw-dump.c +++ b/src/tools/pw-dump.c @@ -341,12 +341,16 @@ static void put_pod_value(struct data *d, const char *key, const struct spa_type put_key(d, key); switch (type) { case SPA_TYPE_Bool: + if (size < sizeof(int32_t)) + break; put_value(d, NULL, *(int32_t*)body ? "true" : "false"); break; case SPA_TYPE_Id: { const char *str; char fallback[32]; + if (size < sizeof(uint32_t)) + break; uint32_t id = *(uint32_t*)body; str = spa_debug_type_find_short_name(info, *(uint32_t*)body); if (str == NULL) { @@ -357,24 +361,38 @@ static void put_pod_value(struct data *d, const char *key, const struct spa_type break; } case SPA_TYPE_Int: + if (size < sizeof(int32_t)) + break; put_int(d, NULL, *(int32_t*)body); break; case SPA_TYPE_Fd: case SPA_TYPE_Long: + if (size < sizeof(int64_t)) + break; put_int(d, NULL, *(int64_t*)body); break; case SPA_TYPE_Float: + if (size < sizeof(float)) + break; put_double(d, NULL, *(float*)body); break; case SPA_TYPE_Double: + if (size < sizeof(double)) + break; put_double(d, NULL, *(double*)body); break; case SPA_TYPE_String: + if (size < 1 || ((const char *)body)[size - 1]) + break; put_string(d, NULL, (const char*)body); break; case SPA_TYPE_Rectangle: { - struct spa_rectangle *r = (struct spa_rectangle *)body; + struct spa_rectangle *r; + + if (size < sizeof(*r)) + break; + r = (struct spa_rectangle *)body; put_begin(d, NULL, "{", STATE_SIMPLE); put_int(d, "width", r->width); put_int(d, "height", r->height); @@ -383,7 +401,11 @@ static void put_pod_value(struct data *d, const char *key, const struct spa_type } case SPA_TYPE_Fraction: { - struct spa_fraction *f = (struct spa_fraction *)body; + struct spa_fraction *f; + + if (size < sizeof(*f)) + break; + f = (struct spa_fraction *)body; put_begin(d, NULL, "{", STATE_SIMPLE); put_int(d, "num", f->num); put_int(d, "denom", f->denom); @@ -392,8 +414,12 @@ static void put_pod_value(struct data *d, const char *key, const struct spa_type } case SPA_TYPE_Array: { - struct spa_pod_array_body *b = (struct spa_pod_array_body *)body; + struct spa_pod_array_body *b; void *p; + + if (size < sizeof(*b)) + break; + b = (struct spa_pod_array_body *)body; info = info && info->values ? info->values: info; put_begin(d, NULL, "[", STATE_SIMPLE); SPA_POD_ARRAY_BODY_FOREACH(b, size, p)