public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
From: Alejandro Colomar <alx.manpages@gmail.com>
To: David Malcolm <dmalcolm@redhat.com>, GCC <gcc@gcc.gnu.org>
Cc: "Iker Pedrosa" <ipedrosa@redhat.com>,
	"Florian Weimer" <fweimer@redhat.com>,
	"Paul Eggert" <eggert@cs.ucla.edu>,
	"Michael Kerrisk" <mtk.manpages@gmail.com>,
	"Martin Uecker" <uecker@tugraz.at>,
	"Jₑₙₛ Gustedt" <jens.gustedt@inria.fr>
Subject: Re: Missed warning (-Wuse-after-free)
Date: Fri, 17 Feb 2023 02:04:24 +0100	[thread overview]
Message-ID: <23d3a3ff-adad-ac2e-92a6-4e19f4093143@gmail.com> (raw)
In-Reply-To: <38e7e994a81d2a18666404dbaeb556f3508a6bd6.camel@redhat.com>


[-- Attachment #1.1: Type: text/plain, Size: 5628 bytes --]

[CC: Added those who contributed to the discussion in linux-man@,
     and also the authors of N2861 for C2x]

Hi David,

On 2/16/23 16:15, David Malcolm wrote:
> On Thu, 2023-02-16 at 15:35 +0100, Alejandro Colomar via Gcc wrote:
>> Hi!
>>
>> I was preparing an example program of a use-after-realloc bug,
>> when I found that GCC doesn't warn in a case where it should.
>>
>>
>> alx@debian:~/tmp$ cat realloc.c
>> #include <stdint.h>
>> #include <stdlib.h>
>> #include <stdio.h>
>> #include <string.h>
>> #include <unistd.h>
>>
>> static inline char *
>> xstrdup(const char *s)
>> {
>>         char  *p;
>>
>>         p = strdup(s);
>>         if (p == NULL)
>>                 exit(EXIT_FAILURE);
>>         return p;
>> }
>>
>> static inline char *
>> strnul(const char *s)
>> {
>>         return (char *) s + strlen(s);
>> }
>>
>> int
>> main(void)
>> {
>>         char  *p, *q;
>>
>>         p = xstrdup("");
>>         q = strnul(p);
>>
>>         if (p == q)
>>                 puts("equal before");
>>         else
>>                 exit(EXIT_FAILURE); // It's an empty string; this
>> won't happen
>>
>>         printf("p = %p; q = %p\n", p, q);
>>
>>         p = realloc(p, UINT16_MAX);
>>         if (p == NULL)
>>                 exit(EXIT_FAILURE);
>>         puts("realloc()");
>>
>>         if (p == q) {  // Use after realloc.  I'd expect a warning
>> here.
>>                 puts("equal after");
>>         } else {
>>                 /* Can we get here?
>>                    Let's see the options:
>>
>>                         - realloc(3) fails:
>>                                 We exit immediately.  We don't arrive
>> here.
>>
>>                         - realloc(3) doesn't move the memory:
>>                                 p == q, as before
>>
>>                         - realloc(3) moved the memory:
>>                                 p is guaranteed to be a unique
>> pointer,
>>                                 and q is now an invalid pointer.  It
>> is
>>                                 Undefined Behavior to read `q`, so `p
>> == q`
>>                                 is UB.
>>
>>                    As we see, there's no _defined_ path where this
>> can happen
>>                  */
>>                 printf("PID = %i\n", (int) getpid());
>>         }
>>
>>         printf("p = %p; q = %p\n", p, q);
>> }
>> alx@debian:~/tmp$ cc -Wall -Wextra realloc.c -O3 -fanalyzer
>> realloc.c: In function ‘main’:
>> realloc.c:67:9: warning: pointer ‘p’ may be used after ‘realloc’ [-
>> Wuse-after-free]
>>    67 |         printf("p = %p; q = %p\n", p, q);
>>       |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>> realloc.c:39:13: note: call to ‘realloc’ here
>>    39 |         p = realloc(p, UINT16_MAX);
>>       |             ^~~~~~~~~~~~~~~~~~~~~~
>> alx@debian:~/tmp$ ./a.out 
>> equal before
>> p = 0x55bff80802a0; q = 0x55bff80802a0
>> realloc()
>> PID = 25222
>> p = 0x55bff80806d0; q = 0x55bff80802a0
>>
>>
>> Did I miss anything?
> 
> GCC's -fanalyzer will warn if you dereference q, so e.g. adding:
>  printf("*q = %i\n", *q);
> gives a warning:
>   https://godbolt.org/z/6qx4afb3E
> 
> <source>: In function 'main':
> <source>:65:29: warning: use after 'free' of 'q' [CWE-416] [-Wanalyzer-use-after-free]
>    65 |         printf("*q = %i\n", *q);
>       |                             ^~

[...]

> 
> I'm not convinced that it's useful to the end-user to warn about the
> "use of q itself" case.

I didn't quote the standard because I couldn't find it.  I was searching in C11,
and it seems that it was only implicitly Undefined Behavior, without explicit
spelling (the value of the pointer was indeterminate, according to C11).
Now C23 will better clarify that reading such a pointer value (not even
dereferencing) is Undefined Behavior.

There was a discussion in linux-man@ some years ago, which now I realize it
didn't end up being applied (I thought we had applied a patch, but it seems we
didn't).  I'll check if we still need such a patch (and I guess we do, since
we're having this conversation).

Using the pointer is _wrong_.  And by wrong, I mean that it's Undefined Behavior.
I think that alone is enough to issue a warning.  Especially, since the compiler
already has that information; otherwise, it couldn't have warned about line 67
of my example program.  I could understand if due to optimizations the compiler
lost that information, so it couldn't warn, but in this case, there's no excuse.

The benefit for users?  They'll realize that the code they wrote is bad.  Not even
suspicious, as some warnings warn about suspicious code.  This case is
uncontroversially wrong.  That code has no valid reason to be written that way,
under ISO C.

Cheers,

Alex

> 
> Dave

-- 
<http://www.alejandro-colomar.es/>
GPG key fingerprint: A9348594CE31283A826FBDD8D57633D441E25BB5

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

  reply	other threads:[~2023-02-17  1:04 UTC|newest]

Thread overview: 39+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-02-16 14:35 Alejandro Colomar
2023-02-16 15:15 ` David Malcolm
2023-02-17  1:04   ` Alejandro Colomar [this message]
2023-02-17  1:05     ` Alejandro Colomar
2023-02-17  1:56       ` Sam James
2023-02-17  8:12     ` Martin Uecker
2023-02-17 11:35       ` Alejandro Colomar
2023-02-17 13:34         ` Andreas Schwab
2023-02-17 13:48         ` Martin Uecker
2023-02-23 19:23           ` Alex Colomar
2023-02-23 19:57             ` Martin Uecker
2023-02-24  0:02               ` Alex Colomar
2023-02-24  1:21                 ` Serge E. Hallyn
2023-02-24  1:42                   ` Alex Colomar
2023-02-24  3:01                     ` Peter Lafreniere
2023-02-24  8:52                       ` Martin Uecker
2023-02-24  8:43                     ` Martin Uecker
2023-02-24 16:10                     ` Serge E. Hallyn
2023-02-24  8:36                   ` Martin Uecker
2023-02-24 16:01                     ` Serge E. Hallyn
2023-02-24 16:37                       ` Martin Uecker
2023-02-17  3:48   ` Siddhesh Poyarekar
2023-02-17 11:22     ` Alejandro Colomar
2023-02-17 13:38       ` Siddhesh Poyarekar
2023-02-17 14:01         ` Mark Wielaard
2023-02-17 14:06           ` Siddhesh Poyarekar
2023-02-17 21:20         ` [PATCH] Make -Wuse-after-free=3 the default one in -Wall Alejandro Colomar
2023-02-17 21:39           ` Siddhesh Poyarekar
2023-02-17 21:41             ` Siddhesh Poyarekar
2023-02-17 22:58             ` Alejandro Colomar
2023-02-17 23:03               ` Siddhesh Poyarekar
2023-02-17 11:24     ` Missed warning (-Wuse-after-free) Jonathan Wakely
2023-02-17 11:43       ` Alejandro Colomar
2023-02-17 12:04         ` Jonathan Wakely
2023-02-17 12:53       ` Siddhesh Poyarekar
2023-02-17 14:10         ` Jonathan Wakely
2023-02-17 13:44     ` David Malcolm
2023-02-17 14:01       ` Siddhesh Poyarekar
2023-02-17  8:49 ` Yann Droneaud

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=23d3a3ff-adad-ac2e-92a6-4e19f4093143@gmail.com \
    --to=alx.manpages@gmail.com \
    --cc=dmalcolm@redhat.com \
    --cc=eggert@cs.ucla.edu \
    --cc=fweimer@redhat.com \
    --cc=gcc@gcc.gnu.org \
    --cc=ipedrosa@redhat.com \
    --cc=jens.gustedt@inria.fr \
    --cc=mtk.manpages@gmail.com \
    --cc=uecker@tugraz.at \
    /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.
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 read-only IMAP folder(s) and NNTP newsgroup(s).