7 ms·
When to use memory safe languages
- scaredginger 4y agoThis is such a broad topic with so much to cover, I admire the author's willingness to tackle it. There's a ton of information one could say belongs in the article, but I don't think it would ever be written if they had tried to cover everything. All in all, I think this is a pretty good introduction, with a good trade-off between completeness and digestibility
- karolsputo 4y agoThis. Let’s not jump to the conclusion that making this point today is a silly argument or even an evil deed. For someone who writes mostly in GC languages this was a great read and can recommend. Even with switching to <your_safe_language> let’s not loose awareness of what is possible to strengthen current approaches.
- bheadmaster 4y agoThere are generally four approaches to memory safety: [...] Reference counting (RC), like in Swift, Nim, Lobster, etc. Reference Counting by itself does not provide memory safety, as it cannot handle cyclic references, which would lead to memory leaks in any sufficiently complex program. I don't have direct experience in any of the mentioned languages, but I seriously doubt they use Reference Counting as a sole mechanism for managing memory.
- Xylakant 4y agoRust provides explicit mechanisms to leak memory and its notion of memory safety does not include “never leaks” . A rust program that leaks memory like a sieve is considered safe.
- norman784 4y agoI think weak references solves that issue. > A weak reference is a reference that doesn’t keep a strong hold on the instance it refers to, and so doesn’t stop ARC from disposing of the referenced instance. [0] [0] https://docs.swift.org/swift-book/LanguageGuide/AutomaticReferenceCounting.html https://docs.swift.org/swift-book/LanguageGuide/AutomaticRef...
- bheadmaster 4y agoThey would solve the issue only if the language itself forbid the programmer from creating cyclic strong references. If that's the case, then I was wrong in my original comment. Although the thought of forbidding arbitrary references feels a little restrictive to me - it would be placing the burden of keeping a tree of references onto the programmer. I don't know how well that works in practice. Perhaps trying out some of the mentioned languages would be insightful.
- masklinn 4y ago> which would lead to memory leaks in any sufficiently complex program. Memory leaks (and more generally resource leaks) are not generally considered memory safety issues. After all, that's basically what an advanced GC manages for you: you leak memory, and it tries to clean up after you. But whether it does is entirely up to it and its configuration (nothing precludes disabling it and leaking all the memory, there's nothing actionable at the language level).
- deleted 4y ago[deleted]
- scaredginger 4y agoYou have a point, but memory leaks generally aren't considered as problematic as other memory issues, such as buffer overruns and use after free. While they can cause programs to crash and degrade, they generally don't corrupt program data or lead to security vulnerabilities. As such, people often don't include protection from memory leaks as a criterion for 'memory safety'. It's possible to explicitly leak memory in the safe subset of Rust (e.g. Box::leak). It's also possible to 'leak' memory in GC'd languages too by keeping old references around you'll never use, although this example is just arguing semantics even more.
- bheadmaster 4y ago> memory leaks generally aren't considered as problematic as other memory issues, such as buffer overruns and use after free. [...] they generally don't corrupt program data or lead to security vulnerabilities. I see. Although that definition of safety feels a little wrong to me, I can't think of any security issue that could be caused by a memory leak. Perhaps OOM killer butchering random processes on the system, bringing it to some vulnerable state? But then again - that's a system failure, as any well-behaved process might as well use more memory than is available.
- hedora 4y agoSafety usually means the program isn’t doing something wrong. You are thinking of liveness, which means the program continues to do something good. If killing a process leaves the system in an unsafe state, that’s probably not the fault of the OOM killer. (What if the killed process was slow to start, or failed an assert and exited instead?)
- jerf 4y agoIt can depend on your precise definition of "safe". If you define it in terms of accessing correct memory, leaked memory may be inconvenient, it may be "incorrect", but it is safe. It is not, on its own, a security issue (other than eventually leading to possible program termination due to resource exhaustion, which is considered a security issue but I've always thought of this as generally "just barely" in the security class of issue). It may be chained into one if some other bug allowed access to it, but that "some other bug" would itself be the memory unsafe bug.
- skohan 4y agoIt may not even be incorrect. For instance if the only thing you care about is raw speed, an allocator which just grabs pages of memory and never deallocates or overwrites might be the optimal solution, especially if it's provable allocations will never grow beyond a certain upper limit.
- cb321 4y agoNim is choice, including choice among a variety of memory management options including manual, markAndSweep style collection, reference counting variants, etc.
- tptacek 4y agoThis seems like a long axiomatic rationalization for using memory-unsafe languages. "[W]ith the right tooling, practices, and discipline, one can reduce the risk of memory safety bugs to an acceptable level for their situation". Well, empirically, no, that's not the case: the largest, most sophisticated teams in the world have tried, and it hasn't worked out.
- sanxiyn 4y agoDo you have an argument why CHERI wouldn't work? As far as I know CHERI has not been tried yet.
- pcwalton 4y agoCHERI doesn't do anything for use-after-free. It's basically a bounds checking solution.
- CraigJPerry 4y ago>> Well, empirically, no, that's not the case Rust itself has had more CVEs in the past 18 months than Postfix (written in C) has had in the past 18 years [1]. So it must be more nuanced than you're claiming. EDIT: Postfix is somewhere in the region of 1,000x to 10,000x more popular than rust - it's hard to compare a compiler to a mail transfer agent but the MTA is in the more risky use case and yet fares better despite having more sysadmins deploying it than there are rust developers. [1] https://www.cvedetails.com/vulnerability-list/vendor_id-19029/product_id-48677/Rust-lang-Rust.html https://www.cvedetails.com/vulnerability-list/vendor_id-1902... https://www.cvedetails.com/vulnerability-list/vendor_id-8450/Postfix.html https://www.cvedetails.com/vulnerability-list/vendor_id-8450...
- scaredginger 4y agoI mean, you're not wrong, but cherry-picking two examples that aren't really comparable isn't a good argument
- 4y ago
- Octoth0rpe 4y agoGiven that many 'memory safe' languages offer escape hatches for non-memory-safe code, shouldn't the answer rather obviously be "always"? Assuming no extra constraints like compatibility with a large amount of non-memory-safe code, and that the language is actually fit for purpose (don't use js for kernel modules, nim as a procedural language in postgres)
- hedora 4y agoSadly, no, there isn’t always a memory safe language that is fit for purpose. For one thing, the article lists 5 memory management techniques. It is reasonably common for sufficiently large, high performance C++ code bases to rely on three or four of the things on that list, all in the same process. The compiler can only partially verify that the application is not crossing the streams by passing memory from one allocator subsystem into another. Also, memory unsafe languages are sometimes safer on some other dimension than the most obvious memory safe alternative. For instance, it is trivial to write C++ code that provides constant, non-null references (in the absence of UB), but completely impossible to express those invariants in the Java type system.
- chromatin 4y agoThe author gave the following suggestions for how to use manual memory management (MMM) languages more safely: - Don't use malloc. - For long-lived allocations, use per-type arrays. - In a game, we might have an array for all Ships, an array for all Missiles, and an array for all Bases. - For temporary allocations, one can also use an arena allocator. - For temporary allocations whose pointers don't escape, one can also use the stack. - All unions must be tagged 11 and treated as values. - Always use bounds checking. The author then gives a list of tools like ASAN to perform various analyses (static and dynamic) to help further increase safety. What I did not see, however, was one of the simplest and most effective suggestions for MMM programs: Never free. That is, in batch type workloads, scientific computing, and many things that are not a long-running server process, you may have the liberty and resources to allocate but never free, and this could also be an important tool in your chest.
- cb321 4y agoAlong these lines, there is also (from 1988!) the Boehm Garbage Collector just an -lboehm away on your link line which in your suggested mode can reclaim (most) of the memory you might think you would lose. [1] (C does have many gotchas, though.) [1] https://en.wikipedia.org/wiki/Boehm_garbage_collector https://en.wikipedia.org/wiki/Boehm_garbage_collector
- wrs 4y agoThe best way to do “never free” is suggestion #4, an arena allocator.
- hedora 4y agoNice article. It would be nice if it touched on thread safety, since that is inseparable from memory safety these days. Maybe in part 2?
- rurban 4y agoRC alone can never be memory safe, only GC can. First: cyclic structures (just leaks). Second: wrong refcounts leading to UAF (use-after-free), in minor cases leaks.