Skip to content

Cgo wrappers cannot safely pass uintptr to C functions #33

@evanj

Description

@evanj

This package passes uintptr to C functions, which is not safe. It can cause memory corruption in rare cases. I did not try to reproduce this bug with this package, because it is subtle. However, we have a package with similar code, and we ended up with a memory corruption bug: DataDog/zstd#90 . I'm filing this issue because I noticed this package uses the same pattern, so it probably has the same problem.

The unlucky sequence is:

  • Code evaluates the uintptr from a Go pointer to a variable on the stack.
  • Code calls the Cgo wrapper.
  • The Go runtime decides this goroutine needs a larger stack, and copies it somewhere else. It fixes the pointers to variables on the stack. It cannot fix the uintptr variable, since it does not think it is a pointer.
  • Another thread uses the previous stack and changes the contents.
  • The C code casts the uintptr to a pointer, then reads from the wrong memory.

One example piece of code that does this is: https://github.com/valyala/gozstd/blob/master/gozstd.go#L17 , however there are many others. In many cases, I think using unsafe.Pointer instead will not impact the performance of gozstd. For example, the Writer API already copies data into its own heap-allocated buffer, before calling Cgo.

For details, see my reproduction of this problem: https://github.com/evanj/cgouintptrbug

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions