You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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.
@evanj , thanks for the detailed analysis. It looks like the bug can be triggered only if the byte slice b is allocated on a stack for the call C.f(uintptr(unsafe.Pointer(&b[0]))). This issue doesn't apply if b is allocated on a heap, since the &b[0] address doesn't change during stack growth.
That is my analysis as well. However, in that case, I think this means the optimization of using uintptr_t is useless: my understanding is this optimization allows the compiler to be able to allocate objects on the stack. If they aren't ever allocated on the stack, you might as well use unsafe.Pointer because it is both safe and equivalent in terms of memory allocations (I think?)
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:
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
The text was updated successfully, but these errors were encountered: