The best way to deal with this kind of thing is to write a small language that transpiles to the subset of c that you are using.
Neverflow: C macros that guard against buffer overflows
81–90 of 150 posts
Re: Neverflow: C macros that guard against buffer overflows
#82Why 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.
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
#83Re: Neverflow: C macros that guard against buffer overflows
#84The 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…
Is there a library that you recommend for this?
Re: Neverflow: C macros that guard against buffer overflows
#85Modern C (2019) - https://news.ycombinator.com/item?id=36167820 - June 2023 (19 comments)
Re: Neverflow: C macros that guard against buffer overflows
#86#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
#87Earlier 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:…
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
#88Earlier 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.
Re: Neverflow: C macros that guard against buffer overflows
#89Earlier 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.
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
#90The 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…
I'm really glad that C doesn't do this, personally. It would reduce one of the main advantages of the language.