gordonklaus / portaudio

Go bindings for the PortAudio audio I/O library
MIT License
704 stars 95 forks source link

fatal error: checkptr: pointer arithmetic result points to invalid allocation #57

Closed timo-klarshift closed 1 year ago

timo-klarshift commented 1 year ago

I am getting the following trace when running a test with the -race flag:

fatal error: checkptr: pointer arithmetic result points to invalid allocation

goroutine 20 [running]:
runtime.throw({0x718607?, 0x8?})
        /usr/lib/go/src/runtime/panic.go:1047 +0x5d fp=0xc00011bb98 sp=0xc00011bb68 pc=0x449e5d
runtime.checkptrArithmetic(0x1?, {0x0, 0x0, 0xc80?})
        /usr/lib/go/src/runtime/checkptr.go:69 +0xaa fp=0xc00011bbc8 sp=0xc00011bb98 pc=0x41a00a
github.com/gordonklaus/portaudio.getBuffer(0xc000190060, 0xc0001ae000)
        /home/user/go/pkg/mod/github.com/gordonklaus/portaudio@v0.0.0-20221027163845-7c3b689db3cc/portaudio.go:1038 +0x353 fp=0xc00011bc58 sp=0xc00011bbc8 pc=0x668633

Without the race flag - everything works without issues.

timo-klarshift commented 1 year ago
 func getBuffer(s *reflect.SliceHeader, p *C.PaStreamParameters) (unsafe.Pointer, int, error) {
    if p.sampleFormat&C.paNonInterleaved == 0 {
        n := int(p.channelCount)
        if s.Len%n != 0 {
            return nil, 0, fmt.Errorf("length of interleaved buffer not divisible by number of channels")
        }
        return unsafe.Pointer(s.Data), s.Len / n, nil
    } else {
        if s.Len != int(p.channelCount) {
            return nil, 0, fmt.Errorf("buffer has wrong number of channels")
        }
-       buf := make([]uintptr, s.Len)
+       buf := make([]reflect.SliceHeader, s.Len)
        frames := -1
-       sp := s.Data
+       sp := (*[1 << 30]reflect.SliceHeader)(unsafe.Pointer(s.Data)) // convert s.Data to a SliceHeader slice
        for i := range buf {
-           ch := (*reflect.SliceHeader)(unsafe.Pointer(sp))
+           ch := &sp[i]
            if frames == -1 {
                frames = ch.Len
            } else if ch.Len != frames {
                return nil, 0, fmt.Errorf("channels have different lengths")
            }
-           buf[i] = ch.Data
+           buf[i] = *ch
-           sp += unsafe.Sizeof(reflect.SliceHeader{})
        }
-       return unsafe.Pointer(&buf[0]), frames, nil
+       return unsafe.Pointer(&buf[0].Data), frames, nil
    }
 }
timo-klarshift commented 1 year ago

I am running Go 1.20.4

timo-klarshift commented 1 year ago

I was not fully sure and it seemed to work in my tests. Thanks for fixing so quickly!

gordonklaus commented 1 year ago

Thanks for the report!

timo-klarshift commented 1 year ago

May I ask why you are not creating fixed Tags for this repo?

gordonklaus commented 1 year ago

I guess it never crossed my mind. It's not a very active repo. What's the benefit?

timo-klarshift commented 1 year ago

To use it with clear versions as a dependency without having to specify commit hashes in go.mod. It's just easier to communicate a specific version. But it's not a big deal either..