diff --git a/binary.go b/binary.go index 95de772..3a9034f 100644 --- a/binary.go +++ b/binary.go @@ -329,7 +329,7 @@ func (r *BinaryReader) Seek(off int64, whence int) (int64, error) { if off < -r.f.Len() || 0 < off { return 0, fmt.Errorf("invalid offset") } - r.pos = r.f.Len() - off + r.pos = r.f.Len() + off } else { return 0, fmt.Errorf("invalid whence") } @@ -439,7 +439,8 @@ func (r *BinaryReader) ReadInt16() int16 { // ReadInt24 reads a int24 into an int32. func (r *BinaryReader) ReadInt24() int32 { - return int32(r.ReadUint24()) + // no int24 to convert through, so sign-extend from bit 23 + return int32(r.ReadUint24()<<8) >> 8 } // ReadInt32 reads a int32. diff --git a/binary_test.go b/binary_test.go index 54bbb55..0ebc526 100644 --- a/binary_test.go +++ b/binary_test.go @@ -1,6 +1,7 @@ package parse import ( + "io" "testing" "github.com/tdewolff/test" @@ -23,3 +24,30 @@ func TestBinaryReaderFullRead(t *testing.T) { test.T(t, NewBinaryReaderBytes([]byte{1, 2, 3, 4}).ReadUint32(), uint32(0x01020304)) test.T(t, NewBinaryReaderBytes([]byte{1, 2, 3, 4, 5, 6, 7, 8}).ReadUint64(), uint64(0x0102030405060708)) } + +func TestBinaryReaderSeekEnd(t *testing.T) { + // io.SeekEnd counts back from the end, so a negative offset moves earlier. + buf := []byte{1, 2, 3, 4, 5, 6, 7, 8} + for _, tt := range []struct { + off int64 + want int64 + }{{0, 8}, {-1, 7}, {-4, 4}, {-8, 0}} { + r := NewBinaryReaderBytes(buf) + pos, err := r.Seek(tt.off, io.SeekEnd) + test.T(t, err, nil) + test.T(t, pos, tt.want) + } + + r := NewBinaryReaderBytes(buf) + _, err := r.Seek(-4, io.SeekEnd) + test.T(t, err, nil) + test.T(t, r.ReadUint32(), uint32(0x05060708)) +} + +func TestBinaryReaderInt24(t *testing.T) { + for _, v := range []int32{-1, -2, -8388608, 0, 1, 8388607} { + w := NewBinaryWriter(nil) + w.WriteInt24(v) + test.T(t, NewBinaryReaderBytes(w.Bytes()).ReadInt24(), v) + } +}