mailing list of musl libc
 help / color / mirror / code / Atom feed
From: James Y Knight <jyknight@google.com>
To: musl@lists.openwall.com
Subject: Re: [PATCH] Define NULL as __null in C++ mode when using GCC or Clang.
Date: Wed, 10 Jul 2019 12:01:17 -0400	[thread overview]
Message-ID: <CAA2zVHop_6g+piZxCoSHTy9ODhyZP4FdNPdbC8nYXhb6nscyag@mail.gmail.com> (raw)
In-Reply-To: <20190710020357.GI21055@port70.net>

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

On Tue, Jul 9, 2019 at 10:04 PM Szabolcs Nagy <nsz@port70.net> wrote:

> * James Y Knight <jyknight@google.com> [2019-07-09 19:04:13 -0400]:
> > On Tue, Jul 9, 2019 at 3:38 PM Rich Felker <dalias@libc.org> wrote:
> > > On Tue, Jul 09, 2019 at 03:19:00PM -0400, James Y Knight wrote:
> > > > Both GCC and Clang ship their own stddef.h which does this (musl's
> > > > stddef.h is simply ignored). But, musl also defines the macro in a
> > > > number of other headers.
> > >
> > > This was intentional at the time it was done. At least in the present
> > > version of C++ at the time, __null was not a conforming definition.
> > > For example, conforming applications could parse the stringification
> > > of NULL and expect to get something that's a valid null pointer
> > > constant. This could possibly be revisited, if it's changed, and if it
> > > can be done in a way that doesn't involve compiler-specific stuff.
> > >
> >
> > The C++11 standard simply says "The macro NULL is an
> implementation-defined
> > C++ null pointer constant in this International Standard." (and links to
> > the definition of null pointer constant -- "A null pointer constant is an
> > integral constant expression (5.19) prvalue of integer type that
> evaluates
> > to zero or a prvalue of type std::nullptr_t").
> >
> > If the implementation defines __null to be a null pointer constant, which
> > is an integral constant expression of integer type that evaluates to zero
> > (which it does), that seems entirely valid. I see nothing that restricts
> > what it may stringify to.
>
> it is clear that 0L is a conforming definition for all
> conforming c++ compilers.
>
> it is less clear if __null is so in all compilers that
> define __GNUC__.


Sure, it's theoretically possible that some unknown compiler pretends to be
GCC, but then implements __null incorrectly. But if it does, why does musl
care? A conforming C++ implementation certainly requires a great many
components to be implemented correctly, not least of which is the compiler.

so normally one would expect a compelling reason to do

such change.


The warning when you're using NULL as a "long" instead of a pointer is a
very important warning -- so important it's on by default without any
warning flags. It's _extremely_ surprising behavior for most developers
that foo(NULL) can call a foo(long) overload in preference to a foo(int*)
overload. This is why the compiler went to the trouble of implementing
__null in the first place. It's only somewhat less important, now that
'nullptr' is becoming more prevalent.


> > > Mostly, getting musl's definition simply degrades warning diagnostics

>
> > > in C++ slightly -- e.g. GCC can no longer emit this warning:
> > > >   warning: passing NULL to non-pointer argument 1 of 'int foo(long
> int)'
> > > > [-Wconversion-null]
> > >
> > > The current definition however catches bugs where NULL is wrongly used
> > > to terminate a variadic argument list where (void*)0 or (char*)0 is
> > > actually needed. See commits 41d7c77d6a2e74294807d35062e4cd1d48ab72d3
> > > and c8a9c22173f485c8c053709e1dfa0a617cb6be1a. So both choices are a
> > > tradeoff in diagnostic capability.
> >
> >
> > Ehh. Actually musl's definition actually breaks the intended semantics of
> > that warning as well. The following program:
> > #include <unistd.h>
> > int main() {
> >   execl("foo", "bar", NULL);
> > }
> > does indeed not warn with "g++ -Wall foo.cc" when NULL is __null, and it
> > does warn if NULL is 0L.
> >
> > However, it was an intentional choice, not an accident, to suppress the
> > warning in the former case. This kind of usage is widespread,, and in
> > practice it does not trigger buggy behavior (because __null is guaranteed
> > to be the same size as a pointer). GCC does have a separate
> > "-Wstrict-null-sentinel" warning flag, if you want to be more pedantic
> > about this not-standards-compliant code.
>
> if a variadic function implementation calls va_arg(ap,char*)
> on a NULL argument then the behaviour is undefined in c++,
> but it is well-defined in posix! so the pattern is legitimately
> widespread but users often mistakenly compile c code as c++.
>

While it's not defined by C++, I do not believe there are any platforms GCC
or Clang supports where passing __null to a varargs function instead of
(void*)0 causes a problem. The intent is certainly that it's in-practice
safe to use as a varargs-terminator, by being defined to be the correct
size.


> how can we ensure that an optimizing c++ compiler won't
> silently break such code? gcc rutinely eliminates code if
> it can spot that a null pointer is passed to a library
> function where that is undefined.


not diagnosing such correctness issues when you can is bad
> practice: it leaves around ticking time bombs.


There's always a trade-off between which warnings should be enabled by
default or in -Wall. If this were an _actual_ codegen problem, for sure
-Wstrict-null-sentinel should be enabled by default. However, as a
very-common idiom which does not cause an actual problem, having this not
emit a warning in the default flag sets seems justifiable.


> (the warnings __null can provide are rarely time bombs)
>

Without the warning, developers may not realize that the wrong overload is
being called. And maybe their software is working anyways, for whatever
reason -- until someone converts NULL to nullptr, causing an unexpected
behavior change.


> but i think NULL is dangerously broken in c++ either way,
> so both the current and the proposed definition is fine by me,
> i just slightly prefer the current definition.
>

I think everyone agrees NULL is broken in C++, which is why we now have
nullptr.

[-- Attachment #2: Type: text/html, Size: 8029 bytes --]

      parent reply	other threads:[~2019-07-10 16:01 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-07-09 19:19 James Y Knight
2019-07-09 19:38 ` Rich Felker
2019-07-09 23:04   ` James Y Knight
2019-07-10  2:03     ` Szabolcs Nagy
2019-07-10  6:34       ` Florian Weimer
2019-07-10  8:46         ` Szabolcs Nagy
2019-07-10 16:18         ` James Y Knight
2019-07-10 16:44           ` Rich Felker
2019-07-10 17:35             ` James Y Knight
2019-07-10 20:11               ` A. Wilcox
2019-07-10 20:19                 ` Michael Everitt
2019-07-10 20:45                 ` Rich Felker
2019-07-10 20:48               ` Rich Felker
2019-07-10 21:11                 ` Szabolcs Nagy
2019-07-10 21:16                   ` Rich Felker
2019-07-10 21:44                     ` Szabolcs Nagy
2019-07-10 16:01       ` James Y Knight [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CAA2zVHop_6g+piZxCoSHTy9ODhyZP4FdNPdbC8nYXhb6nscyag@mail.gmail.com \
    --to=jyknight@google.com \
    --cc=musl@lists.openwall.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/musl/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).