public inbox for gcc-bugs@sourceware.org help / color / mirror / Atom feed
From: "tom.cosgrove at arm dot com" <gcc-bugzilla@gcc.gnu.org> To: gcc-bugs@gcc.gnu.org Subject: [Bug c/106119] New: Bogus use-after-free warning triggered by optimizer Date: Tue, 28 Jun 2022 14:28:08 +0000 [thread overview] Message-ID: <bug-106119-4@http.gcc.gnu.org/bugzilla/> (raw) https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106119 Bug ID: 106119 Summary: Bogus use-after-free warning triggered by optimizer Product: gcc Version: 12.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: tom.cosgrove at arm dot com Target Milestone: --- There are a number of bug reports related to -Wuse-after-free - it's not clear to me if our particular issue has already been captured, so please do close as duplicate if it has (it seems that the optimiser is moving code around, so could potentially be a duplicate of https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104215). Assuming not a duplicate, this should probably be linked to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104075. Our self-test code checks to see if two consecutive calloc() calls return the same value, by storing the pointer value in a uintptr_t integer and comparing against this value later. When we compile with optimisation (we don't see the problem with -O0) and with an if-statement later in the code, we get a spurious use-after-free warning. We don't get this warning at -O0, or if we remove the if-statement. We have also confirmed that if we reorder the assignment to the uintptr_t and the call to free() we consistently DO get the use-after-free warning (as expected) regardless of optimisation level. gcc-12 $ uname -a Linux e120653 5.17.15-1-MANJARO #1 SMP PREEMPT Wed Jun 15 07:09:31 UTC 2022 x86_64 GNU/Linux gcc-12 $ gcc --version gcc (GCC) 12.1.0 Copyright (C) 2022 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. gcc-12 $ cat foo.c #include <stdint.h> #include <stdio.h> #include <stdlib.h> void calloc_self_test( __attribute__ ((unused)) int verbose ) { void *buffer1 = calloc( 1, 1 ); uintptr_t old_buffer1 = (uintptr_t) buffer1; free( buffer1 ); buffer1 = calloc( 1, 1 ); int same = ( old_buffer1 == (uintptr_t) buffer1 ); if( verbose ) printf( " CALLOC(1 again): passed (%s address)\n", same ? "same" : "different" ); free( buffer1 ); } No warning at -O0: gcc-12 $ gcc -O0 -Wall -Wextra -Wformat=2 -Wno-format-nonliteral -o foo -c foo.c gcc-12 $ But unexpected warning at -O2: gcc-12 $ gcc -O2 -Wall -Wextra -Wformat=2 -Wno-format-nonliteral -o foo -c foo.c foo.c: In function ‘calloc_self_test’: foo.c:8:15: warning: pointer ‘buffer1’ may be used after ‘free’ [-Wuse-after-free] 8 | uintptr_t old_buffer1 = (uintptr_t) buffer1; | ^~~~~~~~~~~ foo.c:9:5: note: call to ‘free’ here 9 | free( buffer1 ); | ^~~~~~~~~~~~~~~ Removing the if-statement quashes the warning: gcc-12 $ perl -ni -e 'print unless /if.*verbose/' foo.c gcc-12 $ cat foo.c #include <stdint.h> #include <stdio.h> #include <stdlib.h> void calloc_self_test( __attribute__ ((unused)) int verbose ) { void *buffer1 = calloc( 1, 1 ); uintptr_t old_buffer1 = (uintptr_t) buffer1; free( buffer1 ); buffer1 = calloc( 1, 1 ); int same = ( old_buffer1 == (uintptr_t) buffer1 ); printf( " CALLOC(1 again): passed (%s address)\n", same ? "same" : "different" ); free( buffer1 ); } gcc-12 $ gcc -O0 -Wall -Wextra -Wformat=2 -Wno-format-nonliteral -o foo -c foo.c gcc-12 $ gcc -O2 -Wall -Wextra -Wformat=2 -Wno-format-nonliteral -o foo -c foo.c gcc-12 $ Checking that we always get the error when we swap the assignment and free() statements: gcc-12 $ cat bar.c #include <stdint.h> #include <stdio.h> #include <stdlib.h> void calloc_self_test( __attribute__ ((unused)) int verbose ) { void *buffer1 = calloc( 1, 1 ); free( buffer1 ); uintptr_t old_buffer1 = (uintptr_t) buffer1; buffer1 = calloc( 1, 1 ); int same = ( old_buffer1 == (uintptr_t) buffer1 ); if( verbose ) printf( " CALLOC(1 again): passed (%s address)\n", same ? "same" : "different" ); free( buffer1 ); } gcc-12 $ gcc -O0 -Wall -Wextra -Wformat=2 -Wno-format-nonliteral -o bar -c bar.c bar.c: In function ‘calloc_self_test’: bar.c:9:15: warning: pointer ‘buffer1’ used after ‘free’ [-Wuse-after-free] 9 | uintptr_t old_buffer1 = (uintptr_t) buffer1; | ^~~~~~~~~~~ bar.c:8:5: note: call to ‘free’ here 8 | free( buffer1 ); | ^~~~~~~~~~~~~~~ gcc-12 $ gcc -O2 -Wall -Wextra -Wformat=2 -Wno-format-nonliteral -o bar -c bar.c bar.c: In function ‘calloc_self_test’: bar.c:9:15: warning: pointer ‘buffer1’ used after ‘free’ [-Wuse-after-free] 9 | uintptr_t old_buffer1 = (uintptr_t) buffer1; | ^~~~~~~~~~~ bar.c:8:5: note: call to ‘free’ here 8 | free( buffer1 ); and we still get the warning (as we would hope) without the if-statement: gcc-12 $ perl -ni -e 'print unless /if.*verbose/' bar.c gcc-12 $ cat bar.c #include <stdint.h> #include <stdio.h> #include <stdlib.h> void calloc_self_test( __attribute__ ((unused)) int verbose ) { void *buffer1 = calloc( 1, 1 ); free( buffer1 ); uintptr_t old_buffer1 = (uintptr_t) buffer1; buffer1 = calloc( 1, 1 ); int same = ( old_buffer1 == (uintptr_t) buffer1 ); printf( " CALLOC(1 again): passed (%s address)\n", same ? "same" : "different" ); free( buffer1 ); } gcc-12 $ gcc -O0 -Wall -Wextra -Wformat=2 -Wno-format-nonliteral -o bar -c bar.c bar.c: In function ‘calloc_self_test’: bar.c:9:15: warning: pointer ‘buffer1’ used after ‘free’ [-Wuse-after-free] 9 | uintptr_t old_buffer1 = (uintptr_t) buffer1; | ^~~~~~~~~~~ bar.c:8:5: note: call to ‘free’ here 8 | free( buffer1 ); | ^~~~~~~~~~~~~~~ gcc-12 $ gcc -O2 -Wall -Wextra -Wformat=2 -Wno-format-nonliteral -o bar -c bar.c bar.c: In function ‘calloc_self_test’: bar.c:9:15: warning: pointer ‘buffer1’ used after ‘free’ [-Wuse-after-free] 9 | uintptr_t old_buffer1 = (uintptr_t) buffer1; | ^~~~~~~~~~~ bar.c:8:5: note: call to ‘free’ here 8 | free( buffer1 ); | ^~~~~~~~~~~~~~~
next reply other threads:[~2022-06-28 14:28 UTC|newest] Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top 2022-06-28 14:28 tom.cosgrove at arm dot com [this message] 2022-06-28 15:37 ` [Bug c/106119] " tom.cosgrove at arm dot com 2022-06-29 13:53 ` tom.cosgrove at arm dot com 2022-07-11 22:07 ` [Bug tree-optimization/106119] [12/13 Regression] " pinskia at gcc dot gnu.org 2022-07-25 15:50 ` rguenth at gcc dot gnu.org 2022-10-17 12:31 ` rguenth at gcc dot gnu.org 2022-12-15 0:37 ` pinskia at gcc dot gnu.org 2023-05-08 12:24 ` [Bug tree-optimization/106119] [12/13/14 " rguenth at gcc dot gnu.org 2024-03-15 1:23 ` [Bug tree-optimization/106119] [12 " law at gcc dot gnu.org
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=bug-106119-4@http.gcc.gnu.org/bugzilla/ \ --to=gcc-bugzilla@gcc.gnu.org \ --cc=gcc-bugs@gcc.gnu.org \ /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: linkBe 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).