mirror of
https://github.com/wader/fq.git
synced 2024-11-27 06:04:47 +03:00
id3v2: In the wild COMM and TXXX frame might not have a null terminator
This commit is contained in:
parent
24a3146081
commit
f66e224452
@ -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 {
|
||||
nullLen := encodingLen[encodingUTF8]
|
||||
if n, ok := encodingLen[uint64(encoding)]; ok {
|
||||
nullLen = n
|
||||
}
|
||||
|
||||
offset, _ := d.PeekFind(
|
||||
offset, _, err := d.TryPeekFind(
|
||||
int(nullLen)*8,
|
||||
nullLen*8,
|
||||
-1,
|
||||
int64(notFoundFixedBytes)*8,
|
||||
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
|
||||
text := textFn(encoding, int(offsetBytes))(d)
|
||||
|
||||
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 {
|
||||
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 {
|
||||
var id string
|
||||
var size uint64
|
||||
@ -493,7 +507,8 @@ func decodeFrame(d *decode.D, version int) uint64 {
|
||||
"COMM": func(d *decode.D) {
|
||||
encoding := d.FieldU8("text_encoding", encodingNames)
|
||||
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)))
|
||||
},
|
||||
// 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>
|
||||
"TXXX": func(d *decode.D) {
|
||||
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)))
|
||||
},
|
||||
// <Header for 'Private frame', ID: "PRIV">
|
||||
|
BIN
format/id3/testdata/txxx-nonullterm
vendored
Normal file
BIN
format/id3/testdata/txxx-nonullterm
vendored
Normal file
Binary file not shown.
29
format/id3/testdata/txxx-nonullterm.fqtest
vendored
Normal file
29
format/id3/testdata/txxx-nonullterm.fqtest
vendored
Normal 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)
|
Loading…
Reference in New Issue
Block a user