16 ms·
I could care less about integer division and minor details of syntax, but that's not going to stop me from being grumpy about C's continuing popularity. Every
by ekidd 10y ago
I could care less about integer division and minor details of syntax, but that's not going to stop me from being grumpy about C's continuing popularity.
Every C program I have ever worked on has been riddled with integer overflows, undefined behavior, buffer overflows and bugs. This was perfectly acceptable for a Vax or a Sun workstation in the 80s, and at forgivable in the mid 90s when plenty of developers still only had 8 MB of RAM and wasted half of that on Netscape Navigator.
But we live in an age of Pwn2Own and ClusterFuzz, where even the tiniest of bugs can be used as step 4 in a 6-step exploit, and where C compilers reserve the right to completely and silently break your program at the faintest whiff of undefined behavior.
I know my limitations: I'm not smart enough to write C code that deals with hostile data off the network. Neither are the authors of 99% of the C code that I've seen, with the possible exceptions of djb and a few OpenBSD contributors. It's long past time to invent and use better systems languages. Choose what you want, but choose something safer.
- Annatar 10y agoThat's an easily correctable problem: learn the living daylights out of programming in assembler, and then C will be like a walk in the park: no more overflows, no more pointer screwups, no more forgetting to free the memory, because you'll know exactly what will happen in the chip and the memory when that code compiles. You'll even start writing code which relies on integer overflow (rollover from #$ff to #$00 again) because, depending on the situation, it will give you a performance boost, or make the algorithm implementation simpler, or both, and you'll know it. It's long past time to invent and use better systems languages. I can't comment on Go, but the textbook examples of Rust and even treatises on the subject from recognized experts in the computer science field (Adam Leventhal) show it to be an utterly overcomplicated language for which there should be a criminal trial and a prison sentence of several decades. Immutables, borrowing, no, I have to stop; my head hurts already, and I'm getting a migraine thinking about solving even the simplest of classic input-output problems with such an overly complicated language. (And my head wants to explode when I compare Rust with AWK for solving input/output problems, the biggest reason why computers were invented.) So... C, C, and more C, because it's infinitely flexible and simple. I like simple, because simple is smart. Complicated and complex isn't. Let's all please be humane to one another and stop inventing more languages. We need less languages, not a bazillion variations on the one central task: making the computer do something. And for that, we already have all the languages we could ever want or need, and for the theoretical case where we don't, there is always the almighty assembler, in which exist no limitations as to what one can program with it.
- pka 10y agoAt first I thought that was sarcasm... but it's unfortunately not. > no more overflows, no more pointer screwups, no more forgetting to free the memory, because you'll know exactly what will happen in the chip and the memory when that code compiles To whoever wrote this: are you ready to share the code of a sufficiently complex program in C (or assembler, why not) you wrote and pay $100 for every "pointer screwup", buffer overflow, memory leak and generally every bug people find, which could have been prevented by a strong type system or borrow checking and other such complicated features?
- pjmlp 10y ago$1 would be enough, you could still get rich.
- ekidd 10y agoThat's an easily correctable problem: learn the living daylights out of programming in assembler, and then C will be like a walk in the park: no more overflows, no more pointer screwups, no more forgetting to free the memory, because you'll know exactly what will happen in the chip and the memory when that code compiles. Knowing how processors work doesn't prevent people from making mistakes. I knew assembly long before I knew C, because I grew up on computers that were too small to run a C compiler. I've contributed to a half-dozen compilers. I've written disassemblers for weird embedded DSP chips. And by the standards of C programmers, I'm pretty paranoid. None of this makes me superhuman. I make mistakes. I've written network-facing C code, and I've left people exposed to security holes. Want to see the carnage? https://people.canonical.com/~ubuntu-security/cve/pkg/xmlrpc-c.html https://people.canonical.com/~ubuntu-security/cve/pkg/xmlrpc... That's 6 CVEs against an obscure C networking library that I wrote. Technically, none of them were found in my code (not yet). All were in the third-party XML parser that I chose to use. But that doesn't absolve me of fault, and I bet there's a few more bugs lurking in my code that could be found with modern fuzzers. I don't care whether people use Go or Swift or D or Rust or some brand new language. But wherever C goes, bugs and security holes almost inevitably follow. It's going to take decades to reduce the proportion of C in our systems, and we ought to start now.
- zzzcpan 10y agoAgreed. Syntax is not a problem, we bash C mostly for security reasons. And we can stop that as soon as popular C compilers start taking measures to make C code by default as secure as in many other programming languages.
- glider97 10y agoI've dabbled in C, but I'm no expert. Can you explain how compilers can affect the security of C?
- zzzcpan 10y agoLike this: http://www.cs.rutgers.edu/~santosh.nagarakatte/softbound/ http://www.cs.rutgers.edu/~santosh.nagarakatte/softbound/ http://sva.cs.illinois.edu/index.html http://sva.cs.illinois.edu/index.html
- orclev 10y agoUnfortunately those two are linked together. C compilers produce insecure C code because the semantics of the C language limit the options that the C compiler has for generating secure code. You could make a C compiler that generated more secure code, but doing so would make it non-compatible with the C standard and would most likely break a large swath of programs that compile and run on the other non-secure compilers. Worse still it would still generate insecure code even if less of it because things like address aliasing, and being able to cast ints to pointers are fundamentally insecure. For an idea of what it would take to make C actually secure (and even then only in so much as you reasonably can) take a look at all the things Rust has had to do. Nearly everything that exists in Rust is there because they started with a C feature and asked themselves "what do we need to change to make this safe/secure?". Most other languages as a minimal first step towards improving security remove direct access to pointers, they're simply too powerful to do securely in the manner C does. Rust has (mostly) secure pointers, but only after putting an insane amount of work into bolting a massively complicated ownership and lifetime tracking system on top of it, and even then it's still not perfectly secure since they had to include unsafe blocks to provide a trap door for certain edge cases (also for C interop). So yes, you could make a secure C compiler, it just wouldn't compile C code anymore, it would compile some "safe" subset of C which would probably end up looking like either Rust or C# (or maybe ObjectiveC).
- pjmlp 10y ago> It's long past time to invent and use better systems languages. The sad part is that they already existed since 1961 actually, long before C was born, but then some startups decided to base their workstation OSes on UNIX and got successful selling them.
- gnipgnip 10y agoAlan Kay in his famous OOPSLA talk mentions how the architecture itself leads to these language choices. https://www.youtube.com/watch?v=oKg1hTOQXoY https://www.youtube.com/watch?v=oKg1hTOQXoY He mentions how Xerox PARC machines with tagged architectures from the 80s were only 1/50 the speed of the x86 systems in '97. This, in contrast to the 50000x increase in computing power over the same time frame.
- adamnemecek 10y agoCan anyone recommend any resources on older architectures? Alan also talks about the Burroughs CPUs but idk how one would go about learning about those these days.
- nickpsecurity 10y agoIm at work but these two should be a nice start: https://www.smecc.org/The%20Architecture%20%20of%20the%20Burroughs%20B-5000.htm https://www.smecc.org/The%20Architecture%20%20of%20the%20Bur... http://homes.cs.washington.edu/~levy/capabook/ http://homes.cs.washington.edu/~levy/capabook/ Bitsavers and Wikipedia are good resources. The summaries of most on Wikipedia are accurate enough with references to get more authorative information on. I found a lot of it that way.
- pif 10y ago> C compilers reserve the right to completely and silently break your program at the faintest whiff of undefined behavior <rant> Please, stop pushing this wrong rethoric forward! As soon as there is undefined behavior, it's a bug in the code. There is a problem, and the problem is on the developer's side. I appreciate the effort of compilers to help me get the most performant machine code I can, and I've had enough of people asking them to stop being smart in order to accomodate crappy code. </rant>
- wvenable 10y ago> As soon as there is undefined behavior, it's a bug in the code. I think the emphasis on the original comment should be on the silent part. Nobody is arguing that these aren't bugs in the code; the problem is that you get no help from the compiler or runtime to find them and the damage is more severe than it would be if it simply crashed.
- pif 10y ago> the damage is more severe than it would be if it simply crashed. I think I see your point, but you are wrong when you write "simply". Crashing in case of UB is not simple! Actually, ensuring any type of behavior in case of UB is not simple! It requires huge lots of runtime checks, thus you obtain a ridden executable as output. If you want your program to be cuddled in a safe baby box (which is the right thing to want in several cases), then go for an interpreted language, but please let "gcc -O3 -march=..." be what it is: a masterwork coated with magic.
- wvenable 10y agoIn the vast majority of cases, concept of Undefined Behavior shouldn't even exist. All behavior should be defined. We have massively powerful machines and the performance advantage mostly doesn't outweigh the potential damage. And other languages, like Rust, even eliminate lot of UB without a lot of overhead. There are exceptions to every rule, of course, but we need to re-evaluate our priorities as times change.
- 10y ago
- ksk 10y agoYet people continue to introduce security vulnerabilities in high level languages all the time. Maybe its not a problem of the language, but of the people?
- steveklabnik 10y agoDifferent kinds of security vulnerabilities have different levels of severity. The ones in HLL tend to be not nearly as bad as the ones that come out of C codebases.
- ksk 10y agoYes, to your first point. To the second, I'd argue the impact is the not that much different in most cases. Barring horribly mis-configured systems, networked C/C++ applications execute at the local user level so even if you get an exploit going you're SOL unless you have a local privilege escalation vulnerability in the underlying OS. For a web app, most of them are connected to databases and exploiting a vulnerability there usually allows you to either dump user data, or corrupt memory and execute shell code (leaving you with the same situation as the C code). Usual disclaimers apply - these are oversimplifications for casual conversation purposes yada yada.
- ArkyBeagle 10y ago"... I'm not smart enough to write C code that deals with hostile data off the network." I just don't believe you for one minute. It's quite easy to guard against unwanted memory access over serial ports and sockets. You have to know the size of the buffer, but that's just not hard. If you go throwing pointers-as-if-they-were-tokens/handles around and blindly following them, you'll get in trouble. So don't do that. If you constrain operation only to valid data ( which isn't all that difficult ) then ( and I ask out of ignorance ), how can they hurt you? What do I mean by "constrain operation..." yadda yadda? I mean if somebody "misspells" something, you dump the input. Your recognizer accepts only valid tokens. Usually, the tokens are in a table, with an FSM knitting them together. So the table can be wrong, or the FSM can be wrong. That's it. Recently, all commands were in a simple subset of XML ( by the customer's choice ). That was particularly easy. I grew up in environmentally hostile environments where you'd lose things like PHY chips and serial port drivers, so this was how it was done. If you mean exploits in the O/S itself, then yeah - I agree. But then my choice of language is irrelevant. I won't disagree about the C compiler thing, but that shouldn't be at issue here.
- steveklabnik 10y ago> I just don't believe you for one minute. The author demonstrated this by pointing to a list of CVEs caused by their code, so.
- ArkyBeagle 10y agoI understand that completely. "Doing it wrong" is simply a choice that has been made.
- MaulingMonkey 10y agoTo err is human. Beyond the scope of simple, small, toy programs - "doing it wrong" is not a choice, it is a statistic. You do have choices to make in terms of techniques and tools you can apply (assuming you're aware of them) to modify the statistics, but you will not be perfect in your application of them, and the tools were not written by perfect people either. There's another choice here - how high you set the security bar for "deals with hostile data off the network". Ekidd chose to set this bar high enough to rule out C. How high do you set it?
- sytelus 10y agoProblem is that we haven't been able to come up with a good alternative. Go is limited by its curse of minimalism [1] while Rust is verbose and rigid [2]. One of the reasons C became popular was that it was designed to solve real problems, not an exercise in minimalism or academic beauty. Its authors frequently sacrificed beauty and minimalism if it made sense and real world use demanded it. Unlike Rust or Go or NimRod, C is not just strongly opinionated statements on language design. One of the side effect is also that new languages often come with sub-par libraries and language designers expect others/community to figure everything else out. [1] https://www.quora.com/What-reasons-are-there-to-not-use-Go-programming-language?redirected_qid=1787465 https://www.quora.com/What-reasons-are-there-to-not-use-Go-p... [2] https://plus.google.com/+nialldouglas/posts/AXFJRSM8u2t https://plus.google.com/+nialldouglas/posts/AXFJRSM8u2t
- nickpsecurity 10y agoFree Pascal, Component Pascal, and esp Modula-3. Id get rid of capital identifiers. Make syntax more C-like. Modula-3 esp was nearly ideal set of tradeoffs for a safer alternative between C and C++ that also compiles fast like Go on weak hardware. We've had plenty of replacements waiting. C developers are just hyper committed to that language. Even though its inventors moved onto a Wirth-like language.