浏览代码

large mp4 header handling

Philippe G 4 年之前
父节点
当前提交
84190e7c6e

+ 1 - 1
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;

+ 8 - 2
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;

+ 50 - 0
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;

+ 8 - 2
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;

+ 1 - 0
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);