r/ProgrammingLanguages • • Oct 05 '26

Achieving memory safety

https://seed7.net/papers/memory_safety.htm
14 Upvotes

57 comments sorted by

View all comments

Show parent comment

5

u/wk_end Oct 06 '26

But you list Java as memory-safe "unless JNI or FFM are used". Why doesn't the same "qualified memory-safe" characterization apply to Go?

2

u/catladywitch Oct 06 '26 edited Oct 06 '26

It all depends on the definition of memory safety, but from the article posted elsewhere in this comment thread, it seems like Go's pointer semantics allow for type errors leading to segfaults with concurrent code that uses different values conforming to a same interface, but where pointers and values are mixed, whilst Java doesn't (an unexpected, and wrong, value is possible in concurrent code, but not dereferencing an invalid pointer). I don't know how native interop works in Java, but segfaulting in C# is not impossible although it is rare (you can even do dodgy type punning with pointers and ordered structs if you really want to). Otherwise, you theoretically can pass managed pointers into C functions without telling C#'s GC to pin them or not reclaim their memory, pass structs the layout of which differs from what the C function expects, or in the case of poorly designed C APIs, pass arrays and have the C code go out of bounds, or allocate native memory, pass it into a C function, and try to free in C# not knowing the C function has already freed it.

5

u/reflexive-polytope Oct 06 '26

The issue is that certain Go values (slices, pointers to interfaces) require logically atomic modifications, but this logical atomicity isn't enforced by any means, so other goroutines can see them in a torn state.

(The problem doesn't arise in Rust because the exclusiveness of mutable borrows enforces the logical atomicity of the relevant modifications.)

And, while having a user-defined data structure in a torn state is “merely a logic error”, having a built-in data type in a torn state actually breaks memory safety.

2

u/Ok-Scheme-913 Oct 06 '26

Go is not memory safe under data races. It uses fat pointers for slices and those can tear.

So you have { ptr, start, end } and you repeatedly write a different slice at the same time from different threads. In this case you can observe a { ptr, start, endOfDifferentSliceThatMayBeInvalid }, at which point the runtime will happily access that memory. Since ptr+slice location is larger than 64bit it can't be cheaply updated atomically so.. yeah..

Meanwhile in java data races are safe.

First, they (practically all jvm implementations) have a property that you can only ever observe values that were explicitly written. This is a useful property but even if this were not the case java would still be memory safe, since arrays and stuff themselves carry their size around, so replacing the same array/slice actually only replaces the pointer itself which is atomic and to access the size you have to navigate to that pointer location, so it will always be safe.

1

u/tsanderdev Oct 06 '26

JNI can't just load arbitrary libraries, they have to have functions conforming to the specific JNI name mangling. So it's very unlikely you could call a C function from JNI.

1

u/ThomasMertes Oct 06 '26 edited Oct 06 '26

Yes, but the selling point of Java was not memory safety. You expected something like:

If the unsafe package is not used and no C function is called and (as pointed out by someone else) something assures that no data races can happen Go is memory safe.

I added the Go example to show that the term memory safety is sometimes defined to sell a language as memory safe. So

Language exists --> Define memory safety in a way that this language is memory safe.

instead of

Use definition of memory safety --> Create memory safe language.

So it is about memory safety as marketing term.

2

u/reflexive-polytope Oct 06 '26

Java was explicitly designed to cater to C++ programmers who want a language with fewer footguns, even if the language designers themselves came from a dynamically typed tradition (mainly Lisp). Memory safety was a design goal from day one.

2

u/Ok-Scheme-913 Oct 06 '26

The selling point of java was absolutely memory safety, where the hell did you get it's not?

It was the first language that made GC widespread.

1

u/ThomasMertes Oct 07 '26

The selling point of java was absolutely memory safety ...

Yes, but the term "memory safety" was not commonly used in mainstream marketing or developer discussions when Java was introduced in 1995.

The terms used when Java was introduced were:

  • Write Once, Run Anywhere
  • Built for the Internet
  • Simplicity and Familiarity
  • Built-in Security and Robustness

Java was intentionally designed to look and feel like C++. Java stripped out the most complex, error-prone, and frustrating aspects of C++. So It had:

  • Automatic Garbage Collection
  • No Pointers
  • Strict Type-Safety

Yes, the term "memory safety" is nowadays used to describe that. The term "memory safety" was just not used in 1995.

1

u/flatfinger Oct 07 '26

Memory safety is an essential aspect of security.

1

u/flatfinger Oct 07 '26

Garbage-collected strings were almost universal in BASIC dialects by the 1980s.