Skip to content

Cgo wrappers cannot safely pass uintptr to C functions #33

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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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