static int matroska_parse_laces(MatroskaDemuxContext *matroska, uint8_t **buf, int size, int type, uint32_t **lace_buf, int *laces) { int res = 0, n; uint8_t *data = *buf; uint32_t *lace_size; if (!type) { *laces = 1; *lace_buf = av_mallocz(sizeof(int)); if (!*lace_buf) return AVERROR(ENOMEM); *lace_buf[0] = size; return 0; } assert(size > 0); *laces = *data + 1; data += 1; size -= 1; lace_size = av_mallocz(*laces * sizeof(int)); if (!lace_size) return AVERROR(ENOMEM); switch (type) { case 0x1: /* Xiph lacing */ { uint8_t temp; uint32_t total = 0; for (n = 0; res == 0 && n < *laces - 1; n++) { while (1) { if (size == 0) { res = AVERROR_EOF; break; } temp = *data; lace_size[n] += temp; data += 1; size -= 1; if (temp != 0xff) break; } total += lace_size[n]; } if (size <= total) { res = AVERROR_INVALIDDATA; break; } lace_size[n] = size - total; break; } case 0x2: /* fixed-size lacing */ if (size != (size / *laces) * size) { res = AVERROR_INVALIDDATA; break; } for (n = 0; n < *laces; n++) lace_size[n] = size / *laces; break; case 0x3: /* EBML lacing */ { uint64_t num; uint32_t total; n = matroska_ebmlnum_uint(matroska, data, size, &num); if (n < 0) { av_log(matroska->ctx, AV_LOG_INFO, "EBML block data error\n"); res = n; break; } data += n; size -= n; total = lace_size[0] = num; for (n = 1; res == 0 && n < *laces - 1; n++) { int64_t snum; int r; r = matroska_ebmlnum_sint(matroska, data, size, &snum); if (r < 0) { av_log(matroska->ctx, AV_LOG_INFO, "EBML block data error\n"); res = r; break; } data += r; size -= r; lace_size[n] = lace_size[n - 1] + snum; total += lace_size[n]; } if (size <= total) { res = AVERROR_INVALIDDATA; break; } lace_size[*laces - 1] = size - total; break; } } *buf = data; *lace_buf = lace_size; return res; }