diff --git a/fmp/fmp_sector.go b/fmp/fmp_sector.go index 05705bd..b284c01 100644 --- a/fmp/fmp_sector.go +++ b/fmp/fmp_sector.go @@ -123,22 +123,14 @@ func (sect *FmpSector) readChunk(payload []byte) (*FmpChunk, error) { chunk.Type = FMP_CHUNK_SIMPLE_DATA chunk.Value = payload[1:chunk.Length] - case 0x01: - chunk.Length = 3 - chunk.Type = FMP_CHUNK_SIMPLE_KEY_VALUE - chunk.Key = uint64(payload[1]) - chunk.Value = payload[2:chunk.Length] - - case 0x02, 0x03, 0x04, 0x05: - valueLength := uint64(2 * (chunkCode - 1)) - chunk.Length = 2 + valueLength + case 0x01, 0x02, 0x03, 0x04, 0x05: + chunk.Length = 2 + 2*uint64(chunkCode-0x01) + addIf(chunkCode == 0x01, 1) chunk.Type = FMP_CHUNK_SIMPLE_KEY_VALUE chunk.Key = uint64(payload[1]) chunk.Value = payload[2:chunk.Length] case 0x06: - valueLength := uint64(payload[2]) - chunk.Length = 3 + valueLength + chunk.Length = 3 + uint64(payload[2]) chunk.Type = FMP_CHUNK_SIMPLE_KEY_VALUE chunk.Key = uint64(payload[1]) chunk.Value = payload[3:chunk.Length] @@ -162,20 +154,12 @@ func (sect *FmpSector) readChunk(payload []byte) (*FmpChunk, error) { chunk.Value = payload[3:chunk.Length] case 0x0A, 0x0B, 0x0C, 0x0D: - valueLength := uint64(2 * (chunkCode - 0x09)) - chunk.Length = 3 + valueLength + chunk.Length = 3 + 2*uint64(chunkCode-0x09) chunk.Type = FMP_CHUNK_SIMPLE_KEY_VALUE chunk.Key = parseVarUint64(payload[1 : 1+2]) chunk.Value = payload[3:chunk.Length] case 0x0E: - if payload[1] == 0xFE { - chunk.Length = 10 - chunk.Type = FMP_CHUNK_PATH_PUSH - chunk.Value = payload[2:chunk.Length] - break - } - if payload[1] == 0xFF { chunk.Length = 7 chunk.Type = FMP_CHUNK_SIMPLE_DATA @@ -183,55 +167,48 @@ func (sect *FmpSector) readChunk(payload []byte) (*FmpChunk, error) { break } - valueLength := uint64(payload[2]) - chunk.Length = 4 + valueLength + chunk.Length = 4 + uint64(payload[3]) chunk.Type = FMP_CHUNK_SIMPLE_KEY_VALUE chunk.Key = parseVarUint64(payload[1 : 1+2]) chunk.Value = payload[4:chunk.Length] case 0x0F: valueLength := parseVarUint64(payload[3 : 3+2]) - chunk.Length = min(5+valueLength, uint64(len(payload))) + chunk.Length = uint64(len(payload)) + if chunk.Length > 5+valueLength { + return nil, ErrBadChunk + } chunk.Type = FMP_CHUNK_SEGMENTED_DATA chunk.Index = parseVarUint64(payload[1 : 1+2]) chunk.Value = payload[5:chunk.Length] case 0x10, 0x11: - valueLength := 3 + (uint64(chunkCode) - 0x10) - chunk.Length = 1 + valueLength + chunk.Length = 4 + addIf(chunkCode == 0x11, 1) chunk.Type = FMP_CHUNK_SIMPLE_DATA chunk.Value = payload[1:chunk.Length] case 0x12, 0x13, 0x14, 0x15: - valueLength := 1 + 2*(uint64(chunkCode)-0x10) - chunk.Length = 1 + valueLength + chunk.Length = 4 + 2*(uint64(chunkCode)-0x11) chunk.Type = FMP_CHUNK_SIMPLE_DATA chunk.Value = payload[1:chunk.Length] case 0x16: - valueLength := uint64(payload[4]) + chunk.Length = 5 + uint64(payload[4]) chunk.Type = FMP_CHUNK_LONG_KEY_VALUE - chunk.Length = 5 + valueLength chunk.Key = parseVarUint64(payload[1 : 1+3]) chunk.Value = payload[5:chunk.Length] case 0x17: - valueLength := parseVarUint64(payload[4 : 4+2]) - chunk.Length = 6 + valueLength + chunk.Length = 6 + parseVarUint64(payload[4:4+2]) chunk.Type = FMP_CHUNK_LONG_KEY_VALUE chunk.Key = parseVarUint64(payload[1 : 1+3]) chunk.Value = payload[6:chunk.Length] - case 0x19: + case 0x19, 0x1A, 0x1B, 0x1C, 0x1D: + valueLength := uint64(payload[1]) + chunk.Length = 2 + valueLength + 2*uint64(chunkCode-0x19) + addIf(chunkCode == 0x19, 1) chunk.Type = FMP_CHUNK_SIMPLE_DATA - chunk.Length = 2 - chunk.Value = payload[1:chunk.Length] - - case 0x1A, 0x1B, 0x1C, 0x1D: - valueLength := 2 * uint64(chunkCode-0x19) - chunk.Length = 1 + valueLength - chunk.Type = FMP_CHUNK_SIMPLE_DATA - chunk.Value = payload[1:chunk.Length] + chunk.Value = payload[2 : 2+valueLength] case 0x1E: keyLength := uint64(payload[1]) @@ -242,18 +219,18 @@ func (sect *FmpSector) readChunk(payload []byte) (*FmpChunk, error) { chunk.Value = payload[2+keyLength+1 : chunk.Length] case 0x1F: - keyLength := uint64(uint64(payload[1])) + keyLength := uint64(payload[1]) valueLength := parseVarUint64(payload[2+keyLength : 2+keyLength+2+1]) chunk.Length = 2 + keyLength + 2 + valueLength chunk.Type = FMP_CHUNK_LONG_KEY_VALUE chunk.Key = parseVarUint64(payload[2 : 2+keyLength]) chunk.Value = payload[2+keyLength+2 : chunk.Length] - case 0x20: + case 0x20, 0xE0: if payload[1] == 0xFE { chunk.Length = 10 chunk.Type = FMP_CHUNK_PATH_PUSH - chunk.Value = payload[1:chunk.Length] + chunk.Value = payload[2:chunk.Length] break } @@ -262,17 +239,12 @@ func (sect *FmpSector) readChunk(payload []byte) (*FmpChunk, error) { chunk.Value = payload[1:chunk.Length] case 0x23: - chunk.Length = 2 + chunk.Length = 2 + uint64(payload[1]) chunk.Type = FMP_CHUNK_SIMPLE_DATA chunk.Value = payload[1:chunk.Length] - case 0x28: - chunk.Length = 3 - chunk.Type = FMP_CHUNK_PATH_PUSH - chunk.Value = payload[1:chunk.Length] - - case 0x30: - chunk.Length = 4 + case 0x28, 0x30: + chunk.Length = 3 + addIf(chunkCode == 0x30, 1) chunk.Type = FMP_CHUNK_PATH_PUSH chunk.Value = payload[1:chunk.Length] @@ -296,3 +268,10 @@ func (sect *FmpSector) readChunk(payload []byte) (*FmpChunk, error) { return chunk, nil } + +func addIf(cond bool, val uint64) uint64 { + if cond { + return val + } + return 0 +}