Rust, Zig, and the Futility of “Replacing” C
gavinhoward.com
gavinhoward.com
OpenSSH, a program written by one of the most security conscious groups of developers out there (OpenBSD), used widely by pretty much every technology company out there including all of the top 8 companies in the world, has had multiple memory safety problems over its lifetime, /none/ of which would have happened in Rust, Zig, or any of their ilk.
Yes, portability in LLVM-based languages is a problem for sure. Even an LLVM/GCC monoculture isn't particularly great. But saying "nah, you're just doing it wrong"? No.
Cryptography is not far off of bc. It is deterministic and should be easily testable.
My bc is battle-hardened because I did my due diligence. The authors of the Cryptography library are writing _crypto_, which requires such due diligence. Did they?
What I should add to the post is that if they were not planning on doing that due diligence from the start, they should have written it in Rust from the beginning and not made promises to users that they couldn't keep.
It’s open source software. There are no promises.
However, if I was very careful with bc, despite the fact that no one was going to exploit it (which would not be the case if there was a vector for it, such as someone using bc in a script that runs as root), how much more careful should the Cryptography authors have been, since they were writing crypto?
And if they were not going to be careful, they should have used Rust from the beginning and not made (implicit) promises to users.
Edit: typo.
Did you consider that they are being careful by rewriting it in Rust?
> And if they were not going to be careful, they should have used Rust from the beginning and not made (implicit) promises to users.
Maybe Rust wasn't quite there at that point.
So they are only starting to be careful after several years? I addressed that point in the post.
> Maybe Rust wasn't quite there at that point.
It wasn't. But that's the point. Rust wasn't there, it's not there now. It needs to be as portable as C to be "there".
No since you’ll get to the “battle tested” point much fastener.
I'm not sure what you mean here.
Are you saying that a bc will get to a battle-tested state faster than crypto?
If you are, I disagree whole-heartedly. Crypto is bigint math with a few extras. bc has bigint math, a lexer, a parser, and an interpreter. Of those, the parser and interpreter are far more complicated than the bigint math.
And bc's bigint math is not actually just bigint; it's bigdecimal.
If you read deeper into the post, I do, in fact, talk about how supporting those less well-known architectures is important.
Edit: Also, those arguments were made plenty by others, so I didn't feel a need to rehash them much.
> If you read deeper into the post
I did skim the entire post, but the discussion on supporting alternative computer architectures was significantly shorter than the issue of memory safety, or Rust or Zig as languages.
> Also, those arguments were made plenty by others, so I didn't feel a need to rehash them much.
Fair enough.
BTW, I agree with you that generating portable C is actually an interesting solution. Recently, there are a few successful projects like HACL* (Microsoft) [0], Fiat-Crypto (MIT CSAIL) [1] that are based on this idea - they use a high-level framework to synthesize human-unreadable but formally verified C code, effectively using C as a form of portable assembly. Both have been deployed in real-world systems like OpenSSH, Chromium and the Linux kernel with great success.
The fact the post is flagged now somehow makes me feel that Rust community can't stand anything else then praise and worship.
Though don't you think that your criteria would affect all the "X subpar re-implemented in Rust" submissions there are same thing all the time only X changes.
My argument is actually that Rust cannot replace C because it's not portable enough.
I would love for Rust to be portable enough.
I flagged it because it's poorly written flamebait that doesn't add anything to the comments on the GitHub thread.
What they did wrong was making promises to users and then breaking those promises.
I also tried to make the case that they either did not do their due diligence, which they should have done because they used C in the first place, or they did and should not have given up that battle-tested code.
I even mentioned that they were victims of the Rust language not keeping its promises. So I disagree that I am blaming the victim here.
Also, if they did not want to do the due diligence required by using C, they should have written Cryptography in Rust from the beginning and not made promises to users that they couldn't keep.
It's an unsalvageable argument regardless; you have invented a promise nobody made to you, compelling strangers to manage a project in which you have no involvement to conduct their work in accordance with your wishes.
My argument is that Rust _still_ isn't ready for the Cryptography library because it's not portable enough.
And I am not a direct user of the Cryptography library. I am an indirect user on x86_64, so I am unaffected. They have kept their implicit promise to me.
So those paying to Cryptography developers, are the ones to be pissed off, IF their platforms aren't being considered.
Then again, they clearly mention on that page:
" Please put us out of business.
Stop writing C/C++.
Probably you should also sandbox your software. "
But the author is way brighter than I am. I spent my youth programming real-time interrupt rich medical diagnostic software in low-level assembly language, which is harder to get right than C. We had very few bugs. I would be reluctant to do this in C, probably less so in Rust (which I have yet to master)
I appreciate what the Rust community is trying to accomplish, and suspect it will happen.
However, there is an sense of overselling this idea of memory safety. Keep in mind that SolarWinds and Equifax are not memory safety issues. Also, someone wrote a Rust version of heartbleed, so it would be good to keep a perspective.
And it isn't like I haven't been in the position to be rabid promoter of programming demagoguery. First was the unnecessarily limited gammar of Fortran II. I discovered XP/L and promoted that beyond reason. Then there was the GOTO demagogery which I was one of the loudest. And along with that Structured Programming, then Object Oriented Programming.
So as you promote Rust, don't sell the idea that it will prevent every security nightmare out there--it will massively help with some very important ones. Additional work beyond programming language is necessary to improve security.
Naturally memory safe systems programming languages still suffer from the remaining 30% root causes for security exploits.
It isn't perfect, but much better, and we aren't still there because bean counters haven't been paying attention how much money it costs to fix those bugs, and the lack of liability.
But there are exploits and there are breaches. Exploits are bad and Rust will help, but in the rest of industry and government and military, exploits are not the whole story with respect to what causes breaches.
No, it implies that finding such bugs is exponentially harder in C than it is in other languages. Eventually you reach so far up the diminishing returns curve that you simply are able to accomplish more in one language with your time on Earth than you can in another. This is a numbers game, and C loses out to safer competitors when it comes to bugs.
The due diligence that these developers are doing is a meta-analysis that has gone over your head.
> And with my bc, I did my due diligence with memory safety. I fuzzed my bc and eliminated all of the bugs.
That's a pretty absolute claim. And one I doubt.
I'll save my trust for people humble enough to understand the limitations of technologies and themselves.
Probably meant all of the reported bugs, given the context.
For a calculator it may be no huge deal to have such a cavalier attitude. But for cryptography, bugs are considerably more important as the threat model isn't even in the same league.
The fact that I _could have had_ a cavalier attitude towards C memory safety, but didn't, shows (I believe) just how much the Cryptography authors fell short because _they were writing crypto_. If anything, they should have surpassed the amount of due diligence that I did on bc, but they didn't.
I took a quick look over the thread, and TBH I find the authors' reasons and explanations compelling, logical, and respectful (their FAQ, the fact that they polled the users almost a year ago, the fact that they announced their intentions in advance, and how to deal with the impending changes). I suggest you re-think your approach; this won't reflect well.
However, can you tell me more what you mean about rethinking my approach? I am not sure what approach you are referring to.
I don't mean to be rude, but as a disinterested third party, the optics of all of this and your handling of a disagreement reflect badly upon you. At some point in the future after you've cooled off, you'll probably delete the post (but better sooner than later!)
I actually let myself cool down before I wrote the post. I was going to write the post right after I saw the GitHub issue, but I sat on it for awhile, thinking through my thoughts.
It's unfortunate that such a dust-up (which wasn't minor, by the way; it got published in LWN, see https://lwn.net/Articles/845535/) was a perfect way to make arguments against Rust that I have wanted to make.
And I wanted to make them because if Rust can be as portable as C, I would LOVE that!
If you doubt my claims about my bc, I suggest you break it and post it here. Embarrass me.
Yes, I am throwing down the gauntlet because I am that confident in my work. Prove me wrong with actual data.
On the other hand, there's a group of developers with limited resources and perceived moral high ground in terms of security that fits right in with the trends that I've observed in the cryptography community.
Both sides have valid arguments. Which sides of this split you fall on depends on your personal values and immediate needs.
Ultimately, the whole debate is fruitless bickering because you cannot reconcile differences in values. This doesn't just apply to the Python "cryptography" library, but also other places where a switch to Rust was enforced by upstream.
The alternative is to define "closer" portability (iOS, Android, Windows, macOS, desktop/server Linux) and "wider" portability (BSDs, illumos, QNX, custom embedded OSes, architectures that aren't x86_64 and ARM). Then make it clear from the get-go which one of these you're aiming for.
[1] of course the question of who is responsible for building such a compiler potentially becomes a new value-based conflict.
I was surprised by how informal the Rust language semantics are when I was trying to find out how the `?` operator works, exactly. There's no official description anywhere except for an RFC which was created before the feature was introduced, but from which the feature has diverged significantly since it was added to the language!
The Rust Book, normally assumed to be the "true" description of the language, is quite incomplete in places as it's not a formal specification. For example, the section about `?` does not mention that different error types will be auto-converted if there's a `From` implementation between them. This is quite important information missing from the documentation. Just from reading that page, you would be writing really verbose type conversions yourself, everywhere.
But the Rust Book does mention this elsewhere[2] (if you're careful enough reading the first link, you can see that it says `?` is "more or less" equivalent to `try!`, and reading the docs for `try!` you could actually find out what it does, and hope they didn't change anything when implementing `?` - but that's a quite a lot of assumptions). You just need to read the whole book, or at least be lucky enough to look at all the right places, to make sure you understand how a language feature works, precisely.
[1] https://doc.rust-lang.org/edition-guide/rust-2018/error-hand...
[2] https://doc.rust-lang.org/book/ch09-02-recoverable-errors-wi...
https://doc.rust-lang.org/stable/reference/expressions/opera...
My point, above all, is not tied to this specific example, by the way, hope you understand how an informal tutorial about the language does not replace a strict specification - and pointing out that such information is available somewhere if I look hard enough does not disprove anything.
I didn't look very hard, I went to the language reference and searched for "?" in the Tokens section.
One I can think of is doing coroutine / stack swapping stuff. Though even that is not insurmountable if your sequential code is rendered into C in a “CPS” style.
Another related one is exotic manipulations of the instruction pointer beyond what goto/switch provide. This can be solved too, but inefficiently (put all jump-to-able lines of code in a big switch statement). GCC provides computed goto but that is not standard.
In either case, it’s worth pointing out that Rust does not do these types of things and it would be relatively straightforward for a machine to create a 100% semantically equivalent C program from a rust program.
Semantics of loops might also be tricky. In fact rust struggles with LLVM's optimizer already on some infinite loops because C++ and rust diverge in semantics there.
[1] gcc for example generates optimal code when doing checked addition: https://godbolt.org/z/9jnesx
It's a bit more subtle than that, but that is completely devoid of Undefined, Unspecified, and Implementation-Defined Behavior.
They’re actively working on a spec for Zig btw. Here’s Andrew talking about it, first thing as part of the roadmap video: https://youtu.be/pacsngNYXI0
Thank you for this. I will update the post with this information.
https://support.apple.com/guide/security/memory-safe-iboot-i...
We won't get rid of C that easily, given the amount of systems that depend on it and won't be rewritten, which is exactly why besides Apple, also Google, Oracle, ARM, Microsoft are leading efforts to turn modern computers into C machines, with hardware memory tagging to fix at hardware level what WG14 won't fix.
Can you give me a link to the Reddit thread?
I had added several links to the post regarding replies to what I said about Zig.
I have also clarified a few arguments.
And because there seems to be some disbelief at my claim of absolutely not bugs in my bc, I am going to throw down the gauntlet like I did in https://news.ycombinator.com/item?id=26293920.
I encourage everyone who thinks I am wrong to _prove_ me wrong. Find a memory safety bug in my bc.
Should be easy since C is so unsafe, right?
If this famous device is that outstanding, one wonders at what point some version of that funtionality arrives for C or C++.
If something as core as type checking can be an optional feature, I'd be surprised if a heftier brain than mine can't get most of the way to a C++ borrow checker optionally.
Doesn't C++ famously fetish complexity? Wasn't pi once calculated at compile-timel with a C++ template? Where is my Obfuscated C entry that looks like an ASCII Robotron game and borrow-checks, say, the Linux kernel?
Microsoft and Google have already been collaborating in lifetime analysis on Clang Tidy and VC++ static analyser, it just isn't 100% there.
CppCon 2019: Gábor Horváth, Matthias Gehre “Lifetime analysis for everyone”"
https://www.youtube.com/watch?v=d67kfSnhbpA
Lifetime Profile Update in Visual Studio 2019 Preview 2
https://devblogs.microsoft.com/cppblog/lifetime-profile-upda...
GCC 11 will also support a lightweight version of it for C, https://developers.redhat.com/blog/2021/01/28/static-analysi...
Rust freely declares itself to be inspired by Cyclone et al, but its capabilities are quite different from Cyclone's region analysis (and Carp actually came after Rust).
The C++ static analysis, on the other hand, is quite limited in comparison even to Cyclone. It's not sound and doesn't even aim to be- in other words, "just" another static analysis that will not catch everything. ("Just" in quotes because of course more of this is great- my point is merely that it's not the same functionality coming to C++.)
> My understanding is that Rust's chief innovation is the borrow checker.
Carp was a mistake, I wanted to refer to Linear Lisp.
Also in the context of worse is better, C and C++ solutions just need to be good enough.
Learn this and advocate properly.
C and C++ have had static analyzers to catch "some version" of these problems for a long time now, so presumably anyone asking about borrow checker functionality would be interested in whether that functionality matches Rust's (i.e. is sound).
We should not forget that even if those static analysers aren't sound, they allow to keep using 50 years of eco-system.
Which is why companies like Microsoft, despite all security talk, in the end add support for recent ISO C versions, and have "secure" platforms like Azure Sphere with a C only SDK.
> ("Just" in quotes because of course more of this is great- my point is merely that it's not the same functionality coming to C++.)
Also bc might not be quite the yardstick when it comes to software that needs to be secure.
What good is a mask in your pocket?!?
Mask mandates from governors are not, in fact, rules. Executive orders are not laws. See https://gavinhoward.com/2020/10/executive-agencies-cannot-ma... .
If a business decides to enforce their rule, well, then we both know that it would be best that I do as little business with them as possible.
First of all, if you're really arguing that masks affect mental health more than they save lives (https://gavinhoward.com/2020/08/in-science-all-factors-matte...), I don't even know what to say. I'd really want to see the science behind this, but I suspect there isn't any real science. Common sense and knowledge of professions where people use a mask for long periods of time should be enough to debunk this.
Also, this is truly abhorrent:
> Of course, 161,392 people have died. (Oh whoops! It turns out that only 6% of those people died from COVID-19 alone, so it’s really 9,700 deaths)
If my car breaks don't work, I ostensibly die because I'll be crushed when my car falls of a cliff, but the real cause of my death is the fact that the car breaks didn't work.
For the other article, gee, I wonder if the folks behind it have an agenda to push: "Townhall: <<Conservative>> News, Cartoons, Top Stories".
Anyway, do realize that this is a global phenomenon, people aren't out to get your "freedoms" and countries which are far freer than the US have realized that Covid is a real pandemic and treat it using real science, not pseudo-sience peddled by crackpots or even worse, people with a hidden agenda (usually one about making $$$).
I know I won't change your mind, but please break out of your bubble. Find international sources, use Google Translate to see what they say, compare, contrast, think critically. Also, read up on your history and check out what they did to fight the 1919 flu, for example. Or SARS. Or what they're doing all over East Asia, mostly successfully.
Oh, by the way, your argument makes you look even worse than you think it does. It's all about ME ME ME! "There's a tiny chance that masks hurt me" and "there's a tiny chance that masks don't help others as much as people say", so basically, "f** everyone else in that case, I don't want to be inconvenienced".
> Who knows? The point is that we don't know all of the ways that masks affect us.
I don't know all the ways that the rice I ate yesterday affects me. I'm not going to stop eating rice because of this.
Your argument is completely null.
When there's no clear proof of something having a strong negative effect, the rational thing is to assume it doesn't have a strong negative effect.
When something clearly has a strong positive effect, the rational thing is to assume it has a strong positive effect.
And when we decide to do something, we balance positives with negatives. There is nothing in this world that only has positive aspects (the opposite is also true, nothing truly has only negative aspects). We never do something because it's "perfect", we do things that are "good" (more positives than negatives). We live because of water and oxygen but water can drown us and oxygen can burn us.
Your logic is: "a lot of very respectable people (as well as common sense) say that this thing has a positive effect, but I don't know if it has any negative effect, so I just won't do it at all".
That's no logic, it sounds more like spite.
I don't say this lightly, even on the internet, but you act like a horrible person. Please reflect on your behavior and for your sake, I hope you change.
Anyway, goodbye!
Oh, and by the way, there's arsenic in rice. https://www.fda.gov/food/cfsan-risk-safety-assessments/arsen...
The Internet doesn't have a shortage of rants. If you're wrong about other areas then why should I care about your opinions on technology?
That doesn't consider the opportunity cost; time that I spend on this argument can't be spent on another better argument.
There are more arguments then I could read in a lifetime so I focus my attention on people who are otherwise sensible.
Participation in a discussion usually implies an interest and a willingness to spend your time considering various arguments. If you only limit your exposure to arguments made by people who agree with you in other domains then I have to conclude your interest in this space is not very high.
My only posts in this thread have been to explain why I flagged the post and why I feel it's valid to dismiss the author based on his other views.
The author's position on masks is that he's too precious to comply with local laws, that businesses complying with said laws should be boycotted, and that executive orders aren't actually laws so he isn't bound by them. The first two beliefs are merely antisocial; it's the last claim that causes me to place him in the crank category.
> If you only limit your exposure to arguments made by people who agree with you in other domains then I have to assume your interest in this space is not very high.
My political beliefs are sufficiently bizarre that at best few people agree with them; if anything, he and I probably have some beliefs in common.
For masks, see https://gavinhoward.com/2020/08/masks-and-carbon-dioxide/ and https://gavinhoward.com/2020/08/in-science-all-factors-matte... . In essence, those who claim that masks work might be right, but they also ignore other factors that, if considered, might show that masks are worse for us overall.
On religion and LGBTQ issues: > A strong, free nation can only be made up of religious and virtuous individuals, strong nuclear families with a cisgender father and a cisgender mother, and a lively and effective civil society, all protected under the wise framework of the Constitution as it was intended by our Founding Fathers. > To have a virtuous people, America must return to its religious roots. > Strong, nuclear families consisting of a cisgender father and a cisgender mother are the “fundamental units of society." All governments under the Constitution should protect and encourage them and discourage all other kinds of families made through voluntary actions.
On the right to vote and welfare: > they who have actually paid for the services of government, and thus, should have a say in how it runs. Those who haven’t, and get themselves addicted to welfare, should not, for they do not pay the price of living in society. > In addition, all government welfare is waste.
You can look at the sidebar for more fun tags, to see his opinions about Black Lives Matter (evil), "censorship" (Facebook and Squarespace taking down his favorite conspiracy pages), and many tags about his Mormon faith, which as an atheist, is probably not my place to criticize.
At most you got to use dialects like Small-C and BDS C on other platforms.
To be fair most engineers (including many brilliant ones) fail at grasping the intuition of providing simple but not 100% adequate solutions. The difficulty of the last 20% will drive most potential users/implementers away, and reduces the virality.
That does not mean progress is not possible, just that it’s not necessarily viral.
If the zig and rust creators understand that then they should stop measuring their success as a percentage of the size of their user base to the size of C’s user base because their goals are arguably counter to having a user base as large as C’s.
Please provide a source for these alleged success criteria.
It seems many who favor C over Rust don't actually believe in "worse is better". A language must be equal or better than C in all possible aspects before it can be greeted with reluctant distrust instead of hostility. "Worse is better" can be used to defend C, but never a new language.
Even if rust lacks a formal spec and ports to multiple platforms, it is unarguably more complex than C and is an example of “MIT” engineering. Both Rust and Zig pursue the “right thing” whereas C pursued the simplest workable thing, thus increasing its virality.
Apple and Microsoft on top of that, have their safe C dialects.
Red-Hat, Google and Microsoft are adding lifetime analysers to their C and C++ compilers.
I think they understand why C is ubiquitous, and why something has to be done to fix it.
Their complexity will limit their success in the long tail of use cases where C is well established and “good enough.”