1
1
mirror of https://github.com/wader/fq.git synced 2024-12-24 22:05:31 +03:00

Merge pull request #468 from wader/id3v2-comm-txxx-no-null-term

id3v2: In the wild COMM and TXXX frame might not have a null terminator
This commit is contained in:
Mattias Wadman 2022-10-20 22:17:22 +02:00 committed by GitHub
commit b5f5b55b3d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 51 additions and 6 deletions

View File

@ -287,24 +287,34 @@ func textFn(encoding int, nBytes int) func(d *decode.D) string {
} }
} }
func textNullFn(encoding int) func(d *decode.D) string { func textNullLenFn(encoding int, notFoundFixedBytes int) func(d *decode.D) string {
return func(d *decode.D) string { return func(d *decode.D) string {
nullLen := encodingLen[encodingUTF8] nullLen := encodingLen[encodingUTF8]
if n, ok := encodingLen[uint64(encoding)]; ok { if n, ok := encodingLen[uint64(encoding)]; ok {
nullLen = n nullLen = n
} }
offset, _ := d.PeekFind( offset, _, err := d.TryPeekFind(
int(nullLen)*8, int(nullLen)*8,
nullLen*8, nullLen*8,
-1, int64(notFoundFixedBytes)*8,
func(v uint64) bool { return v == 0 }, func(v uint64) bool { return v == 0 },
) )
if err != nil {
d.IOPanic(err, "textNullLenFn")
}
if offset < 0 {
if notFoundFixedBytes < 0 {
d.Fatalf("textNullLenFn: null not found")
}
return textFn(encoding, notFoundFixedBytes)(d)
}
offsetBytes := offset / 8 offsetBytes := offset / 8
text := textFn(encoding, int(offsetBytes))(d) text := textFn(encoding, int(offsetBytes))(d)
d.SeekRel(nullLen * 8) d.SeekRel(nullLen * 8)
// seems sometimes utf16 etc has en exta null byte // seems sometimes utf16 etc has one exta null byte
if nullLen > 1 && d.PeekBits(8) == 0 { if nullLen > 1 && d.PeekBits(8) == 0 {
d.SeekRel(8) d.SeekRel(8)
} }
@ -313,6 +323,10 @@ func textNullFn(encoding int) func(d *decode.D) string {
} }
} }
func textNullFn(encoding int) func(d *decode.D) string {
return textNullLenFn(encoding, -1)
}
func decodeFrame(d *decode.D, version int) uint64 { func decodeFrame(d *decode.D, version int) uint64 {
var id string var id string
var size uint64 var size uint64
@ -493,7 +507,8 @@ func decodeFrame(d *decode.D, version int) uint64 {
"COMM": func(d *decode.D) { "COMM": func(d *decode.D) {
encoding := d.FieldU8("text_encoding", encodingNames) encoding := d.FieldU8("text_encoding", encodingNames)
d.FieldUTF8("language", 3) d.FieldUTF8("language", 3)
d.FieldStrFn("description", textNullFn(int(encoding))) // there are COMM frames with no null termination
d.FieldStrFn("description", textNullLenFn(int(encoding), int(d.BitsLeft()/8)))
d.FieldStrFn("value", textFn(int(encoding), int(d.BitsLeft()/8))) d.FieldStrFn("value", textFn(int(encoding), int(d.BitsLeft()/8)))
}, },
// Text information identifier "T00" - "TZZ" , excluding "TXX", // Text information identifier "T00" - "TZZ" , excluding "TXX",
@ -522,7 +537,8 @@ func decodeFrame(d *decode.D, version int) uint64 {
// Value <text string according to encoding> // Value <text string according to encoding>
"TXXX": func(d *decode.D) { "TXXX": func(d *decode.D) {
encoding := d.FieldU8("text_encoding", encodingNames) encoding := d.FieldU8("text_encoding", encodingNames)
d.FieldStrFn("description", textNullFn(int(encoding))) // there are TXXX frames with no null termination
d.FieldStrFn("description", textNullLenFn(int(encoding), int(d.BitsLeft()/8)))
d.FieldStrFn("value", textFn(int(encoding), int(d.BitsLeft()/8))) d.FieldStrFn("value", textFn(int(encoding), int(d.BitsLeft()/8)))
}, },
// <Header for 'Private frame', ID: "PRIV"> // <Header for 'Private frame', ID: "PRIV">

BIN
format/id3/testdata/txxx-nonullterm vendored Normal file

Binary file not shown.

View File

@ -0,0 +1,29 @@
$ fq -d id3v2 dv txxx-nonullterm
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|.{}: txxx-nonullterm (id3v2) 0x0-0x26.7 (39)
0x00|49 44 33 |ID3 | magic: "ID3" (valid) 0x0-0x2.7 (3)
0x00| 03 | . | version: 3 0x3-0x3.7 (1)
0x00| 00 | . | revision: 0 0x4-0x4.7 (1)
| | | flags{}: 0x5-0x5.7 (1)
0x00| 00 | . | unsynchronisation: false 0x5-0x5 (0.1)
0x00| 00 | . | extended_header: false 0x5.1-0x5.1 (0.1)
0x00| 00 | . | experimental_indicator: false 0x5.2-0x5.2 (0.1)
0x00| 00 | . | unused: 0 0x5.3-0x5.7 (0.5)
0x00| 00 00 00 1d | .... | size: 29 0x6-0x9.7 (4)
| | | frames[0:1]: 0xa-0x26.7 (29)
| | | [0]{}: frame 0xa-0x26.7 (29)
0x00| 54 58 58 58 | TXXX | id: "TXXX" (User defined text information frame) 0xa-0xd.7 (4)
0x00| 00 00| ..| size: 19 0xe-0x11.7 (4)
0x10|00 13 |.. |
| | | flags{}: 0x12-0x13.7 (2)
0x10| 00 | . | tag_alter_preservation: false 0x12-0x12 (0.1)
0x10| 00 | . | file_alter_preservation: false 0x12.1-0x12.1 (0.1)
0x10| 00 | . | read_only: false 0x12.2-0x12.2 (0.1)
0x10| 00 | . | unused0: 0 0x12.3-0x12.7 (0.5)
0x10| 00 | . | compression: false 0x13-0x13 (0.1)
0x10| 00 | . | encryption: false 0x13.1-0x13.1 (0.1)
0x10| 00 | . | grouping_identity: false 0x13.2-0x13.2 (0.1)
0x10| 00 | . | unused1: 0 0x13.3-0x13.7 (0.5)
0x10| 01 | . | text_encoding: "utf16" (1) 0x14-0x14.7 (1)
0x10| ff fe 53 00 6f 00 66 00 74 00 77| ..S.o.f.t.w| description: "Software" 0x15-0x26.7 (18)
0x20|00 61 00 72 00 65 00| |.a.r.e.| |
| | | value: "" 0x27-NA (0)