Live data from Hacker News

Getting Past C

blog.ntpsec.org

221–230 of 504 posts

Re: Getting Past C

#221

Earlier quoted context omitted.

We do, in both directions.

Is there a technical or political issue preventing Rust from using upstream LLVM? Either way, is there a possible resolution on the horizon?

Nope. You can use a stock LLVM if you want. Some tests might fail, since patches might not be in upstream yet.

It's not really something to resolve; it's just the usual situation with a big dependency.

Re: Getting Past C

#222

Earlier quoted context omitted.

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…

> I use the standard library function realloc. Realloc may automatically copy the range to a new memory block if the old block cannot be expanded, and when that happens the old range is freed. Any other pointers you had to items in that original array may become invalid every time realloc is called, and if it's automated by your dynamic array code, that could conceivably be any time you push an item onto that array.…

I am still perplexed why you think by using a dynamic array of chars for a buffer, it somehow involves me storing copies of the malloc'd memory anywhere. You can simply access data by copying it:

https://ideone.com/OObuAt

Note that it still prints 42 despite the allocated memory being freed. Line 7 copies the data at a specified index into x - x has no references to the malloc'd memory.

Re: Getting Past C

#223

Earlier quoted context omitted.

When writing modern C in a disciplined way, it is not as bad as the Rustophiles will make it out to be, but still a problem. Scenarios where I frequently end up fixing other people's memory errors: 1. No Error Handling: not checking an error condition on a function that allocates, then using the uninitialized pointer anyway 2. Sloppy Error Handling: jumping to abort from an error without freeing what has already been…

A properly-designed Rust API will not allow code without error handling to compile, so 1) should be much less relevant in Rust. 2) I can't remember if a panic in Rust calls destructors, which would clean up that memory. Can someone answer that please? 3) is only relevant in FFI scenarios in Rust, and everywhere else is irrelevant because Rust does not require the use of such footguns for basic string manipulation.

A panic _may_ call destructors, but it cannot be relied upon. For example, aborting is a perfectly reasonable panic implementation, and your destructors won't get called. If you have unwinding panics, they will call destructors though.

Re: Getting Past C

#224
post #128
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…

The lack of generics means your array implementation is either going to either: - be implemented with macros and token pasting, and result in a ton of mental overhead because you'll have a pile of types like array_foo for an array of `foo`s, and array_bar for an array of `bar`s, along with a pile of corresponding `foo * array_foo_get(array_foo, size_t)` and `bar * array_bar_get(array_bar, size_t)` functions. - or, ha…

You're missing main glaring issue with parametric polymorphism, bloat.

Re: Getting Past C

#225

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.

So can the C compiler. The optimization is called 'value range propagation'.

Re: Getting Past C

#226
post #140
post #128

Earlier quoted context omitted.

The lack of generics means your array implementation is either going to either: - be implemented with macros and token pasting, and result in a ton of mental overhead because you'll have a pile of types like array_foo for an array of `foo`s, and array_bar for an array of `bar`s, along with a pile of corresponding `foo * array_foo_get(array_foo, size_t)` and `bar * array_bar_get(array_bar, size_t)` functions. - or, ha…

No, you just allocate enough space to store an extra int at the start for the length, and return a typed pointer to the actual data. Then you need an accessor that checks bounds, if you want safe access. Both of these problems are solved by simple macros.

Arrays and pointers in C already have that int. That's why sizeof() works. The issue is an extra if statement on every single array and pointer access.

Re: Getting Past C

#227
post #89

Earlier quoted context omitted.

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.

Many rust advocates talk about the performance cost of doing things safely in C, and inform me that rust has "Zero-cost abstractions". So it's fairly natural I ask for something I can benchmark.

> Many rust advocates talk about the performance cost of doing things safely in C

Who's saying this? It doesn't really make sense, taken out of context as it is here.

> inform me that rust has "Zero-cost abstractions"

IMO at best the array bounds checking thing is an extremely poor example of a "zero-cost abstraction"; at worst it's not an example of it at all. As I understand it, the term refers to things like static dispatch on closures and trait methods, iterator fusion, and generally any place where the compiler can transform high level abstractions into really efficient low-level code where in other languages/implementations you might incur a performance penalty, for instance by dynamic dispatch to heap-allocated closures, or allocation of an intermediate vector at every "link" in an iterator method chain.

Re: Getting Past C

#228

Earlier quoted context omitted.

> i just don't understand why are buffer overflows such a huge problem in C when the same thing is going to come up when trying to work with memory in Rust. False. Buffer overflows in C can overwrite the program's memory, so it can be hijacked and supplanted with the attacker's code. This cannot happen in Rust (unless unsafe code has the vulnerability), or any memory safe language. Sure you can implement a safe array…

How much does that still happen with DEP and such? Don't OSes not let you write to executable regions or execute from stack/heap by default now?

It doesn't help as much as you'd think. With a buffer overflow on the stack, you can overwrite the stack's return address to point wherever you want, and overwrite a bit further to set the arguments to whatever you want, as well as any local variables on the stack. That depends, obviously, on what code is already there, but there's a lot you can do. For instance, if the system() libc function is linked, you can overwrite the return address and arguments to call system("some arbitrary shell code").

Check out https://en.wikipedia.org/wiki/Return-oriented_programming for more information.

Re: Getting Past C

#229

Earlier quoted context omitted.

It won't work in all cases :) IIRC Idris will move type info to runtime if it can't prove it at compile time. Basically, in Idris I can have a function concat which takes a Vector , a Vector , and produces a Vector . You can have arbitrary expressions there, and even things like a function which returns a different type based on its boolean argument. So most signatures will just carry dependencies through, but some t…

> I'm not sure how much better it does than a good optimizing compiler. It can be done by static analysis by compilers in other languages also. Knowing size at compile time is easy most of the time and we are not talking at all about this case. Your answer that Idris solves that is wrong in the context that this discussion started (dynamically allocated memory/not knowing the size compile time). You still need to tra…

Yes, it can be done by static analysis, but by making size dependencies part of the API it makes the static analysis much easier and able to cross API boundaries without needing to inline, on the contrary most optimizers will not handle such invariants across a few layers of function calls. Like I said, Idris doesn't solve this problem completely, but it is able to eliminate bounds checks in way more situations because the default is effectively no bounds checking.

The nice thing about dependent types is that in all the cases where you don't need a bounds check -- where a program invariant enforces that you are within bounds -- your code will not contain a bounds check regardless of optimization. Only in the cases where there are runtime dependencies that can't be resolved will there be issues, and in thee cases you need a bounds check anyway.

It's not perfect/complete, and like I said optimizers can get most of the way there anyway. I just wanted to note that there are better solutions for bounds checking.

Re: Getting Past C

#230
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…

> 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? The CVE database. Just because you 'can' write such an array implementation doesn't mean you will, doesn't mean your third party libs will, doesn't mean any of your legacy code uses it, and certainly doesn't mean…

Honestly, we need a few AI coders to replace most of the developers in the world and then this won't be an issue. Bounds checking arrays and calloc instead of malloc isn't rocket science. It's a simple formula.

The problem isn't the language it's the developers.

Post reply on HN