diff --git a/apps/codecs/smaf.c b/apps/codecs/smaf.c index cd1155b..7ac2ec5 100644 --- a/apps/codecs/smaf.c +++ b/apps/codecs/smaf.c @@ -99,13 +99,24 @@ static int convert_smaf_audio_basebit(unsigned int basebit) return basebits[basebit]; } -static bool parse_audio_track(struct pcm_format *fmt, - unsigned char **stbuf, unsigned char *endbuf) +static bool parse_audio_track(struct pcm_format *fmt, off_t *pos) { - unsigned char *buf = *stbuf; - int chunksize; + unsigned char *buf; + size_t chunksize; + size_t readsize; + + /* size of the next chunk. */ + chunksize = 6; + + buf = ci->request_buffer(&readsize, chunksize); + if (readsize < chunksize) + { + DEBUGF("CODEC_ERROR: audio track chunk is too small\n"); + return false; + } + ci->advance_buffer(chunksize); + *pos += chunksize; - buf += 8; fmt->channels = ((buf[2] & 0x80) >> 7) + 1; fmt->formattag = convert_smaf_audio_format(SMAF_TRACK_CHUNK_AUDIO, (buf[2] >> 4) & 0x07); @@ -120,50 +131,85 @@ static bool parse_audio_track(struct pcm_format *fmt, DEBUGF("CODEC_ERROR: unsupport pcm data basebit : %d\n", buf[3] >> 4); return false; } - buf += 6; - while (buf < endbuf) + + while (*pos < (off_t)ci->id3->filesize) { - chunksize = get_be32(buf + 4) + 8; + /* get chunk name and chunksize */ + buf = ci->request_buffer(&readsize, 8); + if (readsize < 8) + { + DEBUGF("CODEC_ERROR: audio track chunk is too small\n"); + return false; + } + ci->advance_buffer(8); + *pos += 8; + + chunksize = get_be32(buf + 4); if (memcmp(buf, "Awa", 3) == 0) { - fmt->numbytes = get_be32(buf + 4); - buf += 8; + fmt->numbytes = chunksize; return true; } - buf += chunksize; + else + { + ci->advance_buffer(chunksize); + *pos += chunksize; + } } DEBUGF("CODEC_ERROR: smaf does not include stream pcm data\n"); return false; } -static bool parse_score_track(struct pcm_format *fmt, - unsigned char **stbuf, unsigned char *endbuf) +static bool parse_score_track(struct pcm_format *fmt, int smaftype, off_t *pos) { - unsigned char *buf = *stbuf; - int chunksize; + unsigned char *buf; + size_t chunksize; + size_t readsize; + + /* + * size of the next chunk. + * MA-2/MA-3/MA-5: 20 bytes + * MA-7: 36 bytes + */ + chunksize = (smaftype < 7)? 20 : 36; - if (buf[9] != 0x00) + buf = ci->request_buffer(&readsize, chunksize); + if (readsize < chunksize) { - DEBUGF("CODEC_ERROR: score track chunk unsupport sequence type %d\n", buf[9]); + DEBUGF("CODEC_ERROR: score track chunk is too small\n"); return false; } + ci->advance_buffer(chunksize); + *pos += chunksize; - /* - * skip to the next chunk. - * MA-2/MA-3/MA-5: padding 16 bytes - * MA-7: padding 32 bytes - */ - if (buf[3] < 7) - buf += 28; - else - buf += 44; - - while (buf < endbuf) + if (buf[1] != 0x00) + { + DEBUGF("CODEC_ERROR: score track chunk unsupport sequence type %d\n", buf[1]); + return false; + } + + while (*pos < (off_t)ci->id3->filesize) { - chunksize = get_be32(buf + 4) + 8; + /* get chunk name and chunksize */ + buf = ci->request_buffer(&readsize, 8); + if (readsize < 8) + { + DEBUGF("CODEC_ERROR: score track chunk is too small\n"); + return false; + } + ci->advance_buffer(8); + *pos += 8; + if (memcmp(buf, "Mtsp", 4) == 0) { - buf += 8; + buf = ci->request_buffer(&readsize, 11); + if (readsize < 11) + { + DEBUGF("CODEC_ERROR: score track chunk is too small\n"); + return false; + } + *pos += 11; + if (memcmp(buf, "Mwa", 3) != 0) { DEBUGF("CODEC_ERROR: smaf does not include stream pcm data\n"); @@ -186,58 +232,79 @@ static bool parse_score_track(struct pcm_format *fmt, buf[8] & 0x0f); return false; } - buf += 11; return true; } - buf += chunksize; + else + { + chunksize = get_be32(buf + 4); + ci->advance_buffer(chunksize); + *pos += chunksize; + } } DEBUGF("CODEC_ERROR: smaf does not include stream pcm data\n"); return false; } -static bool parse_header(struct pcm_format *fmt, size_t *pos) +static bool parse_header(struct pcm_format *fmt, off_t *pos) { - unsigned char *buf, *stbuf, *endbuf; + unsigned char *buf; size_t chunksize; + size_t readsize; + *pos = 0; ci->memset(fmt, 0, sizeof(struct pcm_format)); - /* assume the SMAF pcm data position is less than 1024 bytes */ - stbuf = ci->request_buffer(&chunksize, 1024); - if (chunksize < 1024) + /* get chunk name and chunksize */ + buf = ci->request_buffer(&readsize, 8); + if (readsize < 8) + { + DEBUGF("CODEC_ERROR: smaf file is too small\n"); return false; + } + ci->advance_buffer(8); + *pos += 8; - buf = stbuf; - endbuf = stbuf + chunksize; - if (memcmp(buf, "MMMD", 4) != 0) { DEBUGF("CODEC_ERROR: does not smaf format %c%c%c%c\n", buf[0], buf[1], buf[2], buf[3]); return false; } - buf += 8; - while (buf < endbuf) + while (*pos < (off_t)ci->id3->filesize) { - chunksize = get_be32(buf + 4) + 8; + /* get chunk name and chunksize */ + buf = ci->request_buffer(&readsize, 8); + if (readsize < 8) + { + DEBUGF("CODEC_ERROR: smaf file is too small\n"); + return false; + } + ci->advance_buffer(8); + *pos += 8; + if (memcmp(buf, "ATR", 3) == 0) { - if (!parse_audio_track(fmt, &buf, endbuf)) + if (!parse_audio_track(fmt, pos)) return false; break; } - if (memcmp(buf, "MTR", 3) == 0) + else if (memcmp(buf, "MTR", 3) == 0) { - if (!parse_score_track(fmt, &buf, endbuf)) + if (!parse_score_track(fmt, buf[3], pos)) return false; break; } - buf += chunksize; + else + { + chunksize = get_be32(buf + 4); + ci->advance_buffer(chunksize); + *pos += chunksize; + } } - if (buf >= endbuf) + if (*pos >= (off_t)ci->id3->filesize) { DEBUGF("CODEC_ERROR: unsupported smaf format\n"); return false; @@ -251,11 +318,9 @@ static bool parse_header(struct pcm_format *fmt, size_t *pos) /* data signess (default signed) */ fmt->is_signed = (fmt->formattag != SMAF_FORMAT_UNSIGNED_PCM); + /* data is always big endian */ fmt->is_little_endian = false; - /* sets pcm data position */ - *pos = buf - stbuf; - return true; } @@ -305,7 +370,7 @@ next_track: decodedsamples = 0; codec = 0; - if (!parse_header(&format, &n)) + if (!parse_header(&format, &firstblockposn)) { i = CODEC_ERROR; goto done; @@ -371,8 +436,8 @@ next_track: goto done; } - firstblockposn = 1024 - n; - ci->advance_buffer(firstblockposn); + ci->seek_buffer(firstblockposn); + ci->seek_complete(); /* The main decoder loop */ bytesdone = 0; diff --git a/apps/metadata/smaf.c b/apps/metadata/smaf.c index 586802b..e1030f4 100644 --- a/apps/metadata/smaf.c +++ b/apps/metadata/smaf.c @@ -48,62 +48,92 @@ static int support_codepages[7] = { #define TAG_ARTIST (('A'<<8)|'N') #define TAG_COMPOSER (('S'<<8)|'W') -static bool read_datachunk(unsigned char *src, int size, unsigned short tag, - int codepage, unsigned char *dst) +#define CONTENTS_TAG(b) ((b[0]<<8)|b[1]) +#define CONTENTS_SIZE(b) ((b[2]<<8)|b[3]) + +static bool read_option(int fd, int codepage, unsigned char *dst, int dstsize, + int *datasize, int *realsize) { - int datasize = 0; - unsigned char *utf8; + /* value length <= 256 bytes */ + unsigned char buf[256]; + unsigned char utf8[256*3]; + unsigned char *p = buf; + int count = 0; + + *datasize = (int)read(fd, buf, 256); + if (*datasize < 1) + { + DEBUGF("metadata error: smaf read error\n"); + return false; + } - while(size > datasize + 4) + while (p - buf < *datasize) { - datasize = (src[2] << 8) | src[3]; - if (tag == ((src[0] << 8) | src[1])) - { - src += 4; - if (codepage < NUM_CODEPAGES) - utf8 = iso_decode(src, dst, codepage, datasize); - else /* codepage == UTF_16, UCS_2 */ - utf8 = utf16BEdecode(src, dst, datasize); - *utf8 = '\0'; + if (*p == ',') + break; - return true; + if (*p == '\\' && *(p+1) == ',') + p++; + + count++; + p++; + } + if (p - buf < *datasize) + { + lseek(fd, (p - buf) - (*datasize) + 1, SEEK_CUR); + *datasize = (p - buf) + 1; + } + + if (codepage < NUM_CODEPAGES) + p = iso_decode(buf, utf8, codepage, count); + else /* codepage == UTF_16, UCS_2 */ + p = utf16BEdecode(buf, utf8, count); + + *p = '\0'; + + if (dst != NULL) + { + strlcpy(dst, utf8, dstsize); + *realsize = strlen(utf8) + 1; + if (*realsize > dstsize) + { + DEBUGF("metadata warning: data length: %d > contents store buffer size: %d\n", + *realsize, dstsize); + *realsize = dstsize; } - src += (datasize + 4); } - return false; + return true; } -static bool read_option(unsigned char *src, int size, unsigned short tag, - int codepage, unsigned char *dst) +static bool read_data(int fd, int codepage, int datasize, + unsigned char *dst, int dstsize, int *realsize) { - int datasize = 0; - unsigned char *endsrc = src + size; + unsigned char tmpbuf[datasize]; + unsigned char utf8buf[datasize*3+1]; unsigned char *utf8; - while(src < endsrc) + if (read(fd, tmpbuf, datasize) < datasize) { - utf8 = src; - src += 3; - datasize = 0; - while (*src != ',' || *(src-1) == '\\') - { - datasize++; - src++; - } - if (tag == ((utf8[0] << 8) | utf8[1]) && utf8[2] == ':') - { - utf8 += 3; - if (codepage < NUM_CODEPAGES) - utf8 = iso_decode(utf8, dst, codepage, datasize); - else /* codepage == UTF_16, UCS_2 */ - utf8 = utf16BEdecode(utf8, dst, datasize); - *utf8 = '\0'; + DEBUGF("metadata error: smaf contents field is too small\n"); + return false; + } - return true; - } - src++; + if (codepage < NUM_CODEPAGES) + utf8 = iso_decode(tmpbuf, utf8buf, codepage, datasize); + else /* codepage == UTF_16, UCS_2 */ + utf8 = utf16BEdecode(tmpbuf, utf8buf, datasize); + *utf8 = '\0'; + + *realsize = strlen(utf8buf) + 1; + if (*realsize > dstsize) + { + DEBUGF("metadata warning: data length: %d > contents store buffer size: %d\n", + *realsize, dstsize); + *realsize = dstsize; } - return false; + + strlcpy(dst, utf8buf, dstsize); + return true; } static int convert_smaf_audio_frequency(unsigned int freq) @@ -137,31 +167,191 @@ static int convert_smaf_codetype(unsigned int codetype) return -1; } -static bool get_smaf_metadata_audio_track(struct mp3entry *id3, - unsigned char* buf, unsigned char *endbuf) +static bool parse_smaf_audio_track_contents(int fd, struct mp3entry *id3, int size) +{ + unsigned char buf[5]; + /* contents stored buffer */ + unsigned char *cbuf = id3->id3v2buf; + int codepage; + int csize = sizeof(id3->id3v2buf); + int dsize; + int rsize; + + if (read(fd, buf, 5) < 5) + { + DEBUGF("metadata error: smaf contents field is too small\n"); + return false; + } + codepage = convert_smaf_codetype(buf[2]); + if (codepage < 0) + { + DEBUGF("metadata error: smaf unsupport codetype: %d\n", buf[2]); + return false; + } + + size -= 5; + while ((id3->title == NULL || id3->artist == NULL || id3->composer == NULL) + && (size > 0 && csize > 0)) + { + if (read(fd, buf, 3) < 3) + { + DEBUGF("metadata error: smaf contents field is too small\n"); + return false; + } + if (buf[2] != ':') + { + DEBUGF("metadata error: smaf illegal tag format %c%c%c\n", + buf[0], buf[1], buf[2]); + return false; + } + switch (CONTENTS_TAG(buf)) + { + case TAG_TITLE: + if (!read_option(fd, codepage, cbuf, csize, &dsize, &rsize)) + return false; + + id3->title = cbuf; + break; + case TAG_ARTIST: + if (!read_option(fd, codepage, cbuf, csize, &dsize, &rsize)) + return false; + + id3->artist = cbuf; + break; + case TAG_COMPOSER: + if (!read_option(fd, codepage, cbuf, csize, &dsize, &rsize)) + return false; + + id3->composer = cbuf; + break; + default: + if (!read_option(fd, codepage, NULL, csize, &dsize, &rsize)) + return false; + rsize = 0; + break; + } + cbuf += rsize; + csize -= rsize; + size -= (dsize + 3); + } + return true; +} + +static bool parse_smaf_score_track_contents(int fd, struct mp3entry *id3) +{ + unsigned char buf[8]; + /* contents stored buffer */ + unsigned char *cbuf = id3->id3v2buf; + int codepage; + int csize = sizeof(id3->id3v2buf); + int dsize; + int rsize; + int size; + + if (read(fd, buf, 8) < 8) + { + DEBUGF("metadata error: smaf contents field is too small\n"); + return false; + } + if (memcmp(buf, "Dch", 3) != 0) + { + DEBUGF("metadata error: smaf does not include Dch chunk\n"); + return false; + } + codepage = convert_smaf_codetype(buf[3]); + if (codepage < 0) + { + DEBUGF("metadata error: smaf unsupport codetype: %d\n", buf[3]); + return false; + } + + size = get_long_be(buf + 4); + while ((id3->title == NULL || id3->artist == NULL || id3->composer == NULL) + && (size > 0 && csize > 0)) + { + if (read(fd, buf, 4) < 4) + { + DEBUGF("metadata error: smaf contents field is too small\n"); + return false; + } + + dsize = CONTENTS_SIZE(buf); + + switch (CONTENTS_TAG(buf)) + { + case TAG_TITLE: + if (!read_data(fd, codepage, dsize, cbuf, csize, &rsize)) + return false; + + id3->title = cbuf; + break; + case TAG_ARTIST: + if (!read_data(fd, codepage, dsize, cbuf, csize, &rsize)) + return false; + + id3->artist = cbuf; + break; + case TAG_COMPOSER: + if (!read_data(fd, codepage, dsize, cbuf, csize, &rsize)) + return false; + + id3->composer = cbuf; + break; + default: + lseek(fd, dsize, SEEK_CUR); + rsize = 0; + break; + } + cbuf += rsize; + csize -= rsize; + size -= (dsize + 4); + } + + return true; +} + +static bool get_smaf_metadata_audio_track(int fd, struct mp3entry *id3, + unsigned long pos) { + unsigned char buf[8]; int bitspersample; int channels; int chunksize; long numbytes; unsigned long totalsamples; - channels = ((buf[10] & 0x80) >> 7) + 1; - bitspersample = convert_smaf_audio_basebit(buf[11] >> 4); + if (read(fd, buf, 6) < 6) + { + DEBUGF("metadata error: smaf contents field is too small\n"); + return false; + } + pos += 6; + + channels = ((buf[2] & 0x80) >> 7) + 1; + bitspersample = convert_smaf_audio_basebit(buf[3] >> 4); if (bitspersample == 0) { - DEBUGF("metada error: smaf unsupport basebit %d\n", buf[11] >> 4); + DEBUGF("metadata error: smaf unsupport basebit %d\n", buf[3] >> 4); return false; } - id3->frequency = convert_smaf_audio_frequency(buf[10] & 0x0f); + id3->frequency = convert_smaf_audio_frequency(buf[2] & 0x0f); - buf += 14; - while (buf < endbuf) + while (pos < id3->filesize) { - chunksize = get_long_be(buf + 4) + 8; - if (memcmp(buf, "Awa", 3) == 0) + if (read(fd, buf, 8) < 8) { - numbytes = get_long_be(buf + 4) - 3; + DEBUGF("metadata error: smaf contents field is too small\n"); + return false; + } + chunksize = get_long_be(buf + 4); + if (memcmp(buf, "Awa", 3) != 0) + { + lseek(fd, chunksize, SEEK_CUR); + pos += (chunksize + 8); + } + else + { + numbytes = chunksize; totalsamples = (numbytes << 3) / (bitspersample * channels); /* Calculate track length (in ms) and estimate the bitrate (in kbit/s) */ @@ -169,15 +359,15 @@ static bool get_smaf_metadata_audio_track(struct mp3entry *id3, return true; } - buf += chunksize; } - DEBUGF("metada error: smaf does not include pcm audio data\n"); + DEBUGF("metadata error: smaf does not include pcm audio data\n"); return false; } -static bool get_smaf_metadata_score_track(struct mp3entry *id3, - unsigned char* buf, unsigned char *endbuf) +static bool get_smaf_metadata_score_track(int fd, struct mp3entry *id3, + int smaftype, unsigned long pos) { + unsigned char buf[11]; int bitspersample; int channels; int chunksize; @@ -185,24 +375,38 @@ static bool get_smaf_metadata_score_track(struct mp3entry *id3, unsigned long totalsamples; /* - * skip to the next chunk. - * MA-2/MA-3/MA-5: padding 16 bytes - * MA-7: padding 32 bytes + * size of the next chunk. + * MA-2/MA-3/MA-5: 20 bytes + * MA-7: 36 bytes */ - if (buf[3] < 7) - buf += 28; - else - buf += 44; + chunksize = (smaftype < 7)? 20 : 36; + lseek(fd, chunksize, SEEK_CUR); + pos += chunksize; - while (buf + 10 < endbuf) + while (pos < id3->filesize) { - chunksize = get_long_be(buf + 4) + 8; - if (memcmp(buf, "Mtsp", 4) == 0) + if (read(fd, buf, 8) < 8) { - buf += 8; + DEBUGF("metadata error: smaf contents field is too small\n"); + return false; + } + pos += 8; + if (memcmp(buf, "Mtsp", 4) != 0) + { + chunksize = get_long_be(buf + 4); + lseek(fd, chunksize, SEEK_CUR); + pos += chunksize; + } + else + { + if (read(fd, buf, 11) < 11) + { + DEBUGF("metadata error: smaf contents field is too small\n"); + return false; + } if (memcmp(buf, "Mwa", 3) != 0) { - DEBUGF("metada error: smaf unsupport format: %c%c%c%c\n", + DEBUGF("metadata error: smaf unsupport format: %c%c%c%c\n", buf[0], buf[1], buf[2], buf[3]); return false; } @@ -211,7 +415,7 @@ static bool get_smaf_metadata_score_track(struct mp3entry *id3, bitspersample = convert_smaf_audio_basebit(buf[8] & 0x0f); if (bitspersample == 0) { - DEBUGF("metada error: smaf unsupport basebit %d\n", buf[8] & 0x0f); + DEBUGF("metadata error: smaf unsupport basebit %d\n", buf[8] & 0x0f); return false; } @@ -225,22 +429,16 @@ static bool get_smaf_metadata_score_track(struct mp3entry *id3, return true; } - buf += chunksize; } - DEBUGF("metada error: smaf does not include pcm audio data\n"); + DEBUGF("metadata error: smaf does not include pcm audio data\n"); return false; } bool get_smaf_metadata(int fd, struct mp3entry* id3) { - unsigned char smafbuf[1024]; - - /* Use the trackname part of the id3 structure as a temporary buffer */ - unsigned char* buf = (unsigned char *)id3->path; - unsigned char *endbuf = smafbuf + sizeof(smafbuf); - int i; - int contents_size; - int codepage = ISO_8859_1; + unsigned char buf[16]; + int csize; + unsigned long pos; id3->title = NULL; id3->artist = NULL; @@ -249,121 +447,70 @@ bool get_smaf_metadata(int fd, struct mp3entry* id3) id3->vbr = false; /* All SMAF files are CBR */ id3->filesize = filesize(fd); - /* get RIFF chunk header */ - if ((lseek(fd, 0, SEEK_SET) < 0) || (read(fd, buf, 21) < 21)) + /* get SMAF magic and CNTI chunk */ + if ((lseek(fd, 0, SEEK_SET) < 0) || (read(fd, buf, 16) < 16)) { return false; } - if ((memcmp(buf, "MMMD", 4) != 0) || (memcmp(&buf[8], "CNTI", 4) != 0)) + if ((memcmp(buf, "MMMD", 4) != 0) || (memcmp(buf + 8, "CNTI", 4) != 0)) { - DEBUGF("metada error: does not smaf format\n"); + DEBUGF("metadata error: does not smaf format\n"); return false; } - contents_size = get_long_be(buf + 12); - if (contents_size < 5) + csize = get_long_be(buf + 12); + if (csize < 5) { - DEBUGF("metada error: CNTI chunk size is small %d\n", contents_size); + DEBUGF("metadata error: CNTI chunk size is small %d\n", csize); return false; } - contents_size -= 5; - i = contents_size; - if (i == 0) + if (csize == 5) { - read(fd, buf, 16); - if (memcmp(buf, "OPDA", 4) != 0) - { - DEBUGF("metada error: smaf does not include OPDA chunk\n"); - return false; - } - contents_size = get_long_be(buf + 4) - 8; - - if (memcmp(buf + 8, "Dch", 3) != 0) + if (read(fd, buf, 13) < 13) { - DEBUGF("metada error: smaf does not include Dch chunk\n"); + DEBUGF("metadata error: smaf contents field is too small\n"); return false; } - codepage = convert_smaf_codetype(buf[11]); - if (codepage < 0) + if (memcmp(buf + 5, "OPDA", 4) != 0) { - DEBUGF("metada error: smaf unsupport codetype: %d\n", buf[11]); + DEBUGF("metadata error: smaf does not include OPDA chunk\n"); return false; } - i = get_long_be(buf + 12); + csize = get_long_be(buf + 9) + 13; - if (i > MAX_PATH) - { - DEBUGF("metada warning: smaf contents size is big %d\n", i); - i = MAX_PATH; - } - if (read(fd, buf, i) < i) + if (!parse_smaf_score_track_contents(fd, id3)) return false; - - /* title */ - if (read_datachunk(buf, i, TAG_TITLE, codepage, id3->id3v1buf[0])) - id3->title = id3->id3v1buf[0]; - - /* artist */ - if (read_datachunk(buf, i, TAG_ARTIST, codepage, id3->id3v1buf[1])) - id3->artist = id3->id3v1buf[1]; - - /* composer */ - if (read_datachunk(buf, i, TAG_COMPOSER, codepage, id3->id3v1buf[2])) - id3->composer = id3->id3v1buf[2]; } else { - codepage = convert_smaf_codetype(buf[14]); - if (codepage < 0) - { - DEBUGF("metada error: smaf unsupport codetype: %d\n", buf[11]); + if (!parse_smaf_audio_track_contents(fd, id3, csize)) return false; - } - - if (i > MAX_PATH) - { - DEBUGF("metada warning: smaf contents size is big %d\n", i); - i = MAX_PATH; - } - if (read(fd, buf, i) < i) - return false; - - /* title */ - if (read_option(buf, i, TAG_TITLE, codepage, id3->id3v1buf[0])) - id3->title = id3->id3v1buf[0]; - - /* artist */ - if (read_option(buf, i, TAG_ARTIST, codepage, id3->id3v1buf[1])) - id3->artist = id3->id3v1buf[1]; - - /* composer */ - if (read_option(buf, i, TAG_COMPOSER, codepage, id3->id3v1buf[2])) - id3->composer = id3->id3v1buf[2]; } - if (contents_size > i) - lseek(fd, contents_size - i, SEEK_CUR); - - /* assume the SMAF pcm data position is near the start */ - if (read(fd, smafbuf, sizeof(smafbuf)) < (ssize_t)sizeof(smafbuf)) - return false; + pos = 16 + csize; + lseek(fd, pos, SEEK_SET); - buf = smafbuf; - while (buf + 8 < endbuf) + while (pos < id3->filesize) { - i = get_long_be(buf + 4) + 8; + if (read(fd, buf, 8) < 8) + { + DEBUGF("metadata error: smaf contents field is too small\n"); + return false; + } if (memcmp(buf, "ATR", 3) == 0) - return get_smaf_metadata_audio_track(id3, buf, endbuf); + return get_smaf_metadata_audio_track(fd, id3, pos); else if (memcmp(buf, "MTR", 3) == 0) - return get_smaf_metadata_score_track(id3, buf, endbuf); + return get_smaf_metadata_score_track(fd, id3, buf[3], pos); - buf += i; + csize = get_long_be(buf + 4); + pos += (csize + 8); + lseek(fd, csize, SEEK_CUR); } - DEBUGF("metada error: smaf does not include track chunk\n"); + DEBUGF("metadata error: smaf does not include track chunk\n"); return false; }