Live data from Hacker News

How memory safety CVEs differ between Rust and C/C++

kobzol.github.io

261–270 of 270 posts

Re: How memory safety CVEs differ between Rust and C/C++

#261
post #207

Earlier quoted context omitted.

The check is removed only if you already dereference the pointer before doing the check. But then, you also get the trap before the check. So the compiler eliding the check is not making this worse - as long as the zero page is not mapped. In any case, you can also configure GCC to not do this, and you can also configure it to insert explicit null checks before dereferencing a pointer. So C can offer you security and…

No, it's also removed if you dereference it later on, that's why it is said, that UB has time traveling behaviour. This means, that the compiler can emit a program, that let's you access data without a security check, while the crash only comes later. Also the crash can be removed, because dereferencing it is UB anyway, so the compiler does not need to emit it.

The check can not be removed if it becomes before the access because in this case the program has no UB.

If there were UB, a compiler in C is not allowed to move (time-travel) UB before any observable behavior. This was never allowed by in C (int contrast to C++), but the wording was not clear, which we fixed in C23.

If there is no check, you are right that the access itself is UB and there is no requirement to trap in ISO C, but this is something compilers explicitly support. (and it might be required by POSIX, but I am not sure)

Re: How memory safety CVEs differ between Rust and C/C++

#262
post #248

Earlier quoted context omitted.

Still not picking on C++ here. I would claim that these concepts pretty much all exist in C++ too, but often implicitly so. You would solve them by "braining them", with good rules of thumb, patterns, tests and deep knowledge and skill. In fact, you _have_ to solve them this way. In Rust the compiler is going to have a problem with your code unless you are explicit about borrowing/ ownership, gcc won't care. Which is…

I'm a really big fan of Rust, but I have to challenge this, GP was clearly talking about the complexity of the language itself, and that one is high. Extra features and extra static checking add complexity. Extra complexity in the language can make simple programs harder, and they make complex programs easier to code and maintain, like you said. However, nobody will ever be able to make a Rust equivalent of TinyCC, t…

Unless you or him define what you mean by complexity, we are not going to be able to come to an agreement there. This line of reasoning, it seems to me, is making the case that C is more complex than Assembly because the former has a number of formalizing, let's say, concepts that are not in assembly.

I would on the contrary say that adding extra static checking deducts from the _actual_ complexity of the domain and its application.

Re: How memory safety CVEs differ between Rust and C/C++

#263
post #223
post #213

Earlier quoted context omitted.

My point is that there are plenty of smart people touting various recipes for safe C++, but somehow vanishingly few instances of actually safe C++ codebases. It's hard not to feel like the claims that C++ can be made safe are mostly being made from an abstract theoretical viewpoint and not a pragmatic one, because even the companies with the most resources or the smartest people don't seem to be able to pull it off.

Agreed, however I would vouch it is a matter of culture beyond anything else. Dennis Ritchie had this to say about C, > Although the first edition of K&R described most of the rules that brought C's type structure to its present form, many programs written in the older, more relaxed style persisted, and so did compilers that tolerated it. To encourage people to pay more attention to the official language rules, to de…

I think I agree with your points on tooling. As much as I'd prefer that new projects used Rust instead of C++, I don't have any illusions that C++ isn't going anywhere any time soon, and any sort of static checking that gets introduced for C++ codebases is an improvement compared to not using it. If anything, it seems even more necessary when there are things that the language will likely never be able to check (without breaking changes, which would be controversial to say the least).

Re: How memory safety CVEs differ between Rust and C/C++

#264
post #262

Earlier quoted context omitted.

I'm a really big fan of Rust, but I have to challenge this, GP was clearly talking about the complexity of the language itself, and that one is high. Extra features and extra static checking add complexity. Extra complexity in the language can make simple programs harder, and they make complex programs easier to code and maintain, like you said. However, nobody will ever be able to make a Rust equivalent of TinyCC, t…

Unless you or him define what you mean by complexity, we are not going to be able to come to an agreement there. This line of reasoning, it seems to me, is making the case that C is more complex than Assembly because the former has a number of formalizing, let's say, concepts that are not in assembly. I would on the contrary say that adding extra static checking deducts from the _actual_ complexity of the domain and…

By complexity I mean roughly the number of language rules / techniques / idioms a programmer has to understand and keep in their head to be able to program effectively. I would say this is far lower in C than in Rust. I do not see how the additional hoops Rust makes you jump through makes it easier to achieve a goal, but I see how it can help prevent certain errors (but not many others).

It also seems obvious that the problematic aspect of getting anything done in Rust is fully compensated by having a lot of libraries available quickly via Cargo, so people are essentially just assembling things at a high-level. And in principle, I think this is a very good thing, but in the way this is implemented it comes with severe supply chain risks.

Re: How memory safety CVEs differ between Rust and C/C++

#265
post #242

Earlier quoted context omitted.

In C/C++ the default behavior, always, is very dangerous UB. Some compilers offer an option for guaranteed wrap-around, and some compilers offer an option for controlled crash. None of them is standardized or the default. In Rust the standard mandates a guaranteed wrap-around or a controlled crash. The default behavior is crashing in debug mode and wrapping-around in release mode, but you can control that with a comp…

> > I don't know if Rust will ever attempt to fix this mistake > It was discussed many times, and the conclusion is: it is too expensive, and the default will only change if that will change (due to better optimizations and/or better hardware). It is not a mistake, but a conscious decision. There's also wrapping_add / saturating_add for anyone concerned about this. Ya want a specific behavior? Just tell the compiler!…

> There's also wrapping_add / saturating_add for anyone concerned about this. Ya want a specific behavior? Just tell the compiler!

That is exactly why Rust's behavior for +/- operators is a mistake and wrong. It should always panic and anyone that wants something different can specify that in code, where it's clear and explicit.

Re: How memory safety CVEs differ between Rust and C/C++

#266

Bjarne Stroustrup was recently interviewed by Ryan Peterman^1 1. https://youtu.be/U46fJ2bJ-co?t=2780 and Ryan asked Bjarne about memory safety. Bjarne brushes it off and says that in almost all cases where we see memory safety issues, they are either 1. Being written in C style C++ and not using "Modern C++" 2. Being written in C He then goes on to say say that Modern C++ and where it is necessary, hardened libraries…

> I haven't had those problems for years About twelve months ago, Bjarne wrote a paper named "21st Century C++" for WG21. In that paper Bjarne begins with a 10 line C++ listing which he says is equivalent to a fairly trivial awk program. It's a needlessly bad program which in fact has Undefined Behaviour, as I pointed out here (on HN) at the time. So when Bjarne says he hasn't had this problem, you can take that one…

He is 75 years old, so he might indeed have slowly become incompetent (or just inflexible and stubborn).

Re: How memory safety CVEs differ between Rust and C/C++

#267
post #218
post #145

Earlier quoted context omitted.

> In fact, the fact that the rust compiler adds runtime checks for array indexes if it can't prove the index is in bounds is a criticism some c programmers have of rust. And the fact that after a half a century we're still debating how much we really need to care about U stuff like this when we get severe bugs in a major piece of software written in C seemingly every week is a criticism that pretty much all Rust prog…

Considering the amount of C programs that exist, the "we see severe bugs in C code seemingly every week" is on the same level of propaganda as we see "crime in the news every week" when the real societal problems are entirely different.

The difference is that while we don't have a viable model for zero crime societies, we do have languages that don't suffer from nearly as many memory safety bugs

Re: How memory safety CVEs differ between Rust and C/C++

#268
post #264
post #262

Earlier quoted context omitted.

Unless you or him define what you mean by complexity, we are not going to be able to come to an agreement there. This line of reasoning, it seems to me, is making the case that C is more complex than Assembly because the former has a number of formalizing, let's say, concepts that are not in assembly. I would on the contrary say that adding extra static checking deducts from the _actual_ complexity of the domain and…

By complexity I mean roughly the number of language rules / techniques / idioms a programmer has to understand and keep in their head to be able to program effectively. I would say this is far lower in C than in Rust. I do not see how the additional hoops Rust makes you jump through makes it easier to achieve a goal, but I see how it can help prevent certain errors (but not many others). It also seems obvious that th…

I guess that depends on what goals you have in mind. If they are producing a correct program, then having the compiler verify your assumptions, forcing you do deal with domain complexity upfront is one way to do that. Tests( driven development) is another one.

But in this context I feel that partial solutions are offered as alternatives to more complete ones. I.e.: if holes in your trousers is of no concern, then having tools to avoid that is of no value.

Not picking on C here, as already mentioned, it is a wonderful language.

Re: How memory safety CVEs differ between Rust and C/C++

#269
post #268
post #264

Earlier quoted context omitted.

By complexity I mean roughly the number of language rules / techniques / idioms a programmer has to understand and keep in their head to be able to program effectively. I would say this is far lower in C than in Rust. I do not see how the additional hoops Rust makes you jump through makes it easier to achieve a goal, but I see how it can help prevent certain errors (but not many others). It also seems obvious that th…

I guess that depends on what goals you have in mind. If they are producing a correct program, then having the compiler verify your assumptions, forcing you do deal with domain complexity upfront is one way to do that. Tests( driven development) is another one. But in this context I feel that partial solutions are offered as alternatives to more complete ones. I.e.: if holes in your trousers is of no concern, then hav…

In my experience is it also possible to avoid most holes in the trousers easily with C as well and not just by testing. For example, it is also often possible to build safe abstractions by designing an API around an incomplete type etc.

Re: How memory safety CVEs differ between Rust and C/C++

#270
post #269
post #268

Earlier quoted context omitted.

I guess that depends on what goals you have in mind. If they are producing a correct program, then having the compiler verify your assumptions, forcing you do deal with domain complexity upfront is one way to do that. Tests( driven development) is another one. But in this context I feel that partial solutions are offered as alternatives to more complete ones. I.e.: if holes in your trousers is of no concern, then hav…

In my experience is it also possible to avoid most holes in the trousers easily with C as well and not just by testing. For example, it is also often possible to build safe abstractions by designing an API around an incomplete type etc.

C is turing complete so of course. You can do anything with C but that is not the issue we are discussing here.
Post reply on HN