Hi,
Le 16/02/2023 à 15:35, Alejandro Colomar via Gcc a écrit :
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?
-Wuse-after-free=3
Regards.
--
Yann Droneaud
OPTEYA