1. 75

  2. 19

    Lets also add the original, safe, system language to that list since it tries to cover all bases, has industrial-grade IDE’s, and many successful deployments.


    Then one that lets you straight up prove absence of many of these problems with automated provers. Been used to implement crypto algorithms and DNS among other things.


    1. 3

      In the interest of not having to rewrite everything all in one go, how possible is it to export a C API from a piece of Ada code, and to consume existing C APIs via an FFI?

      1. 3

        You can do it, but it gets a little weird. https://gcc.gnu.org/onlinedocs/gnat_ugn/Interfacing-to-C.html

    2. 15

      I won’t dispute the whole message, but speaking of disingenuous, it’s been zero days since a curl bug is up there. Apple is just lazy about patching. The fix has been available to other curl users for quite some time.


      1. 3

        Apple is just lazy about patching

        Apple’s really bad about this 10.11 stopped getting patches because 10.12 was in beta. There’s no roadmap and no defined lifecycles.

        it’d be safer to just run Windows instead.

        1. 10

          Apple released a security update for 10.11 (and 10.10) just yesterday.

          1. 2

            Actual security patches, or just iTunes updates? My friend switched to Windows on his MacBook because Apple left a critical security bug unpatched for a while. (I think it was actually with 10.10, and 10.11 was in beta.)

            They’re patching 10.11 now though - I think it’s because 10.12 dropped support for some machines.

            1. 4

              For some time now Apple’s policy has been to release patches for the current macOS release and security updates for the preceding two releases. See, for example, the security updates list.

              The most recent updates for macOS/OS X (released 27 March 2017):

              macOS Sierra 10.12.4, Security Update 2017-001 El Capitan, and Security Update 2017-001 Yosemite

              which support:

              macOS Sierra 10.12.3, OS X El Capitan v10.11.6, and OS X Yosemite v10.10.5

      2. 11

        May I propose D?

        • D shares a lot of syntax with C, so C programmers will feel nearly at home.
        • If you like Java, D also has “class” and “interface” and it works like in Java.
        • If you like C++, D has templates and many more features which feel like C++25.
        • No, D is not a simple language like C. Neither is Rust, Swift, etc. D wants to be “comprehensive”, i.e. provide the right tool for every job, not just a hammer.
        • D allows you to forbid unsafe operations like pointer arithmetic via the type system.
        • D checks array bounds by default.
        • D has a GCC backend, which means code generation for all the platforms GCC has. (Ok, gdc is behind the official frontend and you still have to port the runtime. This is not a very strong argument.)
        • D has a “-betterC” flag. If you want to know more, you probably need to wait for this talk or search through the forum. Unfortunately, nobody has written a nice blog article about this yet.
        1. 33

          I have meta-answer to that: I like D, even if I just had a glance at it. I hope it picks up more steam. One of the things that annoy me about the whole (made up) “Rust vs. C” is that this is really a “we need to go beyond C and need the find good ways”. Rust is an attempt. D is one. Swift is another (though definitely built to be the better Objective-C, which comes with it’s own baggage).

          The whole language space is still growing. We can have our share without killing off another. There’s place for more. Even 2% of the global development market is a sizable amount. Rust isn’t for everyone, just as D and Swift are. It’s great that there are options. And get the competition going, because there’s still a lot to fix. If Rust succeeds at still being a used language in 20 years, I’d call it mission accomplished. And I’d be happy if D, Swift or whatever comes up in the next years crosses the line along with it!

          1. 5

            The whole language space is still growing. We can have our share without killing off another. There’s place for more.

            This is the right attitude. I mean, syntax and legacy issues alone block so many adoptions. So many that are like this but not that. Then, there’s objective, measurable benefits of one over the other. Best to sow the seeds a bit wide to increase the odds that several grow into something great. I’m fine with exploration and diverse attempts so long as they’re each solving fundamental problems we know how to solve and need to. Somehow. I got preferences but don’t really care. Long as the tool lets user leap ahead it’s at least OK. :)

          2. 8

            Especially SafeD:


            1. 4

              Are you involved in D? What I find striking about this article it takes ages to talk about what SafeD is, but instead spends a lot of time with very fuzzy talk about what could be wrong with other things.

              If the feature is good, it needs no comparisons to drive the point home.

              1. 3

                Yeah, it sucks when articles do that. I’m not a D person. I was dropping it’s name in case Googling “SafeD” might lead them to interesting info.

                1. 3

                  The article is quite old.

                  A concise description of the @safe annotation is in the spec. That does not address memory safety, though. Hm, I fear dlang documentation is lacking here.

                  1. 2

                    Maybe Ill email them about it to see if they want to do an update with comparisons to Ada or Rust. At the explain SafeD’s features more clearly.

                    1. 2

                      Nah, not more comparisons. More explanations. People reading that are interested in D, not people weighting in on the difference between solution R, A and D.

                      1. 3

                        Alright. I found that the documentation on that was scattered around. I did find one that sums it up. It’s a keyword, safe, that disallows really low-level and unsafe constructs in a given function. Here’s one list I found of behavior safe functions can’t contain:


                        Like Rust, it’s also got a lot of features in it:


                        Too big for me to look through it all. Least we know what SafeD pertains to now, though.

          3. 3

            good article. one nit-pick:

            Memory safety will not prevent an attacker who has obtained your HMAC key from forging a malicious credential that, when deserialized, can call arbitrary Ruby methods (yes, this was a real vulnerability in older versions of Rails)

            HMAC keys are secrets, as MACs are symmetric signatures where the key is used to both sign and verify.

            and “I got your secret” => “I can execute code on your machine” is true for most server setups.

            1. 5

              Not all secrets are equivalent. Losing just the session HMAC key, it’s reasonable to expect an attacker would only be able to forge sessions, not be able to execute arbitrary code. (This was a bug in the deserializer, btw—the HMAC part is only a little bit relevant.)

              1. 4

                Care to make a list of the popular environments in which this is true, and why?

                1. 2

                  I don’t actually have the spreadsheet handy, but just about every web framework has had similar bugs where forged cookie results in deserialization hijinks or setting the admin flag and accessing some debug console or some other game over result. No?

                  More generally, people like to downplay file traversal vulns, but I kind of assume file traversal -> RCE is an easy escalation. Is that true(ish)?

                  1. 6

                    It’s truish. Like, candidly: if there was an HN thread where someone said “that’s no big deal it’s just file traversal” I’d play the “file traversal is usually RCE gameover” card, and if there was a thread where someone said “file traversal is always the end of the world” I’d play the “there are platforms where it isn’t” card.

                    1. 1

                      Heh, so the first draft of my comment was more like “I seem to recall you saying that losing the secret meant RCE”, but it wasn’t meant to be an accusation. Glad I didn’t misremember at least.

                  2. 1

                    SSH, GMail, Vanguard. It’s meant as a general statement — if you don’t keep your secrets secret, that’s a problem right there, not that giving away session tagging keys leads to RCE.

                    If cookie data is tagged, I think it’s reasonable to assume it might be executable (e.g. a Python pickle string), because you assume secrets stay secret and storing tagged pickle strings in cookies is a lot easier than serializing / deserializing objects more manually, and if secrets don’t stay secret, session tagging keys are probably not as high on your list of concerns as some API tokens.

                    1. 2

                      I think it’s worth observing that arbitrary-file-read is often worse than it looks, while also not accepting the legitimacy of designs where it is. We should work to avoid designs where file-read is RCE.

                2. 4

                  I find it super hard to disagree with these arguments (and all of the others that came before it), but simply can’t make peace with the idea that everyone should just abandon C in favor of languages like Rust, D, or even Go for that matter. These languages are far more complicated than C. Admittedly, the complication comes with enhanced expressivity, which can (but not always) be a win.

                  I’d much prefer the effort be spent on safer dialects of C, like say Cyclone, where there’s a chance that the trillions of lines of C can actually be made safe with fewer changes than via a complete rewrite. I’ll let someone more knowledgeable than me speak to the possibility of this.

                  1. 1

                    I’ve admittedly never used Cyclone, but it looks similar in complexity to Rust: one of Cyclone’s big additions is region analysis including explicit lifetimes, which look pretty close to Rust’s lifetimes. I imagine this would also make retrofitting C codebases into Cyclone difficult since a lot of code would need to be fixed to be verifiably lifetime-correct.

                    Also I’ll point out that the Cyclone front page mentions it’s unsupported, and points interested readers towards Rust.

                    1. 1

                      I have to take issue with the claim that C is simple.

                      Hundreds of undefined and implementation defined behaviors does not a simple language make.

                      One might say C is both primitive and complex. The worst of both worlds.

                      1. 1

                        claim that C is simple

                        I didn’t make that claim, for what it’s worth.

                    2. 1

                      I wonder how many memory safety issues arise from the aggressive optimization applied when undefined behavior is triggered?

                      1. 0

                        It is pretty much unfair, the small problem of memory safety is a little part of the argument of curl author. As far as I remember there is at least the C portability and the hight risk to introduce bug by rewriting it.

                        1. -2

                          Almost all of those are user input failures combined with basic design failures. If your bluetooth driver is a path to arbitrary kernel code execution, maybe C is not the problem.

                          To quote DJB

                          3.3 Avoiding parsing I have discovered that there are two types of command interfaces in the world of computing: good interfaces and user interfaces. The essence of user interfaces is parsing: converting an unstructured sequence of commands, in a format usually determined more by psychology than by solid engineering, into structured data. When another programmer wants to talk to a user interface, he has to quote: convert his structured data into an unstructured sequence of commands that the parser will, he hopes, convert back into the original structured data. This situation is a recipe for disaster. The parser often has bugs: it fails to handle some inputs according to the documented interface. The quoter often has bugs: it produces outputs that do not have the right meaning. Only on rare joyous occasions does it happen that the parser and the quoter both misinterpret the interface in the same way.

                          1. 9

                            Unless the code literally calls eval, it shouldn’t result in arbitrary code execution. Even if its a “basic design failure”

                            1. 6

                              Well, it shouldn’t, but if you’re working in C, it’s one common result of memory management failures. Once somebody can overrun a buffer, they’ve got some good odds on triggering code execution.

                              1. 5

                                I’m not sure what you’re getting at here–I’m well aware that one of the risks of writing C is encountering undefined behavior. The person I was responding to was saying C isn’t at fault for code execution bugs, the programmer is. My position is the opposite.

                                1. 4

                                  You claimed that “Unless the code literally calls eval, it shouldn’t result in arbitrary code execution.”

                                  This is technically true. But the whole issue here is that memory management is hard, and missing a single bounds check on an edge case now permits code execution. So, yes, in a very limited sense, this is the programmer’s fault, in the same way that someone shooting themselves in their own food is “their fault”, but that doesn’t mean you can’t say, “Gee, maybe we should design a safety for the gun so that it doesn’t have these accidental discharges.”

                                  1. 4

                                    You appear to agree with my position on the issue (memory management is hard so lets design better tools) but your post is written like a refutation. “Unless the code literally calls eval…” is a normative statement, not a technical assessment of the world as it currently is. I don’t think one should use languages that are not memory safe by default, which is why I put the blame squarely on C and not the programmer for code execution bugs.

                                  2. 1

                                    Parser code is a particularly rich source of memory management bugs. Especially if it’s C. Especially if it’s C and I’m the one writing it.

                                    So, if your program is supposed to get data that are constrained enough not to need a parser, then don’t write a parser.

                                  3. -2

                                    Pretty common to make data space unexecutable and instruction pages read/exec only these days so it should not be a issue for user code even if written in (gasp) C.

                                    1. 12

                                      Return-oriented programming was invented specifically for that scenario IIRC. Its users have been having a field day with over-simplistic defenses like read/exec. Most CompSci work is therefore doing cheaper memory-safety, control-flow integrity, dataflow integrity, or tactical defenses against ROP.


                                      1. 9

                                        There’s plenty of way to get code execution only by corrupting data. It’s been a long time since running shellcode on the stack is dead, and yet that never stopped anyone from getting RCE here and there.

                                        1. 8

                                          How are you a vocal & aggressive defender of C programming, both here and on hacker news, while remaining totally ignorant of how ROP attacks work and why W^X mechanisms do nothing to guard against them?

                                          1. -2

                                            I’m sorry my opinions annoy you so much. Feel free not to read them.

                                            I’m astounded to realize W/X guards “do nothing” to prevent attacks. Who knew?

                                            Many of the complaints about C are obviously correct - it’s an old language with flaws that were visible early on and the C standard has developed in some really stupid ways. Furthermore, many C programmers should not be C programmers - they have no idea of how to hide complexity. On the other hand much of the criticism of C is either irritating self-righteous shilling for some flawed alternative or absent of any understanding of tradeoffs.

                                            1. 2

                                              they have no idea of how to hide complexity

                                              One of the reasons I like C is that it doesn’t give you too many ways to hide complexity. If there’s complexity, it will be in plain sight. And when it comes to security audits, I want to see all the complexity that is there. By contrast, languages like C++ enable and perhaps even encourage people to write deceptive code that looks simple on the surface.. only you don’t know about all the overloading that’s making the code do crazy things behind the scenes.

                                              Complexity needs to be reduced, refactored, or removed entirely. Hiding it doesn’t help.

                                              1. 1

                                                I’m astounded to realize W/X guards “do nothing” to prevent attacks. Who knew?

                                                Literally anyone who has been paying even a modicum of attention to security implications of the continued use of C.

                                                I mean, you’re the one who made the claim “Pretty common to make data space unexecutable and instruction pages read/exec only these days so it should not be a issue for user code even if written in (gasp) C.” which is spectacularly ignorant of both things like ROP attacks AND of the severe information disclosure issues we’ve seen caused by buffer overreads, which W^X also does nothing to help with.

                                                Some level of self-reflection is in order here, to ask yourself why you felt confident making claims you clearly do not have the knowledge or understanding to be making.