Live data from Hacker News

Neverflow: C macros that guard against buffer overflows

github.com

81–90 of 150 posts

Re: Neverflow: C macros that guard against buffer overflows

#82

Why use C and keep reinventing things that C++ provides?

But this isn't something the C++ language provides, which is hilarious. C++ keeps C's crap array type as its native array type. You need to reach into the C++ standard library to get this awkward library type, std::array and then finally you get an array type that remembers how big it is and has some basic features like swap.

>"std::array"

Unless you mean array of anything like in typeless dynamic languages I do not see anything awkward about STL arrays in C++.

Re: Neverflow: C macros that guard against buffer overflows

#83
post #63

Earlier quoted context omitted.

Did you mean to reply somewhere else? This thread is about about bounds checking arrays in the C programming language.

You definitly didn't understood the message.

If you did understood it, then explain it so I can understood it too.

Re: Neverflow: C macros that guard against buffer overflows

#84
post #8

The problem with C and buffer overflows isn't that you can't guard against them, or that there is no existing, reusable code to do so — it's that none of this functionality is standardized. Adding another one to the existing 41383 ways of doing this is in fact the exact opposite of what's needed. Ideally C needs one way of doing this, and that would be described in the standard. But that's not how C "rolls", and we'l…

> existing, reusable code to do so

Is there a library that you recommend for this?

Re: Neverflow: C macros that guard against buffer overflows

#86
The following error prone: it can be mistakenly applied to a pointer:

#define LEN(NAME) (sizeof NAME / sizeof(NAME)[0])

I think gcc has a warning for this pattern now: when the size of a pointer is divided by the size of its referent type.

More importantly, it has an odd extra level of indirection. The traditional definition is:

#define LEN(ARRAY) (sizeof ARRAY / sizeof (ARRAY)[0])

This means that to use LEN on an array, we have to take the address:

   char *array[5];
   LEN(&array);  // -> 5
If we use

   LEN(array);
which is an easy mistake, we get:

    sizeof *array / sizeof (*array)[0]
which is

    sizeof (char *) / sizeof (char)
which is

    sizeof (char *)
which is likely 4 or 8.

I do see that LEN is supposed to be (only) used in conjunction with ARR:

    #define ARR(TYPE, NAME, COUNT) TYPE(*NAME)[COUNT]
but that isn't enforced. An idea would be to add some "secret" prefix or suffix to NAME like blah_ ## NAME, so that name cannot be referenced without going through the macros; i.e. if we define ARR(int, foo, 42) then there is no declared identifier foo; it actually declares blah_foo, and LEN(foo) knows about that, also adding the prefix. Thus mistakenly using LEN(foo) on something not declared with ARR will likely be a reference to an undeclared identifier.

Re: Neverflow: C macros that guard against buffer overflows

#87
post #61

Earlier quoted context omitted.

True, but it also adds lot of features that help to easily migrate to saner features without rewriting the world and throw away 30 years of tooling. Microsoft security team is on the record that just because they are adopting Rust, they won't shy away from C++.

I'm kind of on board with this, but the problem is that it's 30 years of rotten wood. Rust started from a more secure foundation and has put a lot of effort into stabilising even the trickier ground - whereas in C++ it's too often "Yeah, we don't think about it too hard, when there are strong winds I don't go up into the top floor, the creaking is very loud, I'd rather just never find out". Example, Rust 1.0 had std:…

Sometimes it is better to have rotten wood to build something than nothing at all.

If we want to encourage Rust adoption, it is by having a middle path, not via Rust Advocacy Strike Force.

That only shuts the audience off, specially when Rust has a glass ceiling of depending on C++ infrastructure for its reference compilers.

Re: Neverflow: C macros that guard against buffer overflows

#88
post #67

Earlier quoted context omitted.

Those are syntactic sugar for the same thing though. Array[5] is just shorthand for *(Array + 5), which is why 5[Array] also works (because addition is commutative). Note that C does have strong conventions, such as that strings are terminated by a zero byte. Nothing in the language demands that, it’s just a convention! C could adopt better conventions.

Many of the str functions in the C standard library assume a nul terminator.

Yes, but aside from string literals pointed out by a sibling comment, nothing in the language itself dictates this convention. The C library could be augmented with functions which expect strings structured in other ways.

Re: Neverflow: C macros that guard against buffer overflows

#89

Earlier quoted context omitted.

Those are syntactic sugar for the same thing though. Array[5] is just shorthand for *(Array + 5), which is why 5[Array] also works (because addition is commutative). Note that C does have strong conventions, such as that strings are terminated by a zero byte. Nothing in the language demands that, it’s just a convention! C could adopt better conventions.

> Note that C does have strong conventions, such as that strings are terminated by a zero byte Stated the same on HN earlier, but someone pointed out that literal strings are ASCIIZ.

One common trick in safer C libraries is to encode the length of the string one word prior to the beginning of the string. So "hello world" in memory would be

11 'h' 'e' 'l' 'l' 'o' ' ' 'w' 'o' 'r' 'l' 'd' '\0'

ptr ^

C could be upgraded to do this in future versions, without too much backwards incompatibility.

Re: Neverflow: C macros that guard against buffer overflows

#90
post #8

The problem with C and buffer overflows isn't that you can't guard against them, or that there is no existing, reusable code to do so — it's that none of this functionality is standardized. Adding another one to the existing 41383 ways of doing this is in fact the exact opposite of what's needed. Ideally C needs one way of doing this, and that would be described in the standard. But that's not how C "rolls", and we'l…

> Ideally C needs one way of doing this, and that would be described in the standard.

I'm really glad that C doesn't do this, personally. It would reduce one of the main advantages of the language.

Post reply on HN