Ugh. I know all that and I am still sick of hearing about memory safety. My teammates spend way more time fixing security issues in “safe” languages than C/C++/whatever. It simply doesn’t matter…
Rust certainly was not the first "systems programming" language that was memory safe, ADA was aiming for the same title and I think achieved it way before Rust.
Small nit: As someone curious about a definition of memory safety, I had come across Michael Hicks' post. He does not use the list of errors as definition, and argues that such a definition is lacking rigor and he is right. He says;
> Ideally, the fact that these errors are ruled out by memory safety is a consequence of its definition, rather than the substance of it. What is the idea that unifies these errors?
He then offers a technical definition (model) involving pointers that come with capability of accessing memory (as if carrying the bounds), which seems like one way to be precise about it.
I have come to the conclusion that language safety is about avoiding untrapped errors, also known as "undefined behavior". This is not at all new, it just seems to have been forgotten or was never widely known somehow. If interested, find the argument here https://burakemir.ch/post/memory-safety-the-missing-def/
This article comes up with yet another definition of memory safety. Thankfully, it does not conflate thread safety with memory safety. But it does a thing that makes is both inaccurate (I think) and also not helpful for having a good discussion:
TFA hints at memory safety requiring static checking, in the sense that it's written in a way that would satisfy folks who think that way, by saying thingys like "never occur" and including null pointer safety.
Is it necessary for the checking to be static? No. I think reasonable folks would agree that Java is memory safe, yet it does so much dynamic checking (null and bounds). Even Rust does dynamic checking (for bounds).
But even setting that aside, I don't like how the way that the definition is written in TFA doesn't even make it unambiguous if the author thinks it should be static or dynamic, so it's hard to debate with what they're saying.
EDIT: The definition in TFA has another problem: it enumerates things that should not happen from a language standpoint, but I don't think that definition is adequate for avoiding weird execution. For example, it says nothing about bad casts, or misuses of esoteric language features (like misusing longjmp). We need a better definition of memory safety.
It seems obvious that with hardware-level memory safety on the way[1], just gradually modernizing existing C and C++ codebases to take advantage of safer constructs (like smart pointers or checked arithmetic) makes much more sense than rewriting everything in Rust. Even better, thanks to GCC, is that you don't need to sacrifice any portability to take advantage of even bleeding-edge features, due to its front-end/back-end separation and multitude of supported platform back-ends. Fish shell had to drop support for some platforms when it was rewritten in Rust[2].
If the 5 eye agencies recommend memory safety, can we conclude that they already get all their information via "AI" data harvesting in Office 365 and similar? What will happen to Pegasus? Or do they have yet unknown backdoors in Rust?
1 The numbers on memory safety should nowadays separate between spatial ones (bounds-checked in most languages with sane flags) and temporal ones. Temporal ones will be lower than 70%.
2 The article does not mention (compilation) time costs of static checks and its influence on growing code bases, which is a more fundamental system trade-off on scalability and development velocity/efficiency.
> Wrap unsafe code with safe interfaces
3 That sounds like an equivalent of using permission-based separation logic hopefully soon available for LLVM.
> "Get good" is not a strategy
4 Being good is all about knowing exactly techniques, processes, and tools with exact trade-offs and applying them; so I would expect here teaching process knowledge about static and dynamic analysis strategies, tooling and tactics to eliminate bug classes.
However, neither have we sane bug classes overviews nor can we generate sane probabilities/statistics of occurrence based on source code and available static and dynamic analysis even when ignoring functionality requirements.
This reads somewhat like developers should "stay mediocre" and "trust the tools", even though "Get good and improve processes for groups" is probably the here intended strategy.
I think memory safety is fine, but I plan to do it in C++ not Rust-- nothing in this article is remotely new either, just repeating the same tired stuff.
It seems pretty clear statistical hardware level memory safety is coming(Apple has it, Intel/AMD have a document saying they are planning to add it), the safety zealots can turn that on, or you can use FilC if you need absolute memory safety, but really C++ with various hardening features turned on is already fairly solid.
Also I think that memory safety is generally less important than thread safety(because memory safety is rather easy to achieve and detect violations), which almost all those languages recommended by this article blow chunks at. Rust could actual make a solid argument here, instead of wasting time yammering about memory safety.
What if, instead of fighting the symptom of people writing faulty, exploitable software, by explaining to them that Rust (as a stand in) is good, we try to fix the cause?
Imagine if for every data breach, every ransomware attack, every intrusion which used privilege escalation etc. there would be an investigation if the company in question is at fault for using insecure software (i.e. written in unsafe languages and not properly vetted). And if the company is found guilty, it is punished accordingly, so that every company is motivated to prevent such cases.
Of course people can still write C / C++ programs as a hobby or publish their software with open source licenses. But the people or organizations using that software must make sure (within reason) that it is safe or they are held liable if it inflicts damage. It would automatically make software written in safe languages much more attractive to them, because safety is much easier to prove – no evangelist needed.
15 comments
[ 4.9 ms ] story [ 44.8 ms ] threadTell me more about memory safety, any time; just hold the Rust.
Rust skeptics are not memory safety skeptics. Hopefully, there are no memory safety skeptics, other than rhetorical strawmen.
Many have no use for borrow checker, and there is already enough choice with ML inspired type systems.
Even PL/I had a higher security score given by the DoD, than C.
Couldn't find this in the reference text. Is it my interpretation? https://www.memorysafety.org/docs/memory-safety/#how-common-...
Small nit: As someone curious about a definition of memory safety, I had come across Michael Hicks' post. He does not use the list of errors as definition, and argues that such a definition is lacking rigor and he is right. He says;
> Ideally, the fact that these errors are ruled out by memory safety is a consequence of its definition, rather than the substance of it. What is the idea that unifies these errors?
He then offers a technical definition (model) involving pointers that come with capability of accessing memory (as if carrying the bounds), which seems like one way to be precise about it.
I have come to the conclusion that language safety is about avoiding untrapped errors, also known as "undefined behavior". This is not at all new, it just seems to have been forgotten or was never widely known somehow. If interested, find the argument here https://burakemir.ch/post/memory-safety-the-missing-def/
TFA hints at memory safety requiring static checking, in the sense that it's written in a way that would satisfy folks who think that way, by saying thingys like "never occur" and including null pointer safety.
Is it necessary for the checking to be static? No. I think reasonable folks would agree that Java is memory safe, yet it does so much dynamic checking (null and bounds). Even Rust does dynamic checking (for bounds).
But even setting that aside, I don't like how the way that the definition is written in TFA doesn't even make it unambiguous if the author thinks it should be static or dynamic, so it's hard to debate with what they're saying.
EDIT: The definition in TFA has another problem: it enumerates things that should not happen from a language standpoint, but I don't think that definition is adequate for avoiding weird execution. For example, it says nothing about bad casts, or misuses of esoteric language features (like misusing longjmp). We need a better definition of memory safety.
[1] https://community.intel.com/t5/Blogs/Tech-Innovation/open-in...
[2] http://fishshell.com/blog/rustport/
2 The article does not mention (compilation) time costs of static checks and its influence on growing code bases, which is a more fundamental system trade-off on scalability and development velocity/efficiency.
> Wrap unsafe code with safe interfaces
3 That sounds like an equivalent of using permission-based separation logic hopefully soon available for LLVM.
> "Get good" is not a strategy
4 Being good is all about knowing exactly techniques, processes, and tools with exact trade-offs and applying them; so I would expect here teaching process knowledge about static and dynamic analysis strategies, tooling and tactics to eliminate bug classes. However, neither have we sane bug classes overviews nor can we generate sane probabilities/statistics of occurrence based on source code and available static and dynamic analysis even when ignoring functionality requirements. This reads somewhat like developers should "stay mediocre" and "trust the tools", even though "Get good and improve processes for groups" is probably the here intended strategy.
It seems pretty clear statistical hardware level memory safety is coming(Apple has it, Intel/AMD have a document saying they are planning to add it), the safety zealots can turn that on, or you can use FilC if you need absolute memory safety, but really C++ with various hardening features turned on is already fairly solid.
Also I think that memory safety is generally less important than thread safety(because memory safety is rather easy to achieve and detect violations), which almost all those languages recommended by this article blow chunks at. Rust could actual make a solid argument here, instead of wasting time yammering about memory safety.
Imagine if for every data breach, every ransomware attack, every intrusion which used privilege escalation etc. there would be an investigation if the company in question is at fault for using insecure software (i.e. written in unsafe languages and not properly vetted). And if the company is found guilty, it is punished accordingly, so that every company is motivated to prevent such cases.
Of course people can still write C / C++ programs as a hobby or publish their software with open source licenses. But the people or organizations using that software must make sure (within reason) that it is safe or they are held liable if it inflicts damage. It would automatically make software written in safe languages much more attractive to them, because safety is much easier to prove – no evangelist needed.