Live data from Hacker News

Getting Past C

blog.ntpsec.org

81–90 of 504 posts

Re: Getting Past C

#81
post #69

Earlier quoted context omitted.

Obviously, one can program C to do anything, and write all the provably safe abstractions wished. But, that's not really the point. The point is that doing such is not the default. It requires engagement and knowledge of the programmer, especially on distributed projects with loose communication, such as many open source projects. And it only takes one programmer mistake to bring the whole house of cards down. Why al…

And it only takes one programmer mistake to bring the whole house of cards down. Isn't this also true of Rust, with its unsafe keyword? None of these languages are completely safe against programmer mistakes.

Yes. It's trivial in Rust to write unsafe code. It's less trivial to mask the unsafe code and the (unproven, in my opinion) argument is that the explicit "unsafe" keyword makes it prohibitively difficult.

Re: Getting Past C

#82

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.

Some people don't believe in tweaking GC's. I've heard horror stories from people who tried it on the JVM.

(And I have made terrible experiences with JVM's GC, but never tried tuning).

Some people don't believe that extremist functional languages are needed (depending on the domain).

Validation. Oh, well.

I think you propose Haskell, and it might disqualify for an NTP daemon, for example in terms of debuggability (stack traces?).

Re: Getting Past C

#83
post #49

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…

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…

Because the fact that you have to write that secure abstraction means the majority of people won't do it

What's your point? My only argument has been that it's very easy and achievable to avoid buffer overruns in C. The fact that you assert most people won't do it is completely orthogonal to that.

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.

I use the standard library function realloc. The dynamic array is written in a fairly standard way, IE, I am not returning pointers to the allocated memory of the internal array. I access values inside the dynamic array by value (eg they are copied), not as a raw pointer to a slice of memory that could be realloc'd. It would never even occur to me to do that, so your example seems strange and far fetched.

Re: Getting Past C

#84
post #52

Earlier quoted context omitted.

And once you have written a five line safewrite() function, a hundred-line saferecvfrom() function, a 1500-line safeioctl() function, and all of that, and you have a third-party static analysis tool to prove that you're never calling the unsafe read() or ioctl() functions except from the wrappers, what was the advantage of staying in C in the first place?

I see where you are going, but I don't get how you get from 4 to 5 to 100 to 1500?

I can answer: safe read/write from a simple system call can be "easy." Safe read from the network, possible but no longer easy. Safe call to ioctl, which can literally do anything with any device driver... is a "safe" version of that even possible?

Re: Getting Past C

#85

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.

I think this is addressed in the article when they talk about the potential pitfall of Go's GC.

Re: Getting Past C

#86
post #69

Earlier quoted context omitted.

Obviously, one can program C to do anything, and write all the provably safe abstractions wished. But, that's not really the point. The point is that doing such is not the default. It requires engagement and knowledge of the programmer, especially on distributed projects with loose communication, such as many open source projects. And it only takes one programmer mistake to bring the whole house of cards down. Why al…

And it only takes one programmer mistake to bring the whole house of cards down. Isn't this also true of Rust, with its unsafe keyword? None of these languages are completely safe against programmer mistakes.

That's less of a mistake, and more of turning off the footgun's safety. Yes, it still only takes one programmer. But they have to purposefully enable such actions, as opposed to neglect to perform actions through the "proper" abstractions.

Re: Getting Past C

#87
post #36

Earlier quoted context omitted.

I think he means to work with raw memory so using unsafe keyword and in this case he is right. And you can't implement certain things in Rust if you are on the quest for maximum efficiency without using unsafe.

You can't implement certain things in C if you are on the quest for maximum efficiency. Thankfully, one rarely is, because efficiency isn't binary. It's about trade-offs.

I could say exactly the same for Rust, that it's not enough even using unsafe keyword and I need to go into assembly. Someone could even say that assembly is not enough and we need FPGA and then ASIC etc. But it's not the point here. The point is that for ex. you can't get safety from out of bounds access without bound checking, doesn't matter which language you use. And bound checking for certain hot paths is not acceptable.

Re: Getting Past C

#88

Earlier quoted context omitted.

Would you care to provide a short rust implementation of reading an arbitrary length string from standard input? I have rust installed. I would be curious to benchmark it and see if is indeed faster than the same thing in C, using a user-defined bounds checked array.

I didn't claim that rust would be faster than C (not that it can't be) in that situation. I would expect very similar performance. I'm not feeling very well unfortunately, not really in the mood to code.

I just keep hearing about how rust handles safe bounds checked arrays with (and I quote) "Zero-cost abstractions", which to me implied it would be faster than C, since C pays some performance penalty by branching.

Hope you feel better soon.

Re: Getting Past C

#89

Earlier quoted context omitted.

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…

Would you care to provide a short rust implementation of reading an arbitrary length string from standard input? I have rust installed. I would be curious to benchmark it and see if is indeed faster than the same thing in C, using a user-defined bounds checked array.

It's not so much a question of benchmarks, it's that one of the standard C tools for reading an arbitrary string from standard input is gets(). And if you reach for that from the standard toolbox, you've failed before you've started.

Re: Getting Past C

#90

Earlier quoted context omitted.

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.

As others have said, this is a fairly standard optimisation: compilers (Rust, C, C++, Java, PHP, whatever) will remove branches if they can see that it can never be taken. Iterators are slightly different in that they don't have any indexing checks at all: an array iterator yields a plain reference, and these are always dereferenced like plain pointers.
Post reply on HN