Live data from Hacker News

Everything in C is undefined behavior

blog.habets.se

171–180 of 748 posts

Re: Everything in C is undefined behavior

#171
post #15

> A problem with this is that in order to confirm the findings, you’ll need an expert human. But generally expert humans are busy doing other things. The article suggests using LLMs to identify and fix UB. However as per the above, I think the issue is that we need more expert humans. LLM generated code will eventually contain UB. EDIT: added "eventually"

Author here.

> The article suggests using LLMs to identify and fix UB. However as per the above, I think the issue is that we need more expert humans.

Yup. But the point of the article is that even expert humans cannot do this alone. And as I wrote, LLM+junior won't suffice either. We need LLM+senior experts.

And it's a problem that we have way more existing UB than expert capacity.

Now, will LLMs and experts both miss UB in some cases? Of course. There's no 100% solution. But LLMs, I claim, will find orders of magnitude more, with low false positive, than any expert. Even if these expert humans (like in the OpenBSD case for the two bugs I found, one of which was UB) are given more than three decades to do it.

I didn't even use the best model, complex code target, or time. I just wanted to choose a target that has a high chance of having very good experts already having audited it.

Re: Everything in C is undefined behavior

#172
post #8

The problem of UB is not really that it may crash in some architecture. The real problem is that the compiler expects UB code to NOT happen, so if you write UB code anyway the compiler (and especially the optimizer) is allowed to translate that to anything that's convenient for its happy path. And sometimes that "anything" can be really unexpected (like removing big chunks of code).

Removing code paths that the programmer has explicitly laid out in the source code should be made a hard compile error unless the operation has been tagged with an attribute (anyone who wants to add the unsafe keyword to C? ). Another commenter suggested using LLMs, but I disagree. Having clangd emit warning squiggles for unchecked operations (like signed addition) would be a good start.

Consider:

   enum op_t{ add, mul };
   int exec(op_t op, int a, int b) {
       if(op == add) { return a+b; }
       if(op == mul) { return a\*b; }
   }

   c = exec(add, a,b);
Should be the compiler be prevented from inlining exec and constant-propagating op and removing the mul branch? What about if a and b are constants and the addition itself is optimized away?

Re: Everything in C is undefined behavior

#173

Earlier quoted context omitted.

One example along this path as an example is that every function must either terminate or have a side effect. I don't think one has bitten me yet but I could completely see how you accidentally write some kind of infinite loop or recursion and the function gets deleted. Also, bonus points for tail recursion so this bug might only show up with a higher optimization level if during debug nothing hit the infinite loop.

Infinite loop without side effects == program stuck and not responding on user input and not outputting anything. That's not something a useful program will ever want to do.

The problem is when you accidentally write an infinite loop. In a different language, you run the code, see that it gets stuck and fix it. In C, the compiler may delete the function, making it hard to realize what is happening.

Re: Everything in C is undefined behavior

#174
post #22

Earlier quoted context omitted.

Notice though "ignoring the situation" thru "documented manner characteristic of the environment". Even though truly you can read this in an uncharitable way, you could also try and understand the intent of this paragraph, and I think reading it for its intents is always the best way to interpret a language standard when the wording is ambiguous or soft, especially if you're writing a compiler. I don't think you coul…

Ex falso quodlibet. Bounding UB would be a nice idea, or at least prohibiting time-traveling UB (and there is an effort in that direction). But properly specifing it is actually hard.

Prohibiting "time-travelling" UB would be horrible as that's a very important mechanism for dead code elimination.

Re: Everything in C is undefined behavior

#175

Earlier quoted context omitted.

One example along this path as an example is that every function must either terminate or have a side effect. I don't think one has bitten me yet but I could completely see how you accidentally write some kind of infinite loop or recursion and the function gets deleted. Also, bonus points for tail recursion so this bug might only show up with a higher optimization level if during debug nothing hit the infinite loop.

Infinite loop without side effects == program stuck and not responding on user input and not outputting anything. That's not something a useful program will ever want to do.

Not true, C++ made it so trivial infinite loops are not UB because it turns out they do have legitimate uses.

https://lists.isocpp.org/std-proposals/2020/05/1322.php

https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p28...

Re: Everything in C is undefined behavior

#176
post #108
post #89

Earlier quoted context omitted.

The easy cases like you cite are also those that don’t cause problems in practice. I’m not sure that would help all that much, other than to slightly reduce internet criticism.

Fixing easy cases makes the list shorter, so enables more focus on harder cases. And it also signals that you actually do want to improve, just a little bit of boy scout rule goes a long way.

The issue is that the list is infinite (anything not specified is UB), so actually removing any finite amount of UB from the list won't make it shorter.

(only slightly tongue-in-cheek, I do believe that removing silly things is worthwhile).

Re: Everything in C is undefined behavior

#177
post #80
post #54

Earlier quoted context omitted.

Reading for intent is pragmatic. Reading adversarially is what people do who are looking for ways that something can be abused, from an offensive or defensive position. Personally I am tired of the entire topic.

What's bad is when your compiler writers and most of the people involved in standardisation are reading it adversarially.

It's bad when compiler writers want to optimize correct code as much as possible, which is something their actual customers keep asking for?

Re: Everything in C is undefined behavior

#178

> The compiler, and really the underlying hardware too, is playing a game of telephone with your UB intentions. The part about hardware is wrong BTW. In all the cases about null pointers and out-of-bounds access and integer overflow and whatnot, the hardware semantics are clearly defined, and the assembler code does exactly what is written. The way modern compilers act on your code makes C less safe than assembler in…

Author here

> The part about hardware is wrong BTW

Could you be more specific? I think by "wrong" you may mean "not actually relevant to UB", and you're right about that. If that's what you mean then that part is not for you. It's for the "but it's demonstrably fine" crowd.

> the hardware semantics are clearly defined

Yup. The article means to dive from the C abstract machine to illustrate how your defined intentions (in your head), written as UB C, get translated into defined hardware behavior that you did not intend.

I'm not saying the CPU has UB, and I wonder what part made you think I did.

That's what I mean game of telephone. The UB parts get interpreted as real instructions by the hardware, and it will definitely do those things. But what are those things? It's not the things you intended, and any "common sense" reading of the C code is irrelevant, because the C representation of your intentions were UB.

Re: Everything in C is undefined behavior

#179

I have never in my 20 years of writing C heard so much about undefined behavior as I have in the past 6 months on Hacker News. It has never entered the conversation. You write the code. If it doesn't work, you debug it and apply a fix or a workaround. Why does the idea of undefined behavior in C get to the front page so consistently?

I would guess that the continued success of Rust have shown that we don’t have to live with the user-hostility of C in order to write system programs. Therefore, people are understandably growing less and less patient with C and its unending bullshit.

Although I haven’t noticed a spike the last 6 months, just a slowly increasing realization that C isn’t fit for humans and should go the way of asbest: Don’t use it for anything new, and remove it where it already exists, unless doing so would be too expensive or disruptive.

Re: Everything in C is undefined behavior

#180

Earlier quoted context omitted.

One example along this path as an example is that every function must either terminate or have a side effect. I don't think one has bitten me yet but I could completely see how you accidentally write some kind of infinite loop or recursion and the function gets deleted. Also, bonus points for tail recursion so this bug might only show up with a higher optimization level if during debug nothing hit the infinite loop.

Infinite loop without side effects == program stuck and not responding on user input and not outputting anything. That's not something a useful program will ever want to do.

https://9p.io/sources/plan9/sys/src/libc/9sys/abort.c
Post reply on HN