6 ms·
I don't buy that at all though. Logic bugs are far more common, you will still have to carefully review each line and section. C++ isn't inherently unsafe eith
by qbasic_forever 4y ago
I don't buy that at all though. Logic bugs are far more common, you will still have to carefully review each line and section. C++ isn't inherently unsafe either, you can use it with zero dynamic allocation if you really want or use language tools like ref counted smart pointers. Ultimately you can write unsafe and bad rust code too so reviewers will still have to carefully review every submission.
- foota 4y agoThis is true, but anyone can catch a logic bug, whereas seeing undefined behavior can take someone familiar with it.
- qbasic_forever 4y agoLinters will easily catch undefined behavior, better than humans in my experience.
- steveklabnik 4y agoThis is in fact a large part of why people are so pro Rust. Think of the compiler as a very strict linter, one so strict it can catch things that just aren’t semantically possible in many other languages, including C++.
- jjnoakes 4y agoSome linters catch some undefined behavior, but not all undefined behavior (I'm guessing not even most undefined behavior). And no one runs linters. If they did, a ton of CVEs would just vanish. But they haven't.
- mamcx 4y ago> Linters will easily catch undefined behavior, better than humans in my experience. Now imagine if the linter is not optional. Oh, yeah, that is Rust!
- Ar-Curunir 4y agoThat’s exactly what the Rust compiler is: a fully sound^* linter for lifetimes * up to implementation bugs in the compiler
- adgjlsfhk1 4y agono they don't. every use of + in C++ is potentially undefined behavior.
- timschmidt 4y agohttps://arxiv.org/abs/2003.03296 https://arxiv.org/abs/2003.03296 "Rust is an emerging programing language that aims at preventing memory-safety bugs without sacrificing much efficiency. The claimed property is very attractive to developers, and many projects start using the language. However, can Rust achieve the memory-safety promise? This paper studies the question by surveying 186 real-world bug reports collected from several origins which contain all existing Rust CVEs (common vulnerability and exposures) of memory-safety issues by 2020-12-31. We manually analyze each bug and extract their culprit patterns. Our analysis result shows that Rust can keep its promise that all memory-safety bugs require unsafe code, and many memory-safety bugs in our dataset are mild soundness issues that only leave a possibility to write memory-safety bugs without unsafe code. Furthermore, we summarize three typical categories of memory-safety bugs, including automatic memory reclaim, unsound function, and unsound generic or trait. While automatic memory claim bugs are related to the side effect of Rust newly-adopted ownership-based resource management scheme, unsound function reveals the essential challenge of Rust development for avoiding unsound code, and unsound generic or trait intensifies the risk of introducing unsoundness. Based on these findings, we propose two promising directions towards improving the security of Rust development, including several best practices of using specific APIs and methods to detect particular bugs involving unsafe code. Our work intends to raise more discussions regarding the memory-safety issues of Rust and facilitate the maturity of the language."
- mustache_kimono 4y ago> I don't buy that at all though. Logic bugs are far more common, you will still have to carefully review each line and section. I think the parent's point is that it's less likely a bug will be "lurking". You may disagree with that point too, but I tend to agree that it's more likely a memory safety issue is "lurking" than a logic bug is.
- qbasic_forever 4y agoIt doesn't change the point I'm making that just because something is written in Rust means it will require less strictness of code review. There might be a class of bugs that are more difficult to hit in rust but that's just one of many bug types. You can still write terribly buggy code in rust. Assuming less strict review is necessary would be overall worse for the project and likely let _more_ bugs in.
- mustache_kimono 4y ago> Assuming less strict review is necessary would be overall worse for the project. Maybe? It might make it easier for those less experienced with C/C++ memory safety issues to review? Instead of thinking of it as being less strict, I might think of it as -- freeing the reviewer up to focus on other issues.
- Ar-Curunir 4y agoIt means that you can focus your attention on catching logic bugs, instead of dividing attention between memory safety and logic bugs. That is surely a win, no?
- wtetzner 4y agoI think it will make the code reviews potentially more interesting, as it removes a class of things that needed to be dealt with before.
- tialaramex 4y agoLet's make it a bit more concrete with an actual example of submitted code. Here's a recent patch I wrote "Improve E0308: suggest user meant to use byte literal, w/ tests and fix" which adds a suggestion for Rust's diagnostic when you write for example '*' the literal char, Unicode U+002A but it needed a single byte and that's not what a char is. My code suggests adding the prefix b, so writing b'*' here, meaning the ASCII code for that symbol 0x2A which is a single byte :: https://github.com/tialaramex/rust/commit/130d02b62e65c5f2a434eaec63c4249e9d508487 https://github.com/tialaramex/rust/commit/130d02b62e65c5f2a4... I wrote that code but I don't understand the internals of how self.tcx.sess().source_map().span_to_snippet(span) works. Not my problem, we're in the diagnostics code so even if this is perhaps slightly slower than optimal it doesn't matter because a human will need to read this output and act on it - E0308 is a type mismatch, the program does not compile as written. Does my reviewer know? Maybe, I didn't ask them, but they don't really need to, it's clearly fine here to call this stuff, there won't be a nasty surprise "Oh, make sure you restore the FQ5 when setting Z due to calling sess() in this code" because that's not how Rust works whereas in a language like C++ of course such traps may exist. Now there is some risk I made a logic mistake, but, I wrote tests for this of course, unlike with subtle memory safety bugs, logic bugs are often caught by proper testing. My tests here are somewhat superficial, I check 'X' and '#' which should both cause the suggestion, and I check '€' which should not, but I think they cover the cases the compiler will really see here.
- 0x6c6f6c 4y agoRust is designed to remove the entire class of memory safety bugs, yet this comment seems to be a collection of hand wavey disregard for the stark differences in language design.
- qbasic_forever 4y agoThose are just one type of bug. There are plenty of other bugs you can create in rust code and reviewers can't just assume because it's written in rust the code needs less scrutiny.
- ben-schaaf 4y agoA whole class of bugs doesn't have to be looked for. How does that not mean it requires less scrutiny?
- mlindner 4y agoIn my experience those one type of bug are also the hardest bugs to find and fix, even when you know it's sometimes happening. The system can get sufficiently complex such that it's near impossible to find the bug unless you get lucky. And often when you find the bug it can result in an apparently architectural contradiction and it becomes very non-obvious how to fix it as there are two architectural decisions that happen to be at odds with each other rather than a simple mistake.
- twp 4y agoHow many memory safety bugs have you encountered? How many many of these were ownership problems that could only be solved with a strict borrow checker and could not be solved with a garbage collector?
- Cyph0n 4y agoThink of it this way: every time the borrow checker throws a fit, it very likely saved you from a memory safety bug. Now, whether or not you would have made the same mistake in C or C++ is a different issue. GC is unacceptable for some applications. Generally speaking, shifting the memory safety checks to compile time results in better runtime performance. Is the added complexity worth the performance gain? That’s for you to decide.
- steveklabnik 4y agoCode with zero dynamic allocations can still be memory unsafe. Ref-counted pointers in C++ are not inherently memory safe either. If you do run into memory unsafety in rust, you already have signposts pointing towards possible problems. You get very little help in comparison in C++.
- queuebert 4y agoExactly... int oops[10]; oops[69] = 420;
- waterhouse 4y agoThat seems blatant enough that a compiler should catch it, even a C compiler. Clang in fact does so: idiot.c:4:3: warning: array index 69 is past the end of the array (which contains 10 elements) [-Warray-bounds] oops[69] = 420; ^ ~~ idiot.c:3:3: note: array 'oops' declared here int oops[10]; ^ But... if 69 is replaced with a user-supplied argument, then that bypasses the detection. int idx = atoi(argv[1]); int oops[10]; oops[idx] = 420;
- tialaramex 4y agoIf you write a literal illegal index in Rust the compiler will attempt to evaluate it as constant, conclude it's impossible and reject the program (whereas note that Clang only emits a warning for this scenario even though it's clearly bogus) And so the runtime Panic will occur in Rust only for the dynamic case. Notice that in WUFFS the user argument code is still a compile time error. WUFFS wants to know why you thought it would be OK to put arbitrary numbers in idx, a variable you are using to index into an array of size 10, and thus which should only have values between 0 and 9 inclusive. It won't be happy until you write logic to ensure this can't happen.
- oconnor663 4y agoOr: int x = 0x7fffffff; x++; Or: std::array<uint32_t, 2> x = {1, 2}; uint64_t *y = (uint64_t *)&x; *y; Or: std::optional<int> x; *x; Or: std::variant<std::string_view, int> x; x = "foo"; auto &y = std::get<std::string_view>(x); x = 42; std::cout << y;
- lmm 4y ago> Logic bugs are far more common AIUI memory safety issues are literally over half of security issues. (Also, Rust's type system makes it much easier to avoid logic bugs). > C++ isn't inherently unsafe either, you can use it with zero dynamic allocation if you really want or use language tools like ref counted smart pointers. No you can't. C++ fans always claim this is possible but they're never willing to point at specific rules for which code does or doesn't do this, or which libraries are out there that do or don't follow their rules. It's vaporware. > Ultimately you can write unsafe and bad rust code too so reviewers will still have to carefully review every submission. Given that existing review procedures aren't perfect, the acceptable defect rate is clearly not zero. So if switching to Rust eliminates half the bugs, people could do half as much review and the end defect rate would be the same; why would that not be acceptable?
- steveklabnik 4y ago70%, to be a bit more specific than “over half,” yep. That’s roughly the number that keeps coming up across various reports.
- enedil 4y agoA breakdown comparing the language that caused the errors would be helpful. I expect that codebases in C or C++03 or even (idk) C++14 have much higher rate of memory corruption derived vulnerabilities, than those written in C++20.
- steveklabnik 4y agoI agree in the abstract, but people like to argue about if a codebase is truly "Modern C++" or not, even when they use newer versions of C++, due to it largely being about patterns and the amount of them. So you'll have people nitpick this to death.
- pjmlp 4y agoExcept even in C++20 there will the clever dudes writting C strings/arrays, doing strcpy, memset, memcpy,... botching all best efforts for safety. Just go around open source projects from well known ISO C++ members.
- unrealhoang 4y agoLogic bugs are far more common, yes, but also much easier to spot barring subtle edge cases. Whereas with memory unsafety, the reviewer must load every function's conditions and invariants to their brain to emulate the borrow checker, at review time. Also the severity and cost of memory unsafe bug are far more higher: 70% exploit from memory unsafe, finding such bugs are also MUCH harder than finding logic bug.
- enedil 4y agoThis is not C anymore. When you write modern C++, it's much much more hard to introduce memory safety errors. And the logic hides in corner cases, so when you need to review logic, you're necessarily also reviewing memory correctness. I also don't agree with you on the part that logic is much easier than memory corruption - perhaps you haven't worked on systems complex enough? The 70% quote includes programs written in C, which I would argue, has a much higher of memory corruption errors.
- nicoburns 4y agoThe thing with logic is that some logic is simple and some logic is complex. With C or C++ you have to check the simple logic just as carefully as the complex logic because any line of code might introduce a memory vulnerability and UB which could effect your entire project. With Rust, a quick glance over the simple logic is probably enough and you can focus your review effort on the complex bits and the few unsafe blocks (if your project uses any).
- llanowarelves 4y agoI know this can be seen as the "now we have 15 competing standards" thing , but I want Google's Carbon to work out. Effectively a perfectly interopable (both ways) subset of C++ with some syntactic sugar and niceities. But yes I agree that best practices of modern C++ means most of the baggage and bad ways of doing things don't have to be done. Now just to enforce it via education and linters or something conventionally.
- mlindner 4y agoI hadn't heard of Carbon until very recently, and when I went to look at it, it doesn't seem to solve any of the real problems with C++. Their stance on memory safety appears very lukewarm. So I don't really see why Carbon is at all interesting other than it just being another form of their standard "Google being Google" with their extreme "Not Invented Here"-itis. It just sounds like a slightly warmed over version of C++ with different syntax and near identical semantics. Carbon at first blush appears to show that Google doesn't appear to understand the real problems with C++. I can't see why anyone other than Google would ever end up using the language, at least as currently described by Google in their goals for the language. In general for something to be rewritten it needs to cause very substantial advantages to justify the rewrite.
- tuckerman 4y ago(Disclaimer: was at Google/know some people working on Carbon but I had zero involvement myself) If you are in a position where you can wholesale rewrite your program (or are starting greenfield), Carbon is pretty clear upfront that you should use another language: "Existing modern languages already provide an excellent developer experience: Go, Swift, Kotlin, Rust, and many more. Developers that can use one of these existing languages should." Natively fitting into the C++ ecosystem at Google and in some other extremely large C++ codebases (e.g. being able to directly use templated C++ code, using the same build system, bidirectional interoperability) is what is being prioritized.
- mlindner 4y agoI see. I missed that point of advice they gave. However even for existing large C++ codebases, I feel you'd be better served by piecemeal writing code in something like Rust with FFI, if you're going to switch language at all. Carbon doesn't move you in a better long term direction. It appears only useful for delaying the inevitable, which doesn't seem to make much monetary sense.
- jjnoakes 4y agoReviewing code for logic bugs is less work than reviewing code for logic bugs and undefined behavior.
- nicoburns 4y agoLogic bugs are common, but they're much easier to check for (and the scope of consequences of missing something are usually smaller too).
- elihu 4y agoLogic bugs tend to affect the feature that the offending code is meant to support -- if the feature isn't working correctly, it's probably a logic bug in the implementation, so you can look there. Memory safety bugs, on the other hand, can have unpredictable results that are far away from the code that actually caused the problem. Usually it's possible to figure it out from clues like, "the program only crashes after I use this particular feature" but sometimes memory safety bugs can stick around for a long time without anyone figuring out why every once in a while the program crashes for unexplained reasons. If someone submits a pull request adding some feature to a big project, then the stakes of accidentally approving a bad change are (usually) a lot less if you're only concerned with logic bugs and they only affect that feature.