From 84190e7c6e7c1742731b8905cc4be7c98df9d3a2 Mon Sep 17 00:00:00 2001 From: Philippe G Date: Thu, 18 Jun 2020 23:25:18 -0700 Subject: [PATCH] large mp4 header handling --- components/services/buttons.c | 2 +- components/squeezelite/alac.c | 10 ++++-- components/squeezelite/buffer.c | 50 ++++++++++++++++++++++++++++ components/squeezelite/helix-aac.c | 10 ++++-- components/squeezelite/squeezelite.h | 1 + 5 files changed, 68 insertions(+), 5 deletions(-) diff --git a/components/services/buttons.c b/components/services/buttons.c index 865a8e6f..c7fd1973 100644 --- a/components/services/buttons.c +++ b/components/services/buttons.c @@ -303,7 +303,7 @@ void *button_remap(void *client, int gpio, button_handler handler, int long_pres } } - // huh + // don't know what we are doing here if (!button) return NULL; prev_client = button->client; diff --git a/components/squeezelite/alac.c b/components/squeezelite/alac.c index f09d1df0..9d670fe1 100644 --- a/components/squeezelite/alac.c +++ b/components/squeezelite/alac.c @@ -292,9 +292,15 @@ static int read_mp4_header(void) { l->pos += bytes; l->consume = consume - bytes; break; - } else { + } else if (len > streambuf->size) { + // can't process an atom larger than streambuf! + LOG_ERROR("atom %s too large for buffer %u %u", type, len, streambuf->size); + return -1; + } else { + // make sure there is 'len' contiguous space + _buf_unwrap(streambuf, len); break; - } + } } return 0; diff --git a/components/squeezelite/buffer.c b/components/squeezelite/buffer.c index 076fd990..53d77f96 100644 --- a/components/squeezelite/buffer.c +++ b/components/squeezelite/buffer.c @@ -100,6 +100,56 @@ void _buf_resize(struct buffer *buf, size_t size) { buf->base_size = size; } +void _buf_unwrap(struct buffer *buf, size_t cont) { + ssize_t len, by = cont - (buf->wrap - buf->readp); + size_t size; + u8_t *scratch; + + // do nothing if we have enough space + if (by <= 0 || cont >= buf->size) return; + + // buffer already unwrapped, just move it up + if (buf->writep >= buf->readp) { + memmove(buf->readp - by, buf->readp, buf->writep - buf->readp); + buf->readp -= by; + buf->writep -= by; + return; + } + + // how much is overlapping + size = by - (buf->readp - buf->writep); + len = buf->writep - buf->buf; + + // buffer is wrapped and enough free space to move data up directly + if (size <= 0) { + memmove(buf->readp - by, buf->readp, buf->wrap - buf->readp); + buf->readp -= by; + memcpy(buf->wrap - by, buf->buf, min(len, by)); + if (len > by) { + memmove(buf->buf, buf->buf + by, len - by); + buf->writep -= by; + } else buf->writep += buf->size - by; + return; + } + + scratch = malloc(size); + + // buffer is wrapped but not enough free room => use scratch zone + if (scratch) { + memcpy(scratch, buf->writep - size, size); + memmove(buf->readp - by, buf->readp, buf->wrap - buf->readp); + buf->readp -= by; + memcpy(buf->wrap - by, buf->buf, by); + memmove(buf->buf, buf->buf + by, len - by - size); + buf->writep -= by; + memcpy(buf->writep - size, scratch, size); + free(scratch); + } else { + _buf_unwrap(buf, cont / 2); + _buf_unwrap(buf, cont - cont / 2); + } +} + void buf_init(struct buffer *buf, size_t size) { buf->buf = malloc(size); buf->readp = buf->buf; diff --git a/components/squeezelite/helix-aac.c b/components/squeezelite/helix-aac.c index b1dface9..bffe4db3 100644 --- a/components/squeezelite/helix-aac.c +++ b/components/squeezelite/helix-aac.c @@ -314,9 +314,15 @@ static int read_mp4_header(unsigned long *samplerate_p, unsigned char *channels_ a->pos += bytes; a->consume = consume - bytes; break; - } else { + } else if (len > streambuf->size) { + // can't process an atom larger than streambuf! + LOG_ERROR("atom %s too large for buffer %u %u", type, len, streambuf->size); + return -1; + } else { + // make sure there is 'len' contiguous space + _buf_unwrap(streambuf, len); break; - } + } } return 0; diff --git a/components/squeezelite/squeezelite.h b/components/squeezelite/squeezelite.h index ef3a6397..fe75b94b 100644 --- a/components/squeezelite/squeezelite.h +++ b/components/squeezelite/squeezelite.h @@ -544,6 +544,7 @@ void _buf_inc_readp(struct buffer *buf, unsigned by); void _buf_inc_writep(struct buffer *buf, unsigned by); void buf_flush(struct buffer *buf); void _buf_flush(struct buffer *buf); +void _buf_unwrap(struct buffer *buf, size_t cont); void buf_adjust(struct buffer *buf, size_t mod); void _buf_resize(struct buffer *buf, size_t size); void buf_init(struct buffer *buf, size_t size);