4 ms·
My view strongly aligns with John Regehr's [1] (emphases original): > My main idea is that we need to teach C in a way that helps students understand why a ver
by lifthrasiir 7y ago
My view strongly aligns with John Regehr's [1] (emphases original):
> My main idea is that we need to teach C in a way that helps students understand why a very large fraction of critical software infrastructure, including almost all operating systems and embedded systems, is written in C, while also acknowledging the disastrously central role that it has played in our ongoing computer security nightmare. [...]
> We’d like students to be able to answer the question: Is C an appropriate choice for solving this problem? [...] The second big thing each student should learn is: How can I avoid being burned by C’s numerous and severe shortcomings?
[1] https://blog.regehr.org/archives/1393 https://blog.regehr.org/archives/1393
- blub 7y ago"How can I avoid being burned by C’s numerous and severe shortcomings?" The only solution is using a program analyzer which can prove the absence of certain errors. Frama-C and Astrée come to mind. Normal static analyzers are best-effort, will have both false positives and false negatives and will also miss errors. This is the difference between testing and verification. Dynamic analyzers like ASan or valgrind depend on having good code coverage and good value domain coverage. The former should be obvious, the latter will ensure that error-prone code which fails only when variables have specific values is also flagged. E.g: adding two ints is defined for some value ranges, undefined behaviour for others. Now the main issue with all of the above is that virtually no self-respecting C programmer will use a verifier, so while theoretically possible to write safe C, it is practically almost unheard of - safety-critical domains aside. There is no good safe, user-friendly alternative to C, all of them are either much more complex languages (Rust, C++), or less performant (Swift, Go) or have tiny marketshare (D, obscure things like Zig, etc)
- skocznymroczny 7y agoD doesn't belong in this category. If anything, D should be put next to Rust, C++. D is a very complex language compared to C and it offers all the C++-like features like templates and OOP.
- keldaris 7y agoYou can use D's betterC mode, supported by the compilers. This avoids the D runtime entirely, there are no classes, exceptions, etc. You can still use templates and CTFE if you like (which can be awesome), but there's nothing forcing you to do that. You can just copypaste some C code, make a few syntactic changes to get it to compile and get a decent level of safety that way.
- pjmlp 7y agoJust yesterday I watched this ACCU talk about how many of those developers don't bother at all with static analysers or even basic unit tests. "C++ ecosystem: For better, for worse - Anastasia Kazakova" https://www.youtube.com/watch?v=43E5iYzrQn4 https://www.youtube.com/watch?v=43E5iYzrQn4 Although a C++ talk, she also touches C quite a few times, given the goal to get them to adopt C++ as safety improvement, and naturally how to tailor CLion to the markets they are on.
- 0815test 7y agoI find it hard to believe that you can seriously describe Rust as "much more complex" than C and recommend Frama-C in the very same comment! The point of all that "complexity" in Rust is precisely to enforce the use of patterns that will make a Frama-C-like analysis feasible and not overly complex, even for large codebases. This basically boils down to avoiding shared mutable access; not coincidentally, this is also what functional programming languages do! (That is, sequential mutability that's isolated to some part of the code can be modeled through constructs like the ST monad and is relatively benign; shared mutability is a whole other can of worms.)
- blub 7y agoI'm not recommending frama-C, I'm opining on what's necessary to write reliable C code. Much of Rust's complexity is not directly addressing memory safety, it's providing high-level language features. A C-with-borrow-checker would be very different from Rust.
- 0815test 7y ago"A C-with-borrow-checker" is a good-enough description of Cyclone, which is not that different from Rust and which was basically abandoned for Rust. Sure, Rust itself has a number of higher-level features, some of which are a bit problematic by comparison with C (e.g. monomorphizing generics lead to intermediate-code bloat, which causes long compile times) but it turns out that these features are practically needed, either to make programming-in-the-large more feasible or to abstract some underlying details from user-level Rust code so it can keep working even as the compiler and standard library evolve underneath it. C doesn't have these problems being a mature platform, but Rust still does.
- jonv 7y ago"How can I avoid being burned by C’s numerous and severe shortcomings?" I think this is where we start bumping up against the limitations of the universe we live in, because the question becomes "where do we put the bugs?". The biggest flaw with C is the array bounds checking, especially if that array is on the stack, or other bugs related to "raw" pointers: - We could enforce things through hardware, but then you've put the bugs in the microcode. - You can change your language, but then you've put the bugs in your compiler / interpreter / vm. - You can try and formally verify the correctness of your code, but it's less feasible for large codebases. And what if there's a bug in your proof? (proofs are programs) I'm not suggesting people use C/C++, but I wouldn't blame C for the problem of natural numbers.
- majewsky 7y ago> You can change your language, but then you've put the bugs in your compiler / interpreter / vm. Sure, but the number of bounds-checking bugs in, say, the Rust compiler/stdlib is multiple order of magnitudes lower than if all Rust applications had to roll their own bounds-checking code.
- jonv 7y agoYes, but I am in agreement with you. I was simply saying you shouldn't blame C for being what it is, not that you should use it.
- klingonopera 7y agoI'm not sure I quite follow you, because if I believe what I think you believe, then I wouldn't call it "the problem of natural numbers", but I agree that C has no fault in it. Precisely that which makes C so performant is also that which leads it to be "unsafe". It is thus up to the programmer to ensure safety in C, his manual managing of that is the price to pay for the performance gained using the language.
- jonv 7y agoI was simply saying that it's undecideable to do bounds checking at compile time, so it's better to use languages that do bounds checking at run time. But you shouldn't blame C for this.
- sureaboutthis 7y agoAnd yet almost all security problems on the internet involved PHP and JavaScript. When you read about people who have had problems with C, you will find that these are people who never really learned the language and the language is as simple as one can get which should also make one question their abilities.
- baybal2 7y agoSiding with you on that. People coming with "no bound checking/type safety/pointer safety/garbage collection in C" often don't get the simple idea they weren't supposed to be there to begin with, and in C the burden of doing in falls on the developer. There is nothing wrong with setting types manually, managing memory manually, and thinking through how pointers and array boundaries are computed. In fact this is what makes C unbeatable in its niche, and leads to software with very low resource and performance requirements.
- ernst_klim 7y ago>C the burden of doing in falls on the developer. Aka, C code is doomed to segfault. The routine easily verifiable work should be done by a machine, aka by the compiler.
- oblio 7y agoHalf the PHP security vulnerabilities are of the "someone chmoded 777 the Wordpress plugins directory". The other half are C vulnerabilities leaking through the interpreter. And the third half :-) are SQL injections and generic web vulnerabilities. The first batch would happen in any language, it's an operational issue. The second batch comes from C and would likely be prevented by PHP being written in idiomatic Rust. The third batch is a higher level development issue that is cross-language. I think there's value in removing classes vulnerabilities. And blaming the operator is NEVER a good idea. It was the exact opposite of this mentality that made us have safe cars and airplanes today. Before the 70's, the auto industry was doing exactly what you're doing. Once they stopped doing that, people stopped dying for easily preventable issues.