Live data from Hacker News

Improvements to static analysis in GCC 14

developers.redhat.com

131–140 of 147 posts

Re: Improvements to static analysis in GCC 14

#131
post #7
post #2

Very cool stuff! I haven't done much C development lately, so I'm curious how often `strcpy` and `strcat` are used. Last I checked they're almost as big no-nos as using goto. (Yes, I know goto is often preferred in kernel dev...) Can anyone share on how helpful the c-string analyses are to them?

Some usage of goto is still idiomatic in C if used in ways logically equivalent to structured programming constructs C lacks. It requires some care, but I mean, it's C. (I'm not however fond at all of longjmp)

> (I'm not however fond at all of longjmp)

I don't think there is any justifiable reason to use setjmp/longjmp in modern C code. At best it's a crude imitation of throw/catch semantics; if you really want that, C++ has a real implementation.

Re: Improvements to static analysis in GCC 14

#132
post #122

Earlier quoted context omitted.

> People have done it, there are plenty strbuf implementations to go around. Precisely! Why plenty and why is none of them the standard in C?

The TL;DR on that is basically "lazy, security unconscious assholes keep shutting it down". Dennies Ritchie strongly suggested C should add fat pointers all the way back in 1990. Other people have pointed out the issues with zero terminated strings and arrays decaying into pointers (and the ways to deal with them even with backwards compatibility constraints) for years. One of the most prominent was Walter Bright's a…

It is easy to document mistakes in hindsight, since hindsight is 20/20.

It is very easy to write your own one-off secure string handling library. This is a common assignment in intro to C programming classes.

So why isn't it standard in C already?

You offer a theory that there is a gang of "security unconscious assholes [who] keep shutting it down". This gang is so well organized that they have managed to block an easy improvement for many many decades for unknown reasons. That's a pretty wild theory.

Or Occam's razor suggests a different answer: It's actually difficult.

No, not the writing code part, that's easy. It's the seamlessly integrating with ~60 years of mission critical codebases part that's hard.

Re: Improvements to static analysis in GCC 14

#133

Earlier quoted context omitted.

> you should only worry about it at the boundary with the other library. If this was a mitigation, it would solve all problems with nul-terminated strings i.e. do strict and error-checked conversions to nul-terminated strings at all boundaries to the program, and then nul-terminated strings and len-specified strings are equivalently dangerous (or safe, depending on your perspective). The problem is precisely that uns…

It's impossible to avoid "sanitizing" input if you have a conversion step from a library provided char* to a strbuf type. Any use of the strbuf API is guaranteed to be correct. That's very different from needing to be on your toes with every usage of the strxcpy family.

> It's impossible to avoid "sanitizing" input if you have a conversion step from a library provided char* to a strbuf type. Any use of the strbuf API is guaranteed to be correct.

I agree: having a datatype beats sanitising input (I think there's a popular essay somewhere about parsing input vs sanitising input which makes pretty much the same point as you do), but it's still only partially correct.

To get to fully correct you don't need a new string type, you need developers to recognise that the fields "Full Name" and "Email address" and "Phone number", while all being stored as strings, are actually different types and to handle them as such by making those types incompatible so that a `string_copy` function must produce a compilation failure when the destination is "EmailAddressType" and the source is "FullNameType".

Developers in C can, right now, do that with only a few minutes of extra typing effort. Adding a "proper" string type is still going to result in someone, somewhere, parsing a uint8_t from a string into a uint64_t, and then (after some computation) reversing that (now overflowing) uint64_t back into a uint8_t.

If you're doing the right thing and creating types because "Parse, Don't Validate", a better string type doesn't bring any benefits. If you're doing the wrong thing and validating inputs, then you're going to miss one anyway, no matter the underlying string type.

Re: Improvements to static analysis in GCC 14

#134

Earlier quoted context omitted.

> Languages other than C give you options for flow control so that you don't need goto for that. The idiom `if (error) goto cleanup` is about the only thing I see goto used for. What flow control replaces that other than exceptions?

Jumping out of nested loops. Implementing higher level constructs like yield or defer. State machines. Compiler output that uses C as a "cross-platform" assembly language. All of them are better served with more specialized language constructs but as a widely applicable hammer goto is pretty nice. I don't expect C to have good error handling or generators any time soon but with goto I can deal with it.

I'm actually familiar with this, having used libprotothreads in production for about 4 years.

Something like libprotothreads can't actually be implemented in a language that doesn't have gotos, so yeah, I see the need for it.

Re: Improvements to static analysis in GCC 14

#135

if (nbytes The fix that was done was: if (nbytes > sizeof(*hwrpb)) But I think the correct fix is: if (copy_to_user(buffer, hwrpb, sizeof(*hwrpb)) != 0) It never makes sense to copy out of the hwrpb pointer any size other than sizeof(*hwrpb).

If the caller has nbytes = 4

and sizeof(hwrpb) is now 16 bytes, then you will be copying 12 bytes of data too many from the caller, potentially reading into memory it doesn't own. I would say that should be avoided.

The better solution I believe would be to only copy the minimum amount of bytes supported by caller & callee. So:

nbytes = MIN(nbytes, sizeof(hwrpb));

Which should ensure backwards and forwards compatibility, assuming the version info of hwrpb->size is respected then the fact that part of the hwrpb struct isn't initialized shouldn't matter.

Re: Improvements to static analysis in GCC 14

#136
post #132

Earlier quoted context omitted.

The TL;DR on that is basically "lazy, security unconscious assholes keep shutting it down". Dennies Ritchie strongly suggested C should add fat pointers all the way back in 1990. Other people have pointed out the issues with zero terminated strings and arrays decaying into pointers (and the ways to deal with them even with backwards compatibility constraints) for years. One of the most prominent was Walter Bright's a…

It is easy to document mistakes in hindsight, since hindsight is 20/20. It is very easy to write your own one-off secure string handling library. This is a common assignment in intro to C programming classes. So why isn't it standard in C already? You offer a theory that there is a gang of "security unconscious assholes [who] keep shutting it down". This gang is so well organized that they have managed to block an ea…

There's no need to integrate with 60 years of mission critical codebases, you're making up a problem in your head that doesn't exist.

Nothing needs to be fixed, all it takes is to stop doing the stupid thing.

It does not take a "coordinated gang" to shut down C standard proposals, them getting shut down is the default.

You seem to be neither familiar with the nature of the problem or the struggle that is getting anything passed through ISO standardization. I don't mean to belittle you by saying this, I just hope to make you understand that you are assuming things that are simply not based in reality.

It doesn't even need to be in the standard btw. Just write your own. It's a few lines of code. As you say, a beginner exercise. Yet there is code written after the year 2000 that still uses the strxcpy family. Long after the issues have been known and what the solution is.

"Backwards compatibility" is a total red herring. C++ has the solution right there in its standard library. A backwards compatible string buffer implementation.

Re: Improvements to static analysis in GCC 14

#137

Earlier quoted context omitted.

It's impossible to avoid "sanitizing" input if you have a conversion step from a library provided char* to a strbuf type. Any use of the strbuf API is guaranteed to be correct. That's very different from needing to be on your toes with every usage of the strxcpy family.

> It's impossible to avoid "sanitizing" input if you have a conversion step from a library provided char* to a strbuf type. Any use of the strbuf API is guaranteed to be correct. I agree: having a datatype beats sanitising input (I think there's a popular essay somewhere about parsing input vs sanitising input which makes pretty much the same point as you do), but it's still only partially correct. To get to fully co…

Sure but now we're talking about a universal problem across languages, rather than a C-specific problem.

Re: Improvements to static analysis in GCC 14

#138
post #57
post #54

Earlier quoted context omitted.

For signed overflow I use -fsanitize=signed-integer-overflow .

Good. I wonder how many people do and also if their compilers support it. (One would hope so, of course. I assume clang and GCC do.) ... but the question is really what you ship to production. Btw, possible signed overflow was just an example of things people do not want warnings for . OOB is far more dangerous, obviously... and the cost for sanitizer in that case is HUGE... and it doesn't actually catch all cases AF…

For production one could use -fsanitize-undefined-trap-on-error that turns it into traps. I would not describe the cost of -fsanitize-undefined=bounds has huge. The cost of Asan is huge.

Re: Improvements to static analysis in GCC 14

#139
post #132

Earlier quoted context omitted.

It is easy to document mistakes in hindsight, since hindsight is 20/20. It is very easy to write your own one-off secure string handling library. This is a common assignment in intro to C programming classes. So why isn't it standard in C already? You offer a theory that there is a gang of "security unconscious assholes [who] keep shutting it down". This gang is so well organized that they have managed to block an ea…

There's no need to integrate with 60 years of mission critical codebases, you're making up a problem in your head that doesn't exist. Nothing needs to be fixed, all it takes is to stop doing the stupid thing. It does not take a "coordinated gang" to shut down C standard proposals, them getting shut down is the default. You seem to be neither familiar with the nature of the problem or the struggle that is getting anyt…

> Nothing needs to be fixed, all it takes is to stop doing the stupid thing.

Well we'll just agree to disagree I suppose, as I'm equally convinced that you're not grasping what the problem actually is.

All I can say is that if this were as easy to fix as you assert and "all it takes is to stop doing the stupid thing" and we both agree that writing code for the better thing is super easy, then consider why it has not been possible to fix in the C universe.

Re: Improvements to static analysis in GCC 14

#140
post #139

Earlier quoted context omitted.

There's no need to integrate with 60 years of mission critical codebases, you're making up a problem in your head that doesn't exist. Nothing needs to be fixed, all it takes is to stop doing the stupid thing. It does not take a "coordinated gang" to shut down C standard proposals, them getting shut down is the default. You seem to be neither familiar with the nature of the problem or the struggle that is getting anyt…

> Nothing needs to be fixed, all it takes is to stop doing the stupid thing. Well we'll just agree to disagree I suppose, as I'm equally convinced that you're not grasping what the problem actually is. All I can say is that if this were as easy to fix as you assert and "all it takes is to stop doing the stupid thing" and we both agree that writing code for the better thing is super easy, then consider why it has not…

I don't know what to tell you. Look at the git codebase, they downright ban any usage of the strcpy family, going so far as to hide them under macros so people can't use them.

Banning them outright is not possible in old codebases before the internet got really popular and people were pointing out how bad these functions were, but they sure could stop using them in any new code written in that codebase. That's what code review is for.

Any C code written after 2010 has absolutely no excuse to use these functions. They are inefficient, unsafe and more annoying to use than a strbuf implementation that takes half an hour to write.

So why have people continued to use them?

Option a) they were already there, the codebase is over 30 years old, and replacing the code entirely would be too much work. This is a valid reason.

Option b) ignorance, they don't know how to write a strbuf type. This one is downright impossible, any C dev knows how to do it, and like I said, literally every other language does it the same way.

Option c) laziness. This is for me the only real reason. As awful as these functions are, they're in the stdlib. You still see people saying "simple usages of strncpy are fine". They are not fine.

If you can think of an option d) I'd love to know, because I honestly can't think of anything else. Note that interfacing with existing 30 year old codebases does not count, as how you internally manipulate strings has no bearing on that, all you need to ensure is the 0 terminator at the end.

You get a mutable char* from the old function. You shove it in a struct strbuf {size_t capacity, size_t length, char* data}. Done.

You get a constant char* from the old function. You call strlen followed by malloc and memcpy into a new buffer for the strbuf. Or if you don't need to actually mutate the string, you store it in a non-zero terminated struct strview {size_t length; char* data}.

So what is the challenge here? Why is usage of strcpy not banned in any codebase less than 20 years old?

Post reply on HN