> However, the most vocal opposition came from a static analysis perspective: Making null pointers well-defined for zero length means that static analyzers can no longer unconditionally report NULL being passed to functions like memcpy—they also need to take the length into account now.
How does this make any sense? We don't want to remove a low hanging footgun because static analyzers can no longer detect it?
No, it means the static analyzers can't report on a different error because a subset of that class of errors is no longer an error, and the static analysis can't usually distinguish between that subset and the rest.
memcpy(NULL, NULL, 0); // Formerly bad, now ok.
memcpy(NULL, NULL, s); // Formerly bad, now unknown (unless it can be proven that s != 0).
and
memcpy(NULL, b, c); // Same issue.
(where "NULL" == "statically known to be NULL", not necessarily just a literal NULL. Not that that changes the difficulty here.)
Previously: warn if either address might be NULL.
Now: warn if either address might be NULL and the length might be nonzero, and prepare for your users to be annoyed and shut this warning off due to the false alarms.
Any useful static analysis tool does a careful balance between false positives and false negatives (aka false alarms and missed bugs). Too many false positives, and that warning will be disabled, or users will get used to ignoring it, or it will be routinely annotated away at call sites without anyone bothering to figure out whether it's valid or not. Soon the tool will cease to be useful and may be entirely abandoned. In actual practice, the sophistication of a static analysis tool is far less relevant than its precision. It's quite common to have an incredibly powerful static analysis tool that is used for only a small handful of blazingly obvious warnings, sometimes ones that the compiler already has implemented! (All the tool's fancy warnings got disabled one by one and nobody noticed.)
Yes, but that tradeoff exists for most things those tools do. If you can easily and perfectly detect an error, it should just go into the compiler (and perhaps language spec).
> If you can easily and perfectly detect an error, it should just go into the compiler (and perhaps language spec).
Nobody seems to care much about removing UB even when it's super easy. For example, a bunch of basic syntax errors like forgetting the closing quote on a string or not having a newline at the end of the file are UB.
How does this make any sense? We don't want to remove a low hanging footgun because static analyzers can no longer detect it?