Live data from Hacker News

Getting Past C

blog.ntpsec.org

41–50 of 504 posts

Re: Getting Past C

#41

Honestly, why not do it once and for all in a strongly typed pure functional language, validate it, and then tweak the GC parameters to get the performance? Use the safest and most powerful language that you can, if you can.

Yes, please use Haskell or Rust for this. Go is an awkward middle ground.

Re: Getting Past C

#42
post #8

Earlier quoted context omitted.

Can you pass this buffer to e.g. read() and it will still guarantee no buffer overflow even if the programmer mis-calculate the size argument to read() ?

No. It then follows that reading things safely is therefore a completely insurmountable problem in C. There is no possible way for me thin wrapper around read that works on bounds checked arrays, and not use "read" cavalierly in my code without thinking. Right?

The track record of two decades of CERT advisories for buffer overflows suggests that doesn't work in practice.

Re: Getting Past C

#44
post #27

Can anybody make a strong case to me as to why are buffer overflows considered an issue in C when it takes like 10 minutes to write and test an array implementation that prevents that from ever happening? I do agree that C has issues (though in my opinion neighter Rust nor Go address almost any of them) i just don't understand why are buffer overflows such a huge problem in C when the same thing is going to come up w…

Or perhaps just some helper functions in C that wrap array and pointer allocation/access to provide sanity checks. Seems like moving to a new language is rather extreme....

Why? Rust includes index checks by default, so you have zero chance of programmer error. And, to boot, it removes the checks when the compiler decides that the code is provably safe.

Re: Getting Past C

#45
post #26

Earlier quoted context omitted.

Is this abstraction zero-cost? What's the overhead? Can you give me a similar set of primitives to manipulate memory in a temporally safe manner as well? What is the cost of that abstraction? How does it compare to a runtime's GC?

> Is this abstraction zero-cost? What's the overhead? It will cost a single correctly predicted branch, which is effectively free on modern architectures. Any "safe" language will have to make this conditional branch too (Rust's File::read method will check the size of the slice).

Nope. Iterators in Rust can be used to safely avoid bounds checking in ways that would be impossible to enforce in C.

Re: Getting Past C

#46
post #26

Earlier quoted context omitted.

The fact that it doesn't occur to people to build safe abstractions in C to deal with things like buffer overflows still shocks me. C is fairly low level by todays standards. You 100% have to build abstractions using the standard library and then use those abstractions, rather than just using standard library functions everywhere. This isn't an argument against safer languages, or higher level languages, or languages…

Is this abstraction zero-cost? What's the overhead? Can you give me a similar set of primitives to manipulate memory in a temporally safe manner as well? What is the cost of that abstraction? How does it compare to a runtime's GC?

I never made the argument that you shouldn't use a safe GC'd language. I merely made the argument (now flagged for whatever reason) that buffer overflows are an easily solvable issue in C, and if you are having issues with them you really need up your game and learn to create abstractions.

As for the cost of the abstraction of bound checked arrays of arbitrary length, I can't imagine it being any slower than rust. I could be wrong. If you'd care to provide an example program in whatever language you are advocating, I can give you an implementation in C using a bounds checked array ADT, and we can compare notes.

Re: Getting Past C

#47
post #27

Can anybody make a strong case to me as to why are buffer overflows considered an issue in C when it takes like 10 minutes to write and test an array implementation that prevents that from ever happening? I do agree that C has issues (though in my opinion neighter Rust nor Go address almost any of them) i just don't understand why are buffer overflows such a huge problem in C when the same thing is going to come up w…

Because your 'safe' implementation will certainly have a performance cost, and won't be the default. This is why, despite C++ providing std::array, you'll still find buffer overflows in C++ code. C++'s std::array provides the safe 'at' function but you're opting into a performance penalty and it's not the more familiar [] syntax. Rust arrays/ vectors are safe-by-default. To use the unchecked, unsafe version requires…

In addition, the Rust compiler can also remove the built-in indexing checks if it can prove the code is safe. So, say, iterator loops over an array won't have any index checking.

Re: Getting Past C

#48
post #27

Can anybody make a strong case to me as to why are buffer overflows considered an issue in C when it takes like 10 minutes to write and test an array implementation that prevents that from ever happening? I do agree that C has issues (though in my opinion neighter Rust nor Go address almost any of them) i just don't understand why are buffer overflows such a huge problem in C when the same thing is going to come up w…

Or perhaps just some helper functions in C that wrap array and pointer allocation/access to provide sanity checks. Seems like moving to a new language is rather extreme....

Sure, glib for example contains all the wrapped network / file / string handling you need. But then you need to make sure you use it correctly. And that no code goes around that API. And that you didn't make mistakes that invalidate the safety of your abstraction.

Moving to an abstraction would potentially solve some overflow issues and requires constant attention. Moving to a safe language likely solves all of them and you get checked by the compiler instead.

Re: Getting Past C

#49

Earlier quoted context omitted.

I'll bet he can give you an array_read() function that does what you ask. I know I could.

The fact that it doesn't occur to people to build safe abstractions in C to deal with things like buffer overflows still shocks me. C is fairly low level by todays standards. You 100% have to build abstractions using the standard library and then use those abstractions, rather than just using standard library functions everywhere. This isn't an argument against safer languages, or higher level languages, or languages…

Because the fact that you have to write that secure abstraction means the majority of people won't do it, and even if they do, the vast amounts of code that you'll interface with in C that doesn't expect it and will happily index out of bounds if you call it incorrectly means you'll always be fighting an uphill battle. I imagine many people do what you did and write abstractions, and then the more they end up dealing with external libraries, the more they realize they aren't buying themselves as much security as they think they are, and it isn't just a one-time up-front cost, any time they need to interface with code that doesn't use their implementation, they may have to make sure everything is sane afterwards.

> I could push chars onto it and I didn't have to worry

And how did you implement this? Are you stitching together chunks of memory, or are you reallocating and copying? If you are reallocating and copying, what do you do when you have a point to the old address space that still exists? Now instead of manually updating memory and knowing you have to take care of pointers, your dynamic implementation might change stuff from underneath you without you noticing.

Re: Getting Past C

#50
post #27

Can anybody make a strong case to me as to why are buffer overflows considered an issue in C when it takes like 10 minutes to write and test an array implementation that prevents that from ever happening? I do agree that C has issues (though in my opinion neighter Rust nor Go address almost any of them) i just don't understand why are buffer overflows such a huge problem in C when the same thing is going to come up w…

Or perhaps just some helper functions in C that wrap array and pointer allocation/access to provide sanity checks. Seems like moving to a new language is rather extreme....

If you want to do this well, as other commenters pointed out, your entire C library interface is going to have to change to accept bounded arrays instead of pointers and lengths as separate arguments, or worse, just pointers and implicit lengths by looking for the NUL character. But then you've given up the ability to directly call into existing code; everything is at best using a little translation layer to check bounds before/after passing buffers to outside functions. So the advantage of staying in the language is minimal (note that you've given up on "C strings" entirely), and if you're going to have all of this, you might as well use a language with compile-time checks (types, etc.) that you're doing all of this right.

Rust and Go are not your only choices here. C++ with aggressive use of modern features and aggressive non-use of everything inherited from C is also a fine choice, but enforcing that discipline is hard, and the compiler won't help you a lot. Honestly, a dynamic language like Python or Ruby is also a fine choice in many cases, although NTP might be too latency-sensitive for that to work. (But it might not be! Premature optimization and all that.)

Post reply on HN