SPA POD parser: fix several integer overflows

This fixes several integer overflow problems in the POD parser, as well
as fixing a returns-twice warning from GCC and integer truncation
problems in SPA_FLAG_CLEAR and SPA_ROUND_DOWN_N.  The integer overflows
can result in a tiny POD being treated as a huge one, causing
out-of-bounds reads.
This commit is contained in:
Demi Marie Obenour 2022-07-30 13:10:19 -04:00 committed by Wim Taymans
parent 0e4df09e53
commit 1e848fc299
7 changed files with 59 additions and 16 deletions

View file

@ -82,12 +82,20 @@ spa_pod_parser_reset(struct spa_pod_parser *parser, struct spa_pod_parser_state
static inline struct spa_pod *
spa_pod_parser_deref(struct spa_pod_parser *parser, uint32_t offset, uint32_t size)
{
if (offset + 8 <= size) {
struct spa_pod *pod = SPA_PTROFF(parser->data, offset, struct spa_pod);
if (offset + SPA_POD_SIZE(pod) <= size)
return pod;
/* Cast to uint64_t to avoid wraparound. Add 8 for the pod itself. */
const uint64_t long_offset = (uint64_t)offset + 8;
if (long_offset <= size && (offset & 7) == 0) {
/* Use void* because creating a misaligned pointer is undefined. */
void *pod = SPA_PTROFF(parser->data, offset, void);
/*
* Check that the pointer is aligned and that the size (rounded
* to the next multiple of 8) is in bounds.
*/
if (SPA_IS_ALIGNED(pod, 8) &&
long_offset + SPA_ROUND_UP_N((uint64_t)SPA_POD_BODY_SIZE(pod), 8) <= size)
return (struct spa_pod *)pod;
}
return NULL;
return NULL;
}
static inline struct spa_pod *spa_pod_parser_frame(struct spa_pod_parser *parser, struct spa_pod_frame *frame)

View file

@ -39,7 +39,7 @@ extern "C" {
#define SPA_POD_BODY_SIZE(pod) (((struct spa_pod*)(pod))->size)
#define SPA_POD_TYPE(pod) (((struct spa_pod*)(pod))->type)
#define SPA_POD_SIZE(pod) (sizeof(struct spa_pod) + SPA_POD_BODY_SIZE(pod))
#define SPA_POD_SIZE(pod) ((uint64_t)sizeof(struct spa_pod) + SPA_POD_BODY_SIZE(pod))
#define SPA_POD_CONTENTS_SIZE(type,pod) (SPA_POD_SIZE(pod)-sizeof(type))
#define SPA_POD_CONTENTS(type,pod) SPA_PTROFF((pod),sizeof(type),void)