NULL safety (was: strncpy clarify result may not be null terminated)

Alejandro Colomar
2023-11-18T09:42:04Z

[-- Attachment #1: Type: text/plain, Size: 2306 bytes --]

Hi Jonny,

On Fri, Nov 17, 2023 at 09:46:47PM +0000, Jonny Grant wrote:
> > Regarding other string-copying functions, NULL is not inherent to them,
> > so I'm not sure if they should have explicit NULL checks. Why would
> > these functions receive a null pointer? The main possibility is that
> > the programmer forgot to check some malloc(3) call, which should receive
> > a different treatment from a failed copy, normally.
>
> Perhaps it's just my point of view. In safety critical software I always do my best to ensure no code calls an API with the null pointer constant - when it's expecting a valid pointer. Given that the null pointer constant is defined in the C standard, even if APIs have undefined behaviour if they require a pointer but are passed a NULL. So the converse is I make APIs check for NULL (if they require a valid pointer) and reject with an error. Covers all bases (there can be corrupt data files occurring that we can't anticipate), so issues can be logged, and no core dump. I'd rather display a "USB device error 51" message on a UI than suffer a core dump which turns off a piece of safety critical equipment or sends it into a restart death loop.
>
> I recall you mentioned [[gnu::nonnull]] aka __attribute__((nonnull)) which is an optimizer hint the API will always be called with a valid pointer. There is also returns_nonnull.
>
> The difficulty is the optimizer will remove any NULL pointer constant checks within those APIs (if there were any). The side effect is a useful compiler warning, if the compiler figures out someone is passing NULL.
>
> So in a safety critical system we must wrap all such APIs, to put back in the null pointer constant checks.

There's Clang's qualifier _Nonnull, which is not a hint to the
optimizer. It is an attempt to have null correctness similar to how we
have const correctness. It still has little support, even from Clang
itself. It has some important problem: it applies to the pointer, not
to the pointee, but pointer qualifiers are discarded easily. A better
design would make it a pointee qualifier. Hopefully, this will some day
be there to end all NULL discussions. Until then, yeah, NULL is a
dangerous part of the language.

Cheers,
Alex

--
<https://www.alejandro-colomar.es/>