I have no problem with Curl being written in C (I'll take battle-tested C over experimental Rust) but this point seemed odd to me:<p>>C is not the primary reason for our past vulnerabilities<p>>There. The simple fact is that most of our past vulnerabilities happened because of logical mistakes in the code. Logical mistakes that aren’t really language bound and they would not be fixed simply by changing language.<p>So I looked at <a href="https://curl.haxx.se/docs/security.html" rel="nofollow">https://curl.haxx.se/docs/security.html</a><p>#61 -> uninitialized random : libcurl's (new) internal function that returns a good 32bit random value was implemented poorly and overwrote the pointer instead of writing the value into the buffer the pointer pointed to.<p>#60 -> printf floating point buffer overflow<p>#57 -> cookie injection for other servers : The issue pertains to the function that loads cookies into memory, which reads the specified file into a fixed-size buffer in a line-by-line manner using the fgets() function. If an invocation of fgets() cannot read the whole line into the destination buffer due to it being too small, it truncates the output<p>This one is arguably not really a failure of C itself, but I'd argue that Rust encourages a more robust error handling through its Options and Results when C tends to abuse "-1" and NULL return types that need careful checking and can't usually be enforced by the compiler.<p>#55 -> OOB write via unchecked multiplication<p>Rust has checked multiplication enabled by default in debug builds, and regardless of that the OOB wouldn't be possible.<p>#54 -> Double free in curl_maprintf<p>#53 -> Double free in krb5 code<p>#52 -> glob parser write/read out of bound<p>And I'll stop here, so far 7 out of 11 vulnerabilities would probably have been avoided with a safer language. Looks like the <i>vast majority</i> of these issues wouldn't have been possible in safe Rust.
I'm kind of torn on this.<p>On the one hand, Curl is a great piece of software with a better security record than most, the engineering choices it's made thus far have served it just fine, and its developers quite reasonably view rewriting it as risky and unnecessary.<p>On the other hand, the state of internet security is really terrible, and the only way it'll ever get fixed is if we somehow get to the point where writing networking code in a non-memory-safe language is considered professional malpractice. Because it should be; reliably not introducing memory corruption bugs without a compiler checking your work is a higher standard than programmers can realistically be held to, and in networking code such bugs often have immediate and dramatic security consequences. We need to somehow create a culture where serious programmers don't try to do this, the same way serious programmers don't write in BASIC or use tarball backups as version control. That so much existing high-profile networking software is written in C makes this a lot harder, because everyone thinks "well all those projects do it so it must be okay".
While this doesn't so much apply to libcurl (but see below), there is a third alternative to "write everything in C" or "write everything in <some other safer language>". That is: <i>use a safer language to generate C code</i>.<p>End users, even those compiling from source, will still only need a C compiler. Only developers need to install the safer language (even Curl developers must install valgrind to run the full tests).<p>Where can you use generated code?<p>- For non-C language bindings (this could apply to the Curl project, but libcurl is a bit unusual in that it doesn't include other bindings, they are supplied by third parties).<p>- To describe the API and generate header files, function prototypes, and wrappers.<p>- To enforce type checking on API parameters (eg. all the CURL_EASY_... options could be described in the generator and then that can be turned into some kind of type checking code).<p>- Any other time you want a single source of truth in your codebase.<p>We use a generator (written in OCaml, generating mostly C) successfully in two projects: <a href="https://github.com/libguestfs/libguestfs/tree/master/generator" rel="nofollow">https://github.com/libguestfs/libguestfs/tree/master/generat...</a> <a href="https://github.com/libguestfs/hivex/tree/master/generator" rel="nofollow">https://github.com/libguestfs/hivex/tree/master/generator</a>
Not only is curl based on C, but so are operating systems, IP stacks and network software, drivers, databases, Unix userland tools, web servers, mail servers, parts of web browsers and other network clients, language runtimes and libs of higher-level languages, compilers and almost all other infrastructure software we use daily.<p>I know there's a sentiment here on HN against C (as evidenced by bitter comments whenever a new project dares to choose C) but I wish there'd be a more constructive approach, acknowledging the issue isn't so much new software but the large collection of existing (mostly F/OSS) software not going to be rewritten in eg. Rust or some (lets face it) esoteric/niche FP language. Even for new projects, the choice of programming language isn't clear at all if you value integration and maintainability aspects.
Well put.<p>Didn't know that curl was stuck back on C89, that's really optimizing for portability.<p>If anyone is confused by the "curl sits in the boat" section header, that's basically a Swedish idiom being translated straight to English. That rarely works, of course, and I'm sure Daniel knows this. :)<p>The closest English analog would be "curl doesn't rock the boat", I think the two expressions are equivalent (if you sit, you don't rock the boat).
The 7th point: "curl sits in the boat"<p><pre><code> In the curl project we’re deliberately conservative and
we stick to old standards, to remain a viable and reliable
library for everyone. Right now and for the foreseeable
future. Things that worked in curl 15 years ago still work
like that today. The same way. Users can rely on curl. We
stick around. We don’t knee-jerk react to modern trends.
We sit still in the boat. We don’t rock it.
</code></pre>
I see a lot of inertia in there. While it's a great record to maintain 15-year consistency but in the era of every changing InfoSec outlook, it could be a legacy and baggage if the authors resist to change. One thing we know for sure is that human will make mistakes, no matter how skillful you are. In the context of writing a fundamental piece of software with an unsafe programming language, that means we are guarantee to have memory-safety induced CVE bugs in curl in the future.<p>Some of other points that the author raised are valid too. If there is a trade-off that we can have a safer piece of fundamental software by almost eliminating a whole category of memory safety related bugs, and with the downside of less compatibility with legacy systems, more dependencies etc., perhaps we should consider it? I believe the tradeoff is well worthy in the long run and option is ripe for explore.
It's extremely simple. If you think Curl would be better in another language then port it, release your alternative, and maintain it for a long time.<p>Even if your language (Rust, Erlang, LISP, Go) is "better", it's still a minimal part of the equation. A maintainer is what makes the tool. It's hard work to decide which PRs to accept (and worse yet, reject), to backport fixes to platforms for which you can't get a reliable contributor, coordinating fundraising/donations, keeping up with evolving standards...<p>Anyway. Thank you, thank you, thank you Daniel Stenberg. Use whatever damn language you want.
> A library in another language will add that language (and compiler, and debugger and whatever dependencies a libcurl written in that language would need) as a new dependency to a large amount of projects that are themselves written in C or C++ today. Those projects would in many cases downright ignore and reject projects written in “an alternative language”.<p>Why would I be vendoring my own copy of libcurl in my project? Who does? This is how I (or rather, the FFI bindings my language's runtime uses) consume libcurl:<p><pre><code> dlopen("libcurl.so")
</code></pre>
I rely on a binary libcurl <i>package</i>. The binary shared-object file in that package needed a toolchain to build it, but I don't need said toolchain to consume it. That would still be true even if the toolchain required for compiling was C++ or Rust or Go or whatever instead of C, because either the languages themselves, or the projects, ensure that the shared-object files they ship export a C-compatible ABI.<p>An example of a project that works the way I'm talking about: LLVM. LLVM is written in C++, but exports C symbols, and therefore "looks like" C to any FFI logic that cares about such things. LLVM is a rather heavyweight thing to compile, but I can use it just fine in my own code without even having a C++ compiler on my machine.<p>(And an example of a project that <i>doesn't</i> work this way: QT. QT has no C-compatible ABI, so even though it's nominally extremely portable, many projects can't or won't link QT. QT fits the author's argument a lot better than an alternate-language libcurl would.)
Agreed 100%. Definitely going to be trotting this article out next time I see someone blindly arguing for rewriting xyz in Rust.<p>I particularly like the mention of portability. No other language comes even <i>remotely</i> close to the portability of C. What other language runs on Linux, NT, BSD, Minix, Mach, VAX, Solaris, plan9, Hurd, eight dozen other platforms, freestanding kernels, and nearly every architecture ever made?
> <i>The simple fact is that most of our past vulnerabilities happened because of logical mistakes in the code. Logical mistakes that aren’t really language bound and they would not be fixed simply by changing language.</i><p>This statement is laughable nonsense. Shall we go into their bug history and point out counterexamples left and right? [Edit:user simias has done this; thanks!]<p>Every single bug you ever make interacts with the language somehow.<p>Even if you think some bug is nothing but pure, that logic is part of a program, embedded in the program's design, whose organization is driven by language.
><i>There. The simple fact is that most of our past vulnerabilities happened because of logical mistakes in the code. Logical mistakes that aren’t really language bound and they would not be fixed simply by changing language.</i><p>That's wrong. A lot of the C mistakes are indeed "logical mistakes in the code", but most of them would be indeed fixed by changing to a language that prevents those mistakes in the first place.
In my view, the problem with C in general is that it's a loaded gun with no safety or trigger guard. It's trivial to shoot yourself (or someone else) in the foot, and it requires knowledge, meticulous care and lots of forethought to avoid getting shot.<p>I very much agree that rewriting existing, stable software written in C is likely not worth the trouble in many cases, but I can't accept claims that the limitations of C aren't the direct cause of tens of thousands of security vulnerabilities, either.<p>In Rust, even a less experienced developer can fearlessly perform changes in complicated code because the language helps make sure your code is correct in ways that C does not. And you can always turn off the safeties when you need to.<p>Experienced developers should feel all the more empowered by simply not having to always worry about things like accidental concurrent access, use-after-free, object ownership, null pointers or the myriad other trivial ways to cause your program to fail that are impossible in safe Rust. You get to worry about the non-trivial failure modes instead, which is much more productive.
"C is not a new dependency"<p>To just use a library, rust isn't much of a dependency, either. It's designed so you don't even need to know that it's not C.<p>Rust would obviously be a build dependency, but that's lessened somewhat because it tries to make cross-compilation easy.<p>(But this point does apply to pretty much any other language. Curl would not be used as widely if it depended on the Go runtime, for instance.)
While I'm definitely not suggesting we <i>replace</i> Curl with a rewrite in Rust (since the current Curl has had decades of good testing and auditing done on it), I am actually very curious how a rewrite in a safer language like Rust, OCaml, Haskell, or Go would fair in comparison in regards to performance and whatnot.<p>If I were ambitious enough, I'd do it myself in Haskell, but I think it'd be too much work for a simpler curiosity.
This seems like a no-brainer for a re-implementation in rust, but I wouldn't expect that someone would rewrite curl itself in rust, but a new library that does the same things.
I think Rust community increasingly behave like this[1]. They are big on suggesting others the better 'ideas' instead of implementing themselves. So they keep using 'curl' and 'openssl' but tell others to rewrite their software with Rust.<p>1. <a href="http://dilbert.com/strip/1994-12-17" rel="nofollow">http://dilbert.com/strip/1994-12-17</a>
I don't see why this is an issue, whoever is arguing for a change can write rurl and be done, and see if anyone takes it up in their distributions.
I don't think C is a bad language, although I think it could use lists and dictionaries in standard library. std::vector and std::map are the only things that make me pick C++ in an instant, given the choice.
While C by itself is not safe, I would argue that no sane development environment uses C by itself. Over the decades of its production use dozens of tools have been developed that make it far safer: *grind suite, coverage tools, sanitizers, static analyzers, code formatters and so on. Those tools are external, otherwise they would make C slower. Something for something.
I think it's a bit weird that C and curl are used. If we look at C and OpenBSD or so things might look a bit different.<p>Also one has a hard time comparing curl with another language, simply because something with curl's properties (take portability for example) doesn't exist.<p>And no that isn't in defense of anything, just me thinking thinking that measurable points brought up in the discussions don't make sense or exist.<p>The topic is also a bit broader, as you can easily add in static code analysis, compiler flags, stuff like W^C, stuff like seccomp, capsicum, cloudabi, pledge which might not work (well) in other cases.<p>It's a great philosophical discussion topics and I don't wanna stop anyone, just hoping people keep that in mind, when they participate, so we don't end up with new dogmas that get thrown around for the next few year, without knowing contexts or meaning of phrases.<p>Other than that: I really enjoy this discussion. :)
I'm curious, of the bugs that <i>could</i> have been avoided by using a "safe" language, how many could have been avoided by using a bounds checking extension like as <a href="https://www.doc.ic.ac.uk/~phjk/BoundsChecking.html" rel="nofollow">https://www.doc.ic.ac.uk/~phjk/BoundsChecking.html</a> or <a href="https://github.com/Microsoft/checkedc" rel="nofollow">https://github.com/Microsoft/checkedc</a><p>Are such extensions popular, and if not, why not? I assume there's always some performance hit, but that might not be a big deal in an HTTP client, for example.
CPython also has many vulnerabilities in python rather than C.<p>It's hilarious reading rust marketers talk about how people should use rust, and yet their software doesn't work as well. It has plenty of bugs.<p>Then they go on and on about issues which post modern C doesn't have. Guess what? C has a lot of tooling, and yes, it's been improving over the years too. CQual++ exists. AFL exists. QuickCheck exists.<p>Can your rust project from two years ago even compile? Does it have any users at all?<p>There's a formally proven C compiler. How's that LLVM swamp going you've built your castle on?<p>Rust brought a modern knife to a post modern gun fight -- and lost.
Quite recently I happily used libcurl for C++ project rather than any of those C++ wrappers found at github. Granted there is some non-elegance when you adapt C-style error codes to C++ exceptions and non-C++-idiomatic code style right next to any C lib. Yet libcurl is battle tested (AKA proved to be rather bug free) and has nice clean API unlike.<p>IMHO it might eventually make sense to use other language/tech/whatever but the bar is quite high and it will quite probably take some serious sustained effort.
> The plain fact, that also isn’t really about languages but is about plain old software engineering: translating or rewriting curl into a new language will introduce a lot of bugs. Bugs that we don’t have today.<p>Don't rewrites, even in the same language usually lead to a better version of the software? I can't really imagine a seasoned C developer introducing completely new bugs in a code base they are already very familiar with
What is everyone using curl for that it needs to be written in C (or Rust?).<p>If it think about my usage, it's like get or post something and see what the returned json looks like. If I need to download something wget usually works without having to remember -O.<p>But higher level things like httpie are easier to deal with, sane defaults and all that. Maybe they use libcurl...<p>Are there any re-write userland in ${safe-high-level-lang} projects?
Maybe curl could be rewritten in C++ step by step like mpd (<a href="https://musicpd.org" rel="nofollow">https://musicpd.org</a>). C++ has RAII for resource management which can help a lot by itself. In my opinion the most hateful thing in C is freeing resources on all exit paths.<p>Although, curl in C++ - the naming would became inappropriate...
I feel blaming a language for errors is like blaming a gun for killing people.<p>The fact is, mistakes will happen, but in general if you follow the best practices you'll be fine. Failing to follow the best practices means you could be a better programmer. Just because the language gives you an option to do something, doesn't mean you should.
C has still huge market share. Seems that it occurs in 5% of all tech job offers:<p><a href="https://jobsquery.it/stats/data.technologies/C" rel="nofollow">https://jobsquery.it/stats/data.technologies/C</a><p>Stats also showing that average salary for C developers is above average for all tech job openings.
Maybe they should attempt writing it using the Isabelle/HOL transpilers to C from SEL4 project. I don't care if it is C or machine code as long as the proof of correctness is complete, down to at least C library.<p>Curl is small enough to make it relatively easy and used widely enough to make it worthwhile.
This has probably been said, in this thread even, but if curl is insecure (for some value of "insecure") then its ubiquity and ease of embedding are a problem rather than a feature. Fuzzy thinking.
It's well within reason and capabilities for rust community to write libcurl and curl CLI libraries.<p>The community should do it, spend a couple of years stabilizing, and then spread the words to others.
Software is almost a perfectly open market. If proponents of rust really think their preferred language is better in every way, they are free to rewrite the world in rust, and see the adoption numbers they get. After all, if rust is better in every way, we'd expect the adoption numbers to go up for their rust OS, with a rust http stack and rust web browser. Right?<p>Telling others to use their language instead of putting their money where their mouth is is truly what irks me about the rust community the most.<p>Want a rust world? Go write it and ship it.<p>Oh, and you don't get to complain about C until your PC runs more rust than C<p>Cool?
It is utterly amazing to me to see so many people's attitudes on this issue.<p>If I cut myself by hasty use of a knife, is it the fault of the knife maker? How is that even remotely rational? If you aren't willing (or don't know how) to use the tool correctly, don't use it.
This is a great little read and encapsulates the other side of the 'rethink the way' trend-ism of some HN new lang advocacy. C is fine, C is good. It is widely understood, it is a systems staple, and it is not dangerous in knowledgeable hands. Rocking the boat is fashionable.