Live data from Hacker News

Getting Past C

blog.ntpsec.org

231–240 of 504 posts

Re: Getting Past C

#231

Earlier quoted context omitted.

> 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.

Considering that a change in language completely solves the problem, it's hard to get on board with your thesis.

Re: Getting Past C

#232
post #170

Earlier quoted context omitted.

If you're relying on any random third-party Rust crates you haven't audited yourself, don't you lose the safety guarantee? A given crate might turn out to have implemented operations on some data-structure using unsafe blocks, and then to have failed to mark its own API functions as unsafe in turn (like the Rust stdlib does, but without the "extensive manual auditing" that the stdlib gets). AFAIK, cargo doesn't have…

There's a lot more unsafe code in Rust crates than there should be. That's a fixable problem. Some stuff from the early days predates the optimizer getting smart enough that unsafe code isn't needed. I wrote on this a few days ago in a Rust topic.

While I now mostly agree with you that there is more unsafe code than there should be, I still maintain that the frequency of unsafe in a deptree is usually still small enough to be practically auditable, ignoring FFI. It could/should be much less, but it's not too bad. I've done such audits a few times and it's not been too hard and taken very little time.

Auditing FFI is a whole other challenge, however :(

Re: Getting Past C

#233

Earlier quoted context omitted.

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.

I mean, in case of an abort the kernel generally cleans things up for you :) Not all things, but most things.

More exotic panics (like an infinite loop panic on a microcontroller) would not call destructors though.

Most panic impls will either unwind (which will call destructors) or abort/exit, so this is usually not a problem.

Re: Getting Past C

#234

Earlier quoted context omitted.

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.

Considering that a change in language completely solves the problem, it's hard to get on board with your thesis.

My point is, a lot of people are spending time on this when it doesn't matter. In the limit that AI starts replacing human developers these subtle differences in language approaches zero.

New languages here and there every day. Replace this replace that. When, in the end everyone is simply reinventing the "wheel" over-and-over.

All these languages end up as assembly.

Re: Getting Past C

#235

Earlier quoted context omitted.

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.

I mean, in case of an abort the kernel generally cleans things up for you :) Not all things, but most things. More exotic panics (like an infinite loop panic on a microcontroller) would not call destructors though. Most panic impls will either unwind (which will call destructors) or abort/exit, so this is usually not a problem.

Memory will get cleaned up, but your destructors aren't gonna get called.

Re: Getting Past C

#236
post #140

Earlier quoted context omitted.

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.

They don't, sizeof is a compile-time constant. On a pointer, sizeof() just reports the size of the pointer itself (i.e. 4 or 8 bytes on most modern platforms), not the size of the data to which it points (and sizeof(*pointer) reports the size of the type to which pointer points, it doesn't know anything about how many values of that type are stored). For an array, the length is known statically (i.e. it's in the type), and so the computation can be done at compile time.

Re: Getting Past C

#237

Earlier quoted context omitted.

It's crazy that it's not solved above the language level, if people really want zero cost abstraction and architecture friendliness at least tooling should check buffer logic and flag the binary in case Warnings have been ignored.

>if people really want zero cost abstraction That one "if" is (by definition) not zero-cost.

It is by definition a "zero-cost abstraction." Let's ask Stroustrup, who coined the term:

> C++ implementations obey the zero-overhead principle: What you don’t use, you don’t pay for. And further: What you do use, you couldn’t hand code any better.

Two points:

What you don't use, you don't pay for: if you don't use array indexing, you won't get a bounds check. In addition, you can call an access method without a bounds check as well, so it truly is only if you use the checked version.

What you do use, you couldn't hand-code any better: that bounds check is written the exact same way you'd write it in C.

Therefore, this is a zero-cost abstraction.

Re: Getting Past C

#238

I wish more mention of D would happen. It is compatible with C and C++ libraries and features GC without sacrificing the good things of C and C++. I always loved the idea of Rust and Go but they are nowhere near C or C++ where it matters to me. D fits the bill, otherwise I just use Python. I like being able to design software in my own way as opposed to being told how to do it.

The truth is the Rust leadership did the hard work of building a community around the language, making high-quality tutorials and introductions to the language all before it stabilized for 1.0. Many developers claim to dislike "marketing", but Rust did its marketing/evangelism and D didn't. From a purely technical standpoint, Rust's borrow checker is able to catch data races, while D has no such functionality (unless…

Even in single-threaded mode D isn't too safe. Safer than C, but unless you're using the GC it is still unsafe.

Re: Getting Past C

#239

Earlier quoted context omitted.

> 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.

> I am still perplexed why you think by using a dynamic array of chars for a buffer

Because I'm not limiting the case to just core types. You don't only ever need arrays of chars, ints, doubles, floats, etc. Sometimes you need arrays of structs.

As a simplistic example, perhaps you have a large array of structs, and you want to iterate through them and add all the items that match your criteria to a shorter array of matches, which will be pointers to the real data. Adding a single item to the original array could cause realloc to invalidate every pointer in the array of matches. Of course there are ways around this, but someone starting work on the code might not necessarily expect that adding an item to an array would cause pointers elsewhere in the code to become invalid, unless they look at the implementation of your array code to understand what it's doing.

Re: Getting Past C

#240
post #236

Earlier quoted context omitted.

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.

They don't, sizeof is a compile-time constant. On a pointer, sizeof() just reports the size of the pointer itself (i.e. 4 or 8 bytes on most modern platforms), not the size of the data to which it points (and sizeof(*pointer) reports the size of the type to which pointer points, it doesn't know anything about how many values of that type are stored). For an array, the length is known statically (i.e. it's in the type…

And this is such a misconception that it's often cited as a footgun: http://www.cplusplus.com/faq/sequences/arrays/sizeof-array/

> A beginner will often try something along the lines of size = sizeof( myarray ) (which is incorrect).

Post reply on HN