From: David Malcolm <dmalcolm@redhat.com>
To: Alejandro Colomar <alx.manpages@gmail.com>, GCC <gcc@gcc.gnu.org>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Subject: Re: Missed warning (-Wuse-after-free)
Date: Thu, 16 Feb 2023 10:15:30 -0500 [thread overview]
Message-ID: <38e7e994a81d2a18666404dbaeb556f3508a6bd6.camel@redhat.com> (raw)
In-Reply-To: <8ed6d28c-69dc-fed8-5ab5-99f685f06fac@gmail.com>
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);
| ^~
'main': events 1-2
|
| 25 | main(void)
| | ^~~~
| | |
| | (1) entry to 'main'
|......
| 29 | p = xstrdup("");
| | ~~~~~~~~~~~
| | |
| | (2) calling 'xstrdup' from 'main'
|
+--> 'xstrdup': events 3-5
|
| 8 | xstrdup(const char *s)
| | ^~~~~~~
| | |
| | (3) entry to 'xstrdup'
|......
| 13 | if (p == NULL)
| | ~
| | |
| | (4) following 'false' branch (when 'p' is non-NULL)...
| 14 | exit(EXIT_FAILURE);
| 15 | return p;
| | ~
| | |
| | (5) ...to here
|
<------+
|
'main': events 6-15
|
| 29 | p = xstrdup("");
| | ^~~~~~~~~~~
| | |
| | (6) returning to 'main' from 'xstrdup'
|......
| 32 | if (p == q)
| | ~
| | |
| | (7) following 'true' branch (when 'p == q')...
| 33 | puts("equal before");
| | ~~~~~~~~~~~~~~~~~~~~
| | |
| | (8) ...to here
|......
| 39 | p = realloc(p, UINT16_MAX);
| | ~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (9) freed here
| | (10) when 'realloc' succeeds, moving buffer
| 40 | if (p == NULL)
| | ~
| | |
| | (11) following 'false' branch (when 'p' is non-NULL)...
| 41 | exit(EXIT_FAILURE);
| 42 | puts("realloc()");
| | ~~~~~~~~~~~~~~~~~
| | |
| | (12) ...to here
| 43 |
| 44 | if (p == q) { // Use after realloc. I'd expect a warning here.
| | ~
| | |
| | (13) following 'false' branch (when 'p != q')...
|......
| 64 | printf("PID = %i\n", (int) getpid());
| | ~~~~~~~~
| | |
| | (14) ...to here
| 65 | printf("*q = %i\n", *q);
| | ~~
| | |
| | (15) use after 'free' of 'q'; freed at (9)
|
I'm not convinced that it's useful to the end-user to warn about the
"use of q itself" case.
Dave
next prev parent reply other threads:[~2023-02-16 15:15 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 [this message]
2023-02-17 1:04 ` Alejandro Colomar
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=38e7e994a81d2a18666404dbaeb556f3508a6bd6.camel@redhat.com \
--to=dmalcolm@redhat.com \
--cc=alx.manpages@gmail.com \
--cc=gcc@gcc.gnu.org \
--cc=ipedrosa@redhat.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.
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).