← Back to context

Comment by shikck200

8 hours ago

That does not make sense to me. Go is memory-safe, but it does not guarantee data-race freedom.

So whats your point here? Haskell?

> That does not make sense to me.

You said that because you assumed Go is memory-safe in all conditions.

> Go is memory-safe

Yes, but only if there's no data race.

Go is not like Java. Java doesn't guarantee no data race, but when it happens, it's still memory-safe.

  • Neither Java or Go guarantees data-race freedom. A data race does not by itself make ordinary Java or Go code memory-unsafe in the C/C++ sense.

    I fail to see how a racy Java program is more memory safe than a racy Go program?

    • Java arrays are thin pointers to Array objects, which contain the length and data in the same place (on the far side of the pointer). Since thin pointers cannot tear and Array objects cannot be resized, Arrays themselves are always memory-safe in safe code.

      Go slices are fat pointers to undecorated memory. The slice itself is a 3-tuple of pointer, length, and capacity. If you append to a slice that's already at capacity, the Go runtime will allocate new memory for you and return a new 3-tuple. If you assign that result to a variable that's also being accessed by another goroutine, the latter can observe the slice in an inconsistent state. It can, for example, see the old pointer but with the new length, allowing out-of-bounds access. None of this requires unsafe code.

      The same issue applies to string and interface variables, which are also fat pointers.

      3 replies →

    • From what I understand a data race on a simple built in feature like an interface pointer can result in a bad address / type pair, which can cause memory safety issues on any future access. I don't think you can get the JVM itself confused about what type a pointer points to.

There is no memory safety without freedom from data races. One is a prerequisite of the other. This is why languages like C# throw exceptions on unsynchronized concurrent access to some container types, and treat all property accesses as atomic.

  • From the former head of the Go security team [1]:

    > I have never seen real Go code (i.e. not code written purposefully to be exploitable) that was exploitable due to a data race.

    And from tptacek in that same discussion [2]:

    > The fact is that Go doesn't admit memory corruption vulnerabilities, and the way you know that is the fact that there are practically zero exploits for memory corruption vulnerabilities targeting pure Go programs, despite the popularity of the language.

    [1] https://news.ycombinator.com/item?id=44672371

    • Memory safety isn’t really about vulnerabilities. This thread is about Go, so I won’t go further into it here.

  • Are you saying any language that does not promise data-race freedom is memory unsafe? That would rule out almost every programming language.

    • I am, but you’d be surprised. All of the single-threaded languages are fine, for example. Very few languages are actually low-level enough to allow data races. C# and Java go to great lengths to avoid it.

      Race conditions in general are another matter, and aren’t generally considered a requirement (though you can certainly create nasty bugs).

      4 replies →

I suppose that if you create a map in one thread, and then access it from another thread, then that might cause segmentation faults? Because map is a type that is implemented in C.

  • Yes, writing to maps isn't threadsafe, hence sync.Map. I learned this the hard way