diff options
author | Roman Artiukhin <bahusdrive@gmail.com> | 2024-11-24 16:25:51 +0200 |
---|---|---|
committer | Roman Artiukhin <bahusdrive@gmail.com> | 2024-12-11 11:36:08 +0200 |
commit | c1ee278abf66a40ec2698623f167dd5b9537a9b4 (patch) | |
tree | 034ede891e9c724fd617cda51d7181899ccafd1f | |
parent | 1a6f0d8b0f44df0c7c5b0395e62f26716579eea1 (diff) | |
download | rockbox-c1ee278abf.tar.gz rockbox-c1ee278abf.zip |
metadata: mp3: Avoid utf-8 buffer stack allocation when processing cuesheet
Change-Id: Ife49d5e3f2850e8621f927a4864d7863c103db77
-rw-r--r-- | lib/rbcodec/metadata/id3tags.c | 116 |
1 files changed, 73 insertions, 43 deletions
diff --git a/lib/rbcodec/metadata/id3tags.c b/lib/rbcodec/metadata/id3tags.c index 506cbcaaf1..49316a34a9 100644 --- a/lib/rbcodec/metadata/id3tags.c +++ b/lib/rbcodec/metadata/id3tags.c @@ -703,6 +703,59 @@ bool setid3v1title(int fd, struct mp3entry *entry) return true; } +static bool is_cuesheet(char *tag, unsigned char *char_enc, unsigned char *cuesheet_offset) +{ + *char_enc = 0; + /* [enc type]+"CUESHEET\0" = 10 */ + *cuesheet_offset = 10; + unsigned char utf16 = 0; + + switch (tag[0]) + { + case 0x00: + *char_enc = CHAR_ENC_ISO_8859_1; + break; + case 0x01: + if (!memcmp(tag + 1, BOM_UTF_16_BE, BOM_UTF_16_SIZE)) + utf16 = CHAR_ENC_UTF_16_BE; + else if (!memcmp(tag + 1, BOM_UTF_16_LE, BOM_UTF_16_SIZE)) + utf16 = CHAR_ENC_UTF_16_LE; + else + return false; + + tag+= BOM_UTF_16_SIZE; + *char_enc = utf16; + /* \1 + BOM(2) + C0U0E0S0H0E0E0T000 = 21 */ + *cuesheet_offset = 21; + break; + case 0x02: + utf16 = *char_enc = CHAR_ENC_UTF_16_BE; + /* \2 + 0C0U0E0S0H0E0E0T00 = 19 */ + *cuesheet_offset = 19; + break; + case 0x03: + *char_enc = CHAR_ENC_UTF_8; + break; + default: + return false; + } + ++tag; //skip encoding type + const char* key = "CUESHEET"; + + if (!utf16) + return !strncmp(tag, key, 8); + + int tag_index; + for (int i =0; i < 8; ++i) + { + tag_index = i<<1; + if ( (utf16 == CHAR_ENC_UTF_16_BE && tag[tag_index] == 0 && tag[tag_index + 1] == key[i] ) + || (tag[tag_index] == key[i] && tag[tag_index + 1] == 0 )) + continue; + return false; + } + return true; +} /* * Sets the title of an MP3 entry based on its ID3v2 tag. @@ -1019,6 +1072,26 @@ retry_with_limit: /* Attempt to parse Unicode string only if the tag contents aren't binary */ if(!tr->binary) { + if ( /* Is it an embedded cuesheet? */ + (tr->offset == 0 && tr->tag_length == 4 && !memcmp(header, "TXXX", 4)) && + (bytesread >= 14) + ) { + unsigned char char_enc; + unsigned char cuesheet_offset; + if (is_cuesheet(tag, &char_enc, &cuesheet_offset)) + { + if (char_enc > 0) { + entry->has_embedded_cuesheet = true; + entry->embedded_cuesheet.pos = lseek(fd, 0, SEEK_CUR) + - framelen + cuesheet_offset; + entry->embedded_cuesheet.size = totframelen + - cuesheet_offset; + entry->embedded_cuesheet.encoding = char_enc; + } + break; + } + } + /* UTF-8 could potentially be 3 times larger */ /* so we need to create a new buffer */ char utf8buf[(3 * bytesread) + 1]; @@ -1028,49 +1101,6 @@ retry_with_limit: if(bytesread >= buffersize - bufferpos) bytesread = buffersize - bufferpos - 1; - if ( /* Is it an embedded cuesheet? */ - (tr->tag_length == 4 && !memcmp(header, "TXXX", 4)) && - (bytesread >= 14 && !strncmp(utf8buf, "CUESHEET", 8)) - ) { - unsigned char char_enc = 0; - /* [enc type]+"CUESHEET\0" = 10 */ - unsigned char cuesheet_offset = 10; - switch (tag[0]) { - case 0x00: - char_enc = CHAR_ENC_ISO_8859_1; - break; - case 0x01: - tag++; - if (!memcmp(tag, - BOM_UTF_16_BE, BOM_UTF_16_SIZE)) { - char_enc = CHAR_ENC_UTF_16_BE; - } else if (!memcmp(tag, - BOM_UTF_16_LE, BOM_UTF_16_SIZE)) { - char_enc = CHAR_ENC_UTF_16_LE; - } - /* \1 + BOM(2) + C0U0E0S0H0E0E0T000 = 21 */ - cuesheet_offset = 21; - break; - case 0x02: - char_enc = CHAR_ENC_UTF_16_BE; - /* \2 + 0C0U0E0S0H0E0E0T00 = 19 */ - cuesheet_offset = 19; - break; - case 0x03: - char_enc = CHAR_ENC_UTF_8; - break; - } - if (char_enc > 0) { - entry->has_embedded_cuesheet = true; - entry->embedded_cuesheet.pos = lseek(fd, 0, SEEK_CUR) - - framelen + cuesheet_offset; - entry->embedded_cuesheet.size = totframelen - - cuesheet_offset; - entry->embedded_cuesheet.encoding = char_enc; - } - break; - } - for (j = 0; j < bytesread; j++) tag[j] = utf8buf[j]; |