6 ms·
> ordinary code is memory-safe by default What does that mean? What constitutes "ordinary"? I'm not sure there is any official definition of memory safety, but
by thinkharderdev 2y ago
> ordinary code is memory-safe by default
What does that mean? What constitutes "ordinary"? I'm not sure there is any official definition of memory safety, but I would consider it to mean that aside from code that is explicitly marked as unsafe it is impossible to write code that has undefined behavior.
- tptacek 2y agoAn example of extraordinary code would be code that interfaces with and/or pulls in non-memory-safe legacy C code. Another example would be code specifically contrived to highlight a soundness problem in the language. I used the term "extraordinary" to avoid exactly this kind of bickering over corner cases that aren't relevant to day-to-day software development (or at least, not in ways that aren't immediately evident when they come up.)
- thinkharderdev 2y ago> An example of extraordinary code would be code that interfaces with and/or pulls in non-memory-safe legacy C code. That's my point though. Of course calling non-memory safe native code over FFI can lead to memory-safety problems in any language. Likewise using the "unsafe" subset that basically every language has. But none of that is required in Go. It is only required that you mutate shared state from different threads, which is something that I would imagine happens in a lot of Go code codebases since it is an extremely easy mistake to make. To be clear I think: 1. Go is mostly a memory safe language because it does in fact prevent the most common memory safety issues in C/C++ (UAF, buffer overflows, etc) 2. It is LESS memory safe than other modern memory-sage languages (Rust, Java, C#, Python, etc....) 3. The memory safety issues in Go are very difficult to exploit in code that is not specifically crafted to surface them
- kccqzy 2y agoGood definition. I've seen Go beginners trying to append to a slice from multiple goroutines. It works as well as calling push_back on the same vector from multiple threads in C++. It can easily corrupt GC state and lead to segfaults. The beginner didn't use any advanced trickery or the unsafe package. Therefore Go is not a memory safe language.
- sshine 2y ago> Therefore Go is not a memory safe language. Interesting. To quote the NSA [1], "Some examples of memory safe languages are Python, Java, C#, Go, Delphi/Object Pascal, Swift, Ruby, Rust, and Ada. Memory safe languages provide differing degrees of memory usage protections, so available code hardening defenses, such as compiler options, tool analysis, and operating system configurations, should be used for their protections as well." The narrow definition of memory safety here is: Go has garbage collection, so you won't have memory leaks or use-after-free. Go is powerful enough that beginners can cause segfaults by accidentally abusing internals, okay. I'm not sure this is a very redeeming property of Go: Being able to crash the GC, without the flexibility of manual memory management. But I'm not sure I'd categorize it as "not memory safe" for the same reason C/C++ aren't (a trade-off). Because I don't believe that you can generally leverage this for the kinds of memory exploits made in C/C++. I recall that some ML dialects (Standard ML and OCaml) have a library function Obj.magic : 'a -> 'b which escapes the type system. Using this can easily cause segfaults. Does that mean Standard ML and OCaml are not memory safe? Generally, no, they're extremely safe if you avoid that feature, which is most likely. This is arguably less safe than Go, since you most likely won't accidentally run that function. [1]: https://media.defense.gov/2022/Nov/10/2003112742/-1/-1/0/CSI_SOFTWARE_MEMORY_SAFETY.PDF https://media.defense.gov/2022/Nov/10/2003112742/-1/-1/0/CSI...
- kccqzy 2y agoI'm trying to provide some commentary to OP's original term of "ordinary code" three comments above. While this term is inherently ambiguous and subjective, my personal opinion is that appending to slices simultaneously from multiple goroutines count as "ordinary code" but Obj.magic does not.
- tptacek 2y agoYes. And: you will run into correctness bugs quickly if you mutate shared references in Go code. It's only my contention that you won't create a security vulnerability, in the colloquial understanding of the term (ie: a panic doesn't count).
- danielheath 2y agoGo lets you use `unsafe.Pointer` (or indeed, assembly intrinsics) if you really want to, but those are certainly not used "ordinarily".
- tsimionescu 2y agoIt's not just about that. Data races can expose an object in a state that was never written from any thread in Go, potentially corrupting even internal details not exposed. Simply writing a struct value from two different threads can expose this.