10 ms·
There are many good "better C" alternatives already. Rust, zig, D. They address other common types of bug like resource leaks, overflows, use after free. If you
by colonwqbang 2y ago
There are many good "better C" alternatives already. Rust, zig, D. They address other common types of bug like resource leaks, overflows, use after free. If you're ok with rewriting code, you have terrific options.
And of course there is C++, the most famous attempt to fix C in a somewhat compatible way by adding more features. It is debatable whether this effort resulted in a better language. C++ has all the bits needed to check array bounds by default but chooses not to do so...
The problem is that the huge existing stock of C code is written in C and not rust, zig, D, etc. The same would be true for your proposed "better C" language and any other incompatible iteration of C.
If you can come up with a way to add these guarantees to C without needing significant rewriting, I can assure you that most C programmers would be very interested.
- lisper 2y ago> There are many good "better C" alternatives already. Rust, zig, D. All of these are very different from C. What I'm proposing is just one small change to the existing C language. > If you can come up with a way to add these guarantees to C without needing significant rewriting, I can assure you that most C programmers would be very interested. I can pretty much guarantee that they would not because this is easy: phase in the changes. Start by turning array-pointer conflation into a mandatory warning rather than undefined behavior or whatever it is now. Then wait a few years. Then turn it into an error that you can muffle using -C2024 or whatever. I actually don't know whether array-pointer conflation is required by the standard or if it's undefined behavior (I'm pretty sure it's one or the other). But if it's the latter then you don't actually have to change the standard to make this happen, all you need to do is write a compiler that does the Right Thing. AFAIK no such compiler exists. But there is just no excuse for this: % gcc -v Apple clang version 14.0.0 (clang-1400.0.29.202) ... % more test.c int main () { int x[10]; return *(x+20); } % gcc -Wall test.c %
- retrac 2y agoIn assembly, arrays and structs reduce to base address, plus offset times scaling factor. C provides a thin veneer over that. Scaling derived from size of type. Offset is the array index. The basic programming model of C is to view memory as an array.
- lisper 2y agoYes, I understand that. But the topic at hand is a compiler whose "intended use is the compilation of life-critical and mission-critical software written in C". The idea of using C in life-critical and mission-critical software is risible as long as the language definition requires it to have gaping security holes, especially when the single biggest contributor to this problem is fairly easy to fix, at least from a technological point of view if not a political and sociological one.
- nequo 2y agoMy understanding is that the primary purpose of CompCert is to make formally verified code that is extracted into C also get compiled by a compiler that is formally verified to preserve the intended semantics. So CompCert seems to me to aim to help mission-critical software to move away from C, and possibly into Coq/Isabelle/etc., except for the purposes of compilation to machine code.
- lisper 2y agoThat is a noble goal, but I don't see how it can possibly achieve the intended result as long as the C standard is a fundamentally borken as it is. I tried to download CompCert so I could try it out, but they only have a source distribution and to build it you need Coq and OCaml and a few other things because of course CompCert is not written in C. No one in their right mind would write mission-critical software in C.
- seabird 2y agoIf your original source is provably transpilable to C with no UB, and your compiler provably compiles that C without any bungling, then you've made it. The standard is bad and I want to see the end of C before I'm dead, but this isn't a stretch, and C is just a detail in the process.
- LeFantome 2y agoI am mostly in the other side of this argument. C is an insane language in my view ( in a modern context ). That said, what “mission critical software” are you using that is not running on an OS written in C?
- rfoo 2y agoThere are more than one billion lines of C code which hasn't been updated in the last decade and is still in use. Who is going to update these code once the "do the right thing"-compiler become available? Oh, and the worst part: some of them may already be bug-free due to 15 years (if not more) of people trying to make money by selling exploits to surveillance vendors or who knows. But there's certainly high-impact bugs left. Now what, refactor the code to use the fancy eliminate-spatial-memory-corruption C variant and introduce a few UAF by the way?
- lisper 2y agoThe authors and maintainers of that code. Any error or warning flagged by this change is something that really ought to be changed anyway because any unchecked array or pointer dereference is a potential security risk.
- rfoo 2y agoHave you read the source code of Xpdf (the thing being exploited in the famous NSO Apple iMessage 0-click blah blah)? I did (because I wrote an exploit for the bug after the Google blogpost, for curiosity), the code looks disgusting. The author (one poor guy) does not have the code in an online VCS and instead dump a source tarball every few months (or years). The upstream vulnerable code was fixed months after news outbreak. My conclusion is if Apple had a choice it won't end up in iOS at all. Clearly, Apple already paid a lot of maintaining cost in this case (fixing bugs before upstream did), but what you asked for is a whole new level.
- LukeShu 2y agoThere is a well-maintained in-VCS less-disgusting version of Xpdf. It's called Poppler, and Apple chooses to not use it.
- deleted 2y ago[deleted]
- 2y ago
- pyrolistical 2y agoYou should take a closer look at zig. While superficially the syntax is very different, what zig really is, c but more specific
- lisper 2y agoNo, I get that. I was referring to the syntax. Syntax matters. Zig is hands-down a better language than C, and (I'll take your word that) it fills the same niche as C, but it is still a different language with its own idioms and lore and conventions. It is not C-with-tweaks. It cannot be compiled by an extant C compiler. Code written under my proposal would be legal C code under the current standard (but not the other way around). [EDIT] Actually, that turns out not to be true. You'd need to change the behavior of SIZEOF or provide some other way of getting the size of dynamically allocated arrays at run time, since this information would now be maintained by the compiler.
- unwind 2y agoOf course sizeof already has that capability since C has variable length arrays. They are kind of being phased out, but they are there. You can do this: #include <stdio.h> int main(int argc, char *argv[]) { unsigned int lens[argc]; for (int i = 0; i < argc; ++i) lens[i] = (int) strlen(argv[i]); printf("Computed %d lens into %zu bytes of array\n", argc, sizeof lens); return 0; } Very contrived pointless example, but still.
- flohofwoe 2y ago> All of these are very different from C. With the changes you have in mind, that new "C+" would be much closer to Zig than C. For a backward compatible bounds-checking proposal see: https://discourse.llvm.org/t/rfc-enforcing-bounds-safety-in-c-fbounds-safety/70854 https://discourse.llvm.org/t/rfc-enforcing-bounds-safety-in-... This basically just associates a pointer and a length via new (and optional) annotations.
- pjmlp 2y agoThat is what Microsoft is already doing since the Windows XP SP2 security task force, Apple came a bit late into the game. The void foo(int *__counted_by(N) ptr, size_t N); with SAL void foo(_In_reads_bytes_(N) int *ptr, size_t N); https://learn.microsoft.com/en-us/cpp/code-quality/understanding-sal?view=msvc-170 https://learn.microsoft.com/en-us/cpp/code-quality/understan... But given how much long time ago XP SP 2 was, and how many people actually use them, unless forced at their job, that is quite telling how much people care.
- Gibbon1 2y agoWhat bothers me is a function that takes both a ptr and a length is taking a phat pointer. What feels bad is you could add standard phat_ptr_t to the C library. But they refuse to do even that.
- flohofwoe 2y agoSuch a bounds-checking language extension needs to be able to annotate existing libraries without changing their API, otherwise it's not all that useful.
- flohofwoe 2y agoPS (too late for edit so I'm replying to myself): with the above Clang extension you can also define your own phat_ptr_t struct and still associate the length with the pointer. Not sure if that's also possible with the Microsoft extension, for instance this is copied from the proposal text: typedef struct { int *__counted_by(count) buf; size_t count; } sized_buf_t;
- colonwqbang 2y agoYou are just not using the correct compiler flags. Compile with gcc -O2 -Wall -Werror, and you will see that GCC rejects this program due to the out of bounds condition. No need to trash talk GCC when it already does what you want it to.
- lisper 2y agoI'm actually running clang (look at the second line of the transcript). I just invoke it with gcc out of thirty years of habit.
- colonwqbang 2y agoI see! For recent clang, the flag -Warray-bounds-pointer-arithmetic did the same thing for me. So if missing bounds checking for static arrays was your main gripe with C, you can rejoice.
- balnaphone 2y agoPerhaps that is inexcusable. GNU gcc version 13.2.0 (with -O2, as documented) does report a problem. $ cat tst.c int main () { int x[10]; return *(x+20); } $ gcc -Wall -O2 tst.c tst.c: In function ‘main’: tst.c:3:10: warning: array subscript 20 is outside array bounds of ‘int[10]’ [-Warray-bounds=] 3 | return *(x+20); | ^~~~~~~ tst.c:2:7: note: at offset 80 into object ‘x’ of size 40 2 | int x[10]; | ^
- HelloNurse 2y agoThese are easy mode arrays, with size and offset known at compile time. Receiving x as an int* parameter to a function, with no way to know its length automatically, would be more realistic.
- admax88qqq 2y ago> huge existing stock of C code I feel like the amount of effort that has been spent so far to make C safe and fix bugs due to C not being safe is greater than the effort that would have been required to rewrite all existing C code into memory safe languages. But I think secretly C programmers don't want memory safety. Dealing with pointers and remembering to malloc and free are part of what makes them feel more skilled/elite than those other programmers who have garbage collection and bounds checking.
- rfoo 2y agoThe problem here is people seldomly get paid rewriting existing C code into memory safe lamguages. While once in a while someone would be annoyed enough and pay for a fixing-C effort for a little. Do you have suggestions on how to fix the incentive?
- admax88qqq 2y agoI don't think that's the root problem. I think C programmers don't believe C is a problem. New software is started every day on C. There's no excuse for that and no financial incentive to do it. If the engineers actually admitted that C is not a safe languages for shipping software, then we could at the very least freeze the existing code and write everything _new_ in a same language. But we don't. Engineers still go starting brand new greenfield projects in C which is just insane.
- optymizer 2y agoJust because you don't understand it, doesn't mean it's insane. It just means that your view of the world is different from others.
- rfoo 2y ago> then we could at the very least freeze the existing code and write everything _new_ in a same language Sure, if you are willing to help, here's my wishlist: - I wish we can freeze libssh and write everything new in Rust. - I wish we can freeze CPython and write everything new in Rust. - ... Can you do it for free? At work I'm busy maintaining old projects in C++ and writing new ones in Rust. Since I'm not getting paid to rewrite or maintain our dependencies full-time I can't do above. Oh, I'm not paid to initiate an effort to freeze our old projects either. If this sounds too harsh: - I wish we can freeze ZMK [1] and write everything new in Rust (or Zig, though it's not memory safe, whatever). That's about one of my hobbies and I always wanted to do it. [1] https://github.com/zmkfirmware/zmk https://github.com/zmkfirmware/zmk
- riku_iki 2y ago> C++ has all the bits needed to check array bounds by default but chooses not to do so... std::array::at does bound check.
- grumpyprole 2y agoYes, but they've made the convenient lightweight syntax not bounds check. Defaults matter in languages. Other languages make you use an esoteric function e.g at_unsafe to skip bounds checking.
- riku_iki 2y agoits probably because per contract std::array has to behave exactly like C array for legacy ops. Also this is not zero cost abstraction, so programmer has a choice: ultimate performance or extra safety.
- pjmlp 2y agoWhile a bummer, most C++ compilers do have a build flag to enable bounds check in operator[](). Which most sane compilers will do for you in debug builds.
- retrac 2y ago* = [] and friends can be overloaded in C++. So just about any kind of data structure can masquerade as items[3] or *value. Opinions differ on whether this is the great strength or fatal flaw in C++.
- colonwqbang 2y agoAdding a special function for safe indexing doesn't really count, we can do that in C too. "By default" means the most natural and common way to index an array, namely the [] syntax.
- riku_iki 2y ago> "By default" means the most natural and common way to index an array, namely the [] syntax. Sorry, I challenge your authority to decide what is "most natural way".