Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Would Rust Secure Curl? (timmmm.github.io)
132 points by todsacerdoti on Jan 16, 2021 | hide | past | favorite | 116 comments


>These are how I classified the bugs. If I’ve got something drastically wrong let me know.

I'm really happy to see the data behind the claim! I've been slowly desensitized to opinions masquerading as unsourced supporting graphs of dubious provenance. It's so simple, but kudos to the author for the transparency.

When Daniel wrote "C is not the primary reason for our past vulnerabilities", he may or may not have been right. But he sadly did not back that up with easily verifiable, refutable, data.

Data is like a ray of sunlight. Instead of arguing high-level opinions, let's argue the data


Here's some data I found interesting:

>Speaking at the BlueHat security conference in Israel last week, Microsoft security engineer Matt Miller said that over the last 12 years, around 70 percent of all Microsoft patches were fixes for memory safety bugs.

https://www.zdnet.com/article/microsoft-70-percent-of-all-se...

Of course, Rust isn't the only language that tries to address memory safety, but it is one of the few that does so while retaining the performance of C.


Microsoft's current security advisory is to use C#/F# (including their newly introduced low level capabilities up to .NET 5), Rust and then C++ alongside Core Guidelines.

However the same Microsoft has backtracked in their rejection of C, adding support for C11 and C17, replaced the C++ userspace drivers framework with a C one, and despite all security sales pitch for Azure IoT, they ship Sphere OS and RTOS with a C only SDK.


No, Data does not get to decide what cUrl is implemented in, Who ever implements it gets to decide.

If you want to prove that RustUrl would be better then cUrl, you will have to implement it and prove that its actually better, by taking users away from cUrl. Decisions are made by those who make things not by those who have opinions, even if they are backed up by data.

Daniel doesn't have to defend his choices, because you can write your own if you don't like his.


> Who ever implements it gets to decide

That is true. And as the post mentions, Daniel did decide to allow some Rust into the tree, years after he wrote that post. Sometimes people change their mind. It's often a good thing!


Changing your mind is great! I do support, Daniels choice to do what ever he wants in what ever language. My statement was not against Rust, It was against the idea that software development is done by writing think peaces online.

I refer you to the Linux Kernel mailing list FAQ 15-6, that I think makes my point:

http://vger.kernel.org/lkml/#s15-6


It is true that code can convince, but often, the written word matters too.

For example, the Linux kernel is considering accepting Rust in tree. While that is predicated on people writing the code and demonstrating its value, even getting to that point has required a lot of communication and convincing. It is often considered polite in open source projects to attempt to build some consensus before sending large patches upstream.


Sure, but what the author of this article is arguing is that someone who has spent a lot of time and effort making something should throw all that work in the trash, and start over, because they did it wrong, I dint think that is either polite or constructive.


I didn’t read it that way, but yes, I would agree that that sounds very impolite. Maybe I read it wrong!


One of the things the author neglects is the ease of use of newtypes in Rust. This can actually alleviate a lot of parsing issues, by making it impossible to use stuff without parsing.

An example of where I've recently done something like this is my sparse linear algebra code. I have distinct types for column and row vectors for a matrix, so that if I want to right-multiply A with a vector, the input has to be a column vector and the output has to be a row vector. Similarly, if I want to left-multiply A with a vector, the input has to be a row vector and the output has to be a column vector.


Maybe Rust makes newtypes _easy_, but certainly C supports similar idioms by way of wrapping data in a unique struct.


The only significant difference is that you have to give the inner value a name in C, but you don't in Rust. It's a pretty marginal advantage.


I'm happy with the article overall.

>there are also a decent number of other bugs that come from cURL doing ad-hoc inline character-by-character parsing of just about everything, whereas in Rust you would probably use a library to fully parse things.

cURL is the library to fully parse these things,


The author was probably referring to parser generators or combinator libraries like non or pest.


This was my initial charitable interpretation too, but the linked URL is actually to a specific url parsing crate. That's definitely in cURL's wheelhouse.


cURL isn't an abstract parsing library in the notion that is intended here. Rust has some libraries that give you pretty high level abstractions for generalized parsing that are also incredibly performant - something that's not really a thing in C.


That jumped out at me too. cURL is one of the most ubiquitous libraries out there. It's worth keeping its dependencies to an absolute minimum, even if it means having to rewrite a function here and there.


I really should learn Rust. I am just nostalgic for C because C makes me feel like I am doing something closer to what the CPU works with. I know there are several layers underneath all that, but with C you can do all manner of dangerous things that by any means you shouldn’t be allowed to do. I have used it for a few projects over the years but lately the only place I really get into it is programming Arduinos or similar. I am sure sooner or later we will get a good toolkit for a language that both does proper memory management AND can allow you to do all the things you can do with C on a microcontroller, but so far I haven’t seen that.

Also, I have it on my TODO to go back and redo the Capture the Flag challenges from like 10 years ago that dealt with things like stack overflows. I had a ton of fun working on those and it would be fun to revisit them. Anyone got a modern version of something like that?


Zig is what you want.

It can cross-compile down to tiny tiny binaries with no dependencies that run on microcontrollers quite comfortably.


Thanks! I spent a couple of hours looking at it and it looks like a really cool language. Unfortunately no build targets for the ESP8266/ESP32 which is my current t microcontroller of choice but the next time I try to put together a project that targets a different architecture I’ll try Zig out!


Have you done the https://microcorruption.com/ CTF from 2014? It starts pretty simple, but I remember it being super fun.


I have an account there according to my password manager! But like Gandalf I have no memory of this place. Very cool, I know what I’ll be doing tomorrow, thank you!


This is counting the number of bugs, but what about the severity?

https://curl.se/docs/CVE-2018-1000007.html is a logic bug that may cause sensitive headers to be sent to the wrong host on redirects. It's slightly obscure, but I can imagine what an exploit looks like.

https://curl.se/docs/CVE-2018-1000120.html is a memory bug that lets you write a single null byte out of bounds. That's a security issue, but exploiting it seems less straightforward. (Though maybe it is more dangerous than the other one on net? I don't know enough about these issues to say.)

It could be that Rust would prevent half the vulnerabilities yet prevent much less than half the danger caused by vulnerabilities.


Do note that the "single out of bound NULL byte" vulnerability has famously caught people off-guard in the past due to it being unexpectedly exploitable =)

https://googleprojectzero.blogspot.com/2014/08/the-poisoned-...

Those kind of exploits are thankfully getting harder with the many layers of mitigations we have today, but trying to predict which memory bug will or will not be exploitable is a very unintuitive and inadvisable exercise.


So you're saying Rust would make it more secure, but is not a magical panacea that prevents all security holes? I mean...okay. Still seems like a good reason to write it in Rust?


I'm only saying that Daniel's claim that "C is not the primary reason for our past vulnerabilities" might be basically right, even though the article says it's wrong.

I'm a big fan of Rust, if it matters.


I know I’m not reacting to the substance here but thats a terribly designed diagram. If the goal is to compare these values then why don’t they all start at the same level? This stacked exploded bar chart is unconventional and hard to parse at a glance. Dare I say even missleading how the author’s prefered option (the “yes” collumn) is towering above all the other numbers even though it is roughly head to head with the “no” collumn. (47 vs 42).


It is a trade-off. Compared to a standard bar chart, this version makes it easier to judge partial cumulative sums of several adjacent bars.


C libraries/applications like these, which have many memory and logic bugs, should be written in SPARK. It can fully prove that your code is correct. The latest version of the SPARK tools can also handle ownership of pointers [1] (scroll down a little to the ownership_transfer.adb example) So RIIS it is! ;)

[1] https://learn.adacore.com/courses/intro-to-spark/chapters/01...


> Rust proponents may seem overly zealous and I think this has led to a minor backlash of people thinking “Rust can’t be that great surely; these people must be confused zealots, like Trump supporters or Christians”. But it’s difficult to argue with numbers like these.

Huh!?


Well it was probably unwise to add that language to the essay even if I don't think it is wrong.


Tolerance 101:

These are stereotypes. There's far more variety within constituents of a political or religious group (including atheists) than between them. Arguing that one group is more "zealous" than another is almost certainly untrue for any meaningful kind of comparison (e.g., Muslims have more extremists than other groups, but we would rightly balk at generalizing Muslims as extreme). At best, these comments are meaningless; at worst, they incite hate and divisiveness (predictable whataboutism: "but Trump is divisive! Why can't we be divisive toward his supporters?!"--yes he is divisive, but he shouldn't be our moral standard).


Huh!? I am not happy that he did not put costco shoppers in that list .. /s

Yes, that was a needless statement that distracts but you know what, there is no point getting too hung up on things like these from readers perspective too.


What part are you huh?ing at?


It's a foolish, aggressive analogy that needlessly distracts from the topic at hand, regardless of any validity it may or may not have. There are far better ways of communicating the intended message.


Overpolitization of everything?


Christians - confused zealots?


Well either y'all are or everyone else is....or just all of us.


Either way, this is definitely not the point of the post. It seems worthwhile to make an effort to avoid rehashing highly controversial, unrelated topics -- even if the article accidentally baits us into it.


C'mon. I'm as atheist as they come, but anyone who equates Christians with zealots has never encountered the Church of England.


Sure. Fits. Are you looking for support or something?

The language was unnecessary and unprofessional, but those are that only ways it was wrong. If I were writing something in a personal context where such opinions were not out of place rather than a technical article, I would absolutely apply that characterization.

You don't have to. But Don't be so baffled that anyone else does.


One can convincingly argue that pure materialists are confused zealots too.


Trump supporters and Christians: you'll be fine. Not everyone in the world will respect you, and some may disrespect you specifically for that part of your identity. Try to live and let live.


Burgers?


Welcome to the Rust community. Care for a drink?


[flagged]


A lot of the Actix-web drama was the author refusing to replace unsafe code with safe code that performs equally as well. After the creator quit, the community took over and removed a lot of the unsafe code present.


I checked a few, and they mostly look like cases of non-performance-critical code that just happens to have some fiddly, slightly-wrong memory-handling logic -- which Rust would, indeed, make much harder to mess up with little or no runtime penalty.


How many memory bugs of the same calibre has Actix had, even with the large amount of unsafe code in its codebase?


curl is in widespread use while Actix remains fairly obscure, so this isn't a particularly good comparison. Is there even a Rust project that publicly discloses it's bugs in the same manner as curl?


What manner is that, and how is it special?


Does Hacker News approve articles where the author insults Christians? Calling them "confused zealots"?


I never quite understood why an ideology should be except from criticism so long as it be popularly called a religion.

Evidently one can insult Rust evangelists, why do many consider the arbitrary classification of “religion” so special? Especially when it seems a common criterion to call something a religion is “at least part of the belief must be provably false.”. — wakarimasen lol.


The author doesn't criticize an ideology; he insults Christians. I imagine Hacker News would be less tolerant of those remarks if they had referred to Jews or Muslims as "confused zealots".


There’s a fundamental difference between insulting a repressed minority, and “insulting” a majority repressing others for religious reasons.


What is a minority and majority depends on where one lives, of course.

And naturally, the moralist is quick to loose such a perspective that not the entire world lives in his own back yard, it seems. — perhaps if he were more aware of how vast and different the world is, he would have been more doubtful of his own moral convictions.


I mean...1/3rd the world is Christian.

While, of course, you can find specific locations where they aren't the majority, you can also find specific locations, in the US, where white people aren't the majority.

That doesn't change the equation when talking about punching up vs punching down.

Neither is really relevant to the post; he's clearly using hyperbole to describe Rust zealots in other peoples' minds.


Ah yes well, if it work as such then I suppose since Asia is the continent with the plurality number of inhabitants on the planet then we can say all sorts of nasty things about Asians, but about the inhabitant of any other country would be foul play.

Somehow, I feel you simply speak of the plurality of your own back yard.


And 1/4 the world is Muslim, which is still almost certainly more than the proportion of the world you'd judge as white!


33% is, by definition, a minority.


That 33% is a plurality, though.


I suppose that seems reasonable to those who believe an individual’s moral worth is contingent on the ”identity” groups they belong to.


The author wasn't asserting Christians and Trump supporters were actually zealots; the author was saying Rust evangelists are often dismissed in the same way, dismissed for being "confused zealots", when in fact, there may actually be some merit to be found. There are certainly things said by Christians and Trump supporters I don't disagree with. That doesn't make me one, but I am an unapologetic Rust evangelist, so...


As someone with religious faith I am fine with the author's expression, that is what free speech is all about.


Trump is an ideology.


That seems to be a rather empty difference. — I can criticize Rust evangelicalism, but not Rust avangelicals?

And perhaps H.N. would have, but your argument is with me, and not “Hacker News” and I make no such distinction, provided, of course, that by “Jew” you mean “Judaist” and not “person whose maternal parent is a Jew”.


I think it was unnecessary and off-topic, and the quality of the article suffered for it.

However, the rest of the content was interesting.


Same here. The content is interesting, but he just made the whole things worse by insulting people.


I couldn’t care less of it.

Everyone ignores their political mini-rants or whatnot. It’s completely irrelevant to the discussion; especially this one.


> On-Topic: Anything that good hackers would find interesting. That includes more than hacking and startups. If you had to reduce it to a sentence, the answer might be: anything that gratifies one's intellectual curiosity.


I cannot see how you can give such an answer in good faith.


Does it really matter?


The problem with security in Rust is that the language emphasizes the reduction of memory bugs. The resulting code then creates an increased cognitive load which can make other bugs more likely.

Therefore, use Rust if you really have to. Otherwise, tools like automated garbage collection are a much better way to reduce the likelihood of bugs.


The cognitive load is just temporary. I can say that after writing it full-time for about half a year, and dabbling in and out of it for a bit longer, I've gotten as good with Rust as I was with JS or TypeScript.

I've seen people learn Rust as their first programming language, and it fills me with joy that the next generation of programmers won't have to build up this vault of apocryphal knowledge I've had to over the years. Or, at least, not the same one. And hopefully not as large.

I've also found Rust to be a very pleasant application development language. As a former NodeJS developer, I've been able to replace Express with Warp and Electron and React with Iced. It's not ready for all things, but it's ready for a heck of a lot. And the question of "what's possible" has broadened so much due to work by the community in even just the past year, I really think the majority of all other applications, including web frontend (cargo web), servers, desktop apps (iced), and mobile apps (cargo mobile), can be reasonably implemented in most part entirely in Rust within only a few years.


> the language emphasizes the reduction of memory bugs

That's not really true: Rust's borrowing and ownership apply to most kinds of in-program resource ownership and aliasing, not just memory.

> The resulting code then creates an increased cognitive load which can make other bugs more likely.

I'm not saying you're wrong, but I'd like to see any evidence for this. Personally, I'd expect the opposite to be true: knowing whether any given object is non-exclusively borrowed, exclusively borrowed, or owned at any point in the program sounds like very useful documentation for people reading the code.


From skimming some Rust code now and then, it seems to me that Rust programs look completely different at least. While C programs focus on creating simple data structures and getting the task done with as few memory operations as possible, in Rust I've dominantly seen use of types, memory/resource safety patterns and external libraries. My theory is that this removes direct understanding what happens and instead shifts the focus on how to get the task done while not violating the type system rules. In both cases, what the programmer minimizes in the first place might be the lines of code or maybe "code complexity". (Assuming programmers tend to do what most directly leads to completion of the programming task).

I'm not in a position to claim that this theory is actually true, and I won't take a stance which is "better", but personally the former is much more appealing to me, for purely aesthetic reasons.


Rust provides a good balance between performance, correctness, and ergonomics. It's called the "Goldilocks language", because it's not too slow, it's not too unsafe, and it's not too difficult.

Also, much of the tooling I used to add to projects in other languages is either built-in and commonly used (test, fmt), or easily added to cargo (edit, bench, web, mobile).


> My theory is that this removes direct understanding what happens and instead shifts the focus on how to get the task done while not violating the type system rules

In my experience it is in fact still a requirement to understand what's happening in order to write clean and fast Rust code. It is possible to satisfy the compiler using a lot of clone() calls and similar shortcuts, but once you understand what data structure is allocated when and where and how the whole ownership principle works in practice you can suddenly avoid a ton of unnecessary heap allocations and other pitfalls. I'd say my experience with Rust improved a lot once I started grasping what's happening in memory and why certain syntax elements exist, as this makes fixing compiler errors more intuitive and less a blind trial and error session with the borrow checker.

Some of Rust's syntax can look weirdly unfamiliar at the beginning, but everything is there for a good reason. Nothing is done implicitly, and much of the pattern matching and Option/Result related stuff is Rust's way of replacing the concept of `null` with thoroughly type-checked expressions.


I find this description unsatisfying. The "use of types" makes applications easier to understand and cleaner for example. Just a generous use of enums helps with some kinds of logic errors as well and ensures more expressive code. (==1 vs ==Match::Domain)


I use enums in C, too. And the problems with C enums that people complain about don't apply for me. That's not what I mean by "use of types". What I mean by it is significant "programming in type language" as opposed to "in code language". Programming in type language I find unappealing because it is very indirect, implicit, and typically achieves very little per line of code.


> I use enums in C, too

Enums in C are just ints with names. They're error prone and not type checked. You can always use 0 instead of a name and it will work. You can use TLSv2 instead of ExterminateHumans and it will also work.

> What I mean by it is significant "programming in type language" as opposed to "in code language".

I honestly don't understand what you mean by this.


> Enums in C are just ints with names.

Yes, they are integers. You can do arithmetic with them, you can use them as bitmasks, or use sentinels instead, like -1. I like that.


Okay so, the issue here is that you two are speaking past each other. Enums in Rust are more than enums are in C. So this conversation is something like:

Them: I like sandwiches.

You: I get sandwiches from McDonalds, they're great.

Them: Yes, but those are burgers. (The implication being that there are also other kinds of sandwiches.)

You: Yes, burgers are good.

You're not wrong, but you're kind of missing what they're saying.

Enums in Rust can be like enums in C, but they can also be tagged unions. Furthermore, Rust won't automatically cast an enum to an int, so it is a bit harder to make mistakes, even if you're using the C-like ones. That's the advantages they're speaking about. Enums are good and useful in C, it's true. That's why Rust added stuff to make them even more useful.


Yup, plus the other uses have their own implementation. If you're doing arithmetics, in rust you probably want a constant. If you want a bitmask, there's bitfield crate (or a struct/enum with bitwise ops implemented).


Keep in mind that just because you like something, doesn't make it good, and that's starting to get more and more important in these days where software is used for everything, including things really depend on.


This seems like an unlikely claim, do you have any numbers to back it up?

If having memory errors being compile time errors instead of runtime error leads to more logical errors due to complexity. Wouldn't that imply that using other types of complicated checkers also leads to more logical errors, for example static analysis software or valgrind?


Rust's type system with regards to C and that of many other languages certainly helps to avoid logic bugs as well.

A simple difference would be that, for instance, in Java every object is nullable, whereas in Rust, this is only so when it be declared as such, and the type system requires one to in some capacity first verify of a nullable type that it isn't null, before something meaningful can be done with it.


How do I do GUI in Rust? User interface dialogs.

Can I do linked lists in Rust?

Can I define classes such that:

  cInches in1, in2, in3;  // basically a float
  cCm cm;  // basically a float
  in1 = in2 + in3;  // OK
  in1 == 2.f * in2;  // OK
  in1 = in2 / in3;  // compilation error
  cm = in1;  // compilation error
  
  void foo(cInches in);
  foo(cm);  // compilation error



Wow! That's impressive. Did you just whip this up? :o)

I've got 500KLOC C++/Qt running under Windows and macOS. I wonder if Qt have any plans.


Yep! I enjoy using the language :)

There is a crate called “cxx” that provides support for C++ interop in Rust: https://cxx.rs/


Fully idiomatic GUIs are still an open problem in Rust, but I wrote a Win32 MDI application in Rust last week. It just makes you feel gross, but it's the same as other native code.

Linked Lists are easy. _Doubly_ linked lists can't happen without Rc or unsafe, but that's fine.

And yes you can create types for domain units, while controlling the combinations like that, and can go deeper in that sort of idea than C and C++.


1. Use a binding to a library or write your own. Gtk bindings are probably the most mature option, but there are some exciting in-progress ones.

2. Yes. One is even provided in the standard library, if that suits your needs. However, most people don’t use linked lists because other data structures are near-universally better.

3. Rust doesn’t have classes, but you can do something similar. The name is the “newtype pattern.”


Yeah, you can do newtypes (or just defining new types), in addition to Structs, Enums, and Traits.

For those who don't know, Traits are like a sort of "class interface" that can be automatically applied to things that have implementations for those traits, and conversion between, once that code is pulled in scope via `use`.

Rust doesn't have classes or inheritance, instead, it has more powerful tools, ones that aren't as limited.


Why is this being downvoted? Am I wrong about something? If so, please tell me, I'm still learning.

Ah. Maybe it's because I explained stuff that's basically newtypes using language that might make it seem they're different? Ugh. HN comments always make me so neurotic. But the content is usually more interesting than dev.to. I just wish they'd get rid of the downvote feature.


For what it's worth, I'm mildly experienced in Rust and your comment looks pretty much correct.

I'm recovering from a headache (and a little ketted out) so I might be missing something too, but in the spirit of trying to explain confusing downvotes, here's the only two potential nitpicks I can see:

  1. newtypes are not really 'in addition' to structs, enums, etc. they are a particular type of struct with a fancy name.   
  2. Calling composition less powerful than inheritance could be seen as subjective and debatable. I mostly like composition over inheritance, but Rust for example has problems with up-casting of trait objects (https://github.com/rust-lang/rfcs/issues/2765) that inheritance/vtable based languages (e.g. C++) do not have.
So it's not a bad comment, and I suspect you mostly just got piled on due to human error/bias. Or maybe some poor soul got confused and thought you were trying to explain Rust to the poster above you (who may not need much explaining).

Don't take it personally, you seem to have a good grasp of the language. Please keep on learning :)


Thanks! And of course not. I was just trying to support Steve's point, or expand on it a bit.

That was a thoughtful response, though, and I'm grateful.


You know what would definitively prove whether it would? Just do it!

I'm so tired of these "rewrite in rust" articles that have no code behind them. Spend the time and write a replacement for curl, ship it, and people will start using it instead of curl. In some years time, you can write a paper showing how many vulns your replacement had vs. rust. curl continues to be written in C because it has someone actually doing the work to write and update it. A theoretical rust replacement does not exist because no one is doing the hard work of writing and maintaining it.

It's like LibreSSL vs OpenSSL. Did LibreSSL end up being more secure? At least we can find out instead of just guessing about whether removing crappy code from OpenSSL would be a good idea.


Did you see the link in the article? Curl does now have some Rust in it. People have been doing that work.


This is a tool issue and not a language issue. I think that if you do some thing in code that results in unintended behavior, then that's a bug that should be communicated to the developer during development.

A buffer over-run isn't a bug, its the symptom of a a bug in the arithmetic that computes how to access the buffer. The way to fix that is to communicate and address the bug during development, not to try to mitigate the symptom at run time.

I am a C programmer, and to me buffer over-runs are a rare class of bugs, and a class of bugs that are (at least on the heap, and often on the stack) trivial to find and fix with the tools i have.


Why are they so trivial to detect for you while they bedevil the rest of the software industry? Is it possible that there are many such bugs hiding in your code that have not been found, because your code has not been subjected to the amount of scrutiny that projects like cURL, Windows and Chrome have?


I think i have fewer, bugs but this is a wild guess as I have no data supporting this even though i have significant number of users.

I dont know why others struggle with it, but I suspect:

-Most programmers are not used to thinking about memory the way you should when using C.

-Most developers are not aware of the tools available for debugging C.


You should write an operating system, clearly Torvalds and the Microsoft and Apple kernel developers have not reached your level yet.


As someone who helps write an operating system, some areas of kernel code can be less subject to the usual C memory safety issues than most user code. This isn’t because kernel programmers are special, but because the kind of code that gets written is different. I rarely find myself allocating memory at all in kernel code, and if I don’t allocate memory, I’m less likely to overrun a buffer.

In other areas of kernel code, buffers common, but the data is completely opaque. You won’t find kernel code parsing a buffer written to a filesystem because there is nothing to parse. The buffer is literally just a pointer and a length.

That being said, I would love something like Rust for lifetime management and thread safety and for the occasional data structure.

(Large sections of Linux are indeed quite scary from a memory safety perspective. Anything related to /proc or /sys comes to mind.)


I don't find either of the Kernels you mention to be particularly unsafe, despite being written in "unsafe" languages. Can you point to better kernels written in Rust?


Redox?

That being said, a kernel is a huge undertaking. There is nothing else with the scope of Linux. And substantial parts of writing a kernel involve dealing with architecture nastiness, and, in the absence of formal architecture models, no language will help much here. The Linux x86 low level code is a terrifying mess, and it’s also the best and most capable implementation I’m aware of. (I’m obviously biased.) A language like Rust would help only a tiny bit.

(Something like NMI handling on x86 is fundamentally memory unsafe. If you get nested NMIs, your stack gets clobbered. Thanks AMD. Linux has code, mostly in assembly, that detects and recovers. Good luck writing it in any memory safe language.)

I once skimmed seL4, and I would not use its x86 code for serious work in its current form.


> I am a C programmer, and to me buffer over-runs are a rare class of bugs, and a class of bugs that are (at least on the heap, and often on the stack) trivial to find and fix with the tools i have.

What does your testing setup look like? Does it include regular fuzzing and security audits? Buffer overruns are so common because normally your mental model of how the code should work assumes they don't happen, so you forget to test for their presence (or prove their absence, like Rust nudges you to).


That sounds like the opposite of the mindset I have when writing C. Keeping buffer limits in mind all the time, and having them communicated around the code/function calls and respected, is one of the most basic things.

I don't do fuzzing, because I leave string parsing to tools like re2c. I tried it in the past with my mail message parser written in C/re2c and it was not very helpful.


There are also other low-level languages besides C and Rust

I use Pascal, and I never have any buffer overruns in my code. If there were any, Pascal's automatic bound checking on array indices would raise an exception

The only issue is, should I keep the bound checking in the release builds for maximum safety, or disable them for maximum performance?


I tend to have tests on a lot of the time (see below about my test lib). As someone who has worked with C for a long time, I think my mental model is all about direct memory access, so it probably comes more natural to me.


> The way to fix that is to communicate and address the bug during development, not to try to mitigate the symptom at run time.

You'll write bugs and they'll make it past the development phase because bugs are inevitable. So now the choice is whether they're a crash or an rce.


How are they trivial? The issue with buffer overruns is that they're usually silent. If you have an array of pointers, and you overrun that array, you could end up assigning garbage to another pointer variable. Then when you deref that, if you're lucky it'll be outside the mapped memory addresses for that process and you crash. If you're unlucky, you read or write to a random location.

Basically the point is, it's very easy to end up in a situation where you know you have a bug but you're 2+ levels of indirection from the actual logic error. Those sorts of issues are always the biggest time sink.


I have a debug mode in my code base, where I wrap malloc, free, and realloc with debug versions that over allocate all allocations that are made, and put magic numbers before and after the memory blocks. These are periodically checked to make sure nothing has been overwritten that shouldn't be. You can find this code on my website, www.gamepipeline.org as part of the "forge" library.

The system tells me very precisely what has gone wrong with buffer over-runs, and it also make memory leaks and double frees trivial to find.

Visual studios debug mode does something similar with buffer overruns on the stack, but I tend not to put very many buffers on the stack so that much more rare as an issue.

If you want to go even more hardcore, windows has "gflags" that you can turn on to find overruns using memory protection.

LLVM also have the "Checked C" compiler that also finds these issues.

My own system is so good that, I haven't used gflags in a few years and I also haven't tested Checked C so I cant vouch for it, but there are loads of possibilities in this space that i hope to explore further in the future.


This testing-based approach is great at finding buffer overflows that occur within your test suite. But especially for code like curl that runs on untrusted data, you need a more adversarial mindset. Unless your tests cover every possible input, a clever attacker might always find input data that you didn't think to test.


Here's an example from one of your own projects, where code that works fine on normal input has a buffer overrun on malicious or corrupted data:

https://github.com/quelsolaar/HxA/issues/4


These sound good, and I've used things like asan and ubsan which do a lot of the same thing. The issue is not everyone's running in a traditional environment where you have the conveniences of things like... an OS.


I sometimes write code for micro controllers, and I tend to wrap all system calls so that I can run the same code on my PC just to get access to better tools. On small hardware platforms its common that you are forced to use C because of the limited resources, so the options are limited.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: