It sounds as if the root of the problem is the C standard. Wouldn't it be better to fix that instead of creating a shadow standard defined by the implementation of this boring compiler?
I also object to the presupposition that there is secure software and non-secure software. In most practical cases, it is impossibly hard to tell in which class an application falls, so it would be better not to make that distinction at all.
>It sounds as if the root of the problem is the C standard. Wouldn't it be better to fix that
Isn't the reason for a lot of undefined behavior either in the name of performance through optimization and assumptions, portability because the implementation can just do whatever the underlying platform natively does or the committee just couldn't agree on it?
All three of those scenarios appear inherently unfixable to me without a separate sub-standard that intentionally clamps down on performance/ease of portability and actually gets the committee to agree.
I don't know the reasons for why so many things are undefined in C. However, if a program does one thing when compiled with compiler A and another thing when compiled with compiler B, how does that help portability? To my perhaps naive mind this makes portability harder to achieve not easier.
A classic example of trying to define behaviour regardless of what all the different hardware does is Java choosing IEEE754 floating point. Which isn't natively supported on x86.
>Java choosing IEEE754 floating point. Which isn't natively supported on x86.
IEEE754 was based on the design of the 8087, and it's been native on x86 since the 80387.
The problem with Java choosing IEEE754 was, according to the paper you linked, not that it wasn't supported on all hardware, but that Java didn't follow the spec completely,
"Later we shall see why Java’s expanded market would be served better by actual conformity to the letter and spirit of IEEE Standard 754"
The 80-bit floats were still in use right through the 2000s; I know because I had to work out what option to use to get reproducible fp rounding on 64-bit doubles in 32-bit C. I've not had occasion to look at the details of amd64 fp.
The point is you are supposed to avoid undefined behavior, precisely because these things can be different between compilers. In theory, this lets the compilers optimize better for a specific platform/cpu, while avoiding changing the meaning of the programmer's code. In practice, most platforms and compilers have done the same exact thing with the same "undefined" behavior, that a large body of code relies on that defacto standard.
"In practice, most platforms and compilers have done the same exact thing with the same "undefined" behavior, that a large body of code relies on that defacto standard."
All compilers on the same platform have done the same exact thing with the same "undefined" behavior.
At the moment, all platforms are x86. Previously, all platforms were SPARC, and before that, VAX.
Then you require that either the programmer checks if the pointer is null, or the compiler can infer that it isn’t null, or that you add an annotation for that. (Either an annotation for a method parameter to require it not to be null, or an annotation that marks it as nullable, or an annotation that disables these warnings.
The real problem is when compilers make assumptions based on such uses. For example, optimizing C compilers will see that, and assume that p must not be NULL, because otherwise it would be undefined. That can lead to dangerous results. John Regehr is a computer science professor at the University of Utah, and has written about this extensively: http://blog.regehr.org/archives/213
If you look at the comment history, you'll find I have recently argued why you don't want warnings for these kinds of things. But I agree with Regehr et al.'s proposal for a Friendly C, http://blog.regehr.org/archives/1180, which would disallow optimizing way those null-pointer checks. Any attempt for myself to justify why would just restate, poorly, what Regehr and company already state in that post and the ones linked to from it.
I think it's worth noting that some critical code, such as the Linux kernel, already opts out of such optimizations because they've been bitten by it in the past. My previous post talks about that.
> It sounds as if the root of the problem is the C standard.
Some of it is indeed a problem with the standard. There are other bits though where portability or optimization needs kind of require some level of "undefined" behaviour for the standard. There really are some bits of code that perhaps can't be as portable and/or as efficient if you code for safety.
> I also object to the presupposition that there is secure software and non-secure software.
I'm with you 100% here. Especially without a more precise definition of what we mean by "secure".
> In most practical cases, it is impossibly hard to tell in which class an application falls, so it would be better not to make that distinction at all.
Unfortunately, it seems that it's really quite easy to tell. Unless you have overwhelming evidence [1] that says the software is "secure", it's almost certainly going to turn out to be insecure.
I also object to the presupposition that there is secure software and non-secure software. In most practical cases, it is impossibly hard to tell in which class an application falls, so it would be better not to make that distinction at all.