* [Bug middle-end/98109] Seemingly wrong warnings from -Wnonnull when combined with -O2 -fsanitize=undefined
2020-12-02 22:54 [Bug middle-end/98109] New: Seemingly wrong warnings from -Wnonnull when combined with -O2 -fsanitize=undefined gabravier at gmail dot com
@ 2020-12-03 1:08 ` msebor at gcc dot gnu.org
2021-05-19 10:44 ` jlegg at feralinteractive dot com
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: msebor at gcc dot gnu.org @ 2020-12-03 1:08 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98109
Martin Sebor <msebor at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
Last reconfirmed| |2020-12-03
Ever confirmed|0 |1
Keywords| |diagnostic
CC| |msebor at gcc dot gnu.org
Blocks| |95507
Status|UNCONFIRMED |NEW
--- Comment #1 from Martin Sebor <msebor at gcc dot gnu.org> ---
The warings are caused by the null tests inserted by the sanitizer that jump
threading turns into calls with constant nulls. See below. Adding attribute
nonnull also to swap_1000 avoids both the warnings and the sanitization.
This is a known problem with the sanitizer and the late warnings and there
probably is a report like this one in Bugzilla somewhere. I suppose the
warning code could look for calls __builtin___ubsan_handle_nonnull_arg (and
similar) preceding the statement it's about to diagnose and avoid triggering if
it's found. Until something like this is implemented the guidance is to live
with these warnings when using the sanitizer or suppress them by -Wno-xxx.
$ gcc -O2 -S -Wall -fsanitize=undefined -fdump-tree-ubsan=/dev/stdout
-fdump-tree-dom2=/dev/stdout pr98109.c
;; Function swap_1000 (swap_1000, funcdef_no=0, decl_uid=2388, cgraph_uid=1,
symbol_order=0)
Introduced new external node (__builtin___ubsan_handle_nonnull_arg/3).
Symbols to be put in SSA form
{ D.2392 }
Incremental SSA update started at block: 0
Number of blocks in CFG: 15
Number of blocks to update: 14 ( 93%)
void swap_1000 (char * elem1, char * elem2, size_t element_size)
{
char buffer[1000];
<bb 2> :
if (&buffer == 0B)
goto <bb 4>; [0.05%]
else
goto <bb 3>; [99.95%]
<bb 4> :
__builtin___ubsan_handle_nonnull_arg (&*.Lubsan_data0);
<bb 3> :
if (elem1_2(D) == 0B)
goto <bb 6>; [0.05%]
else
goto <bb 5>; [99.95%]
<bb 6> :
__builtin___ubsan_handle_nonnull_arg (&*.Lubsan_data1);
<bb 5> :
my_memcpy (&buffer, elem1_2(D), 1000);
if (elem1_2(D) == 0B)
goto <bb 8>; [0.05%]
else
goto <bb 7>; [99.95%]
<bb 8> :
__builtin___ubsan_handle_nonnull_arg (&*.Lubsan_data2);
<bb 7> :
if (elem2_4(D) == 0B)
goto <bb 10>; [0.05%]
else
goto <bb 9>; [99.95%]
<bb 10> :
__builtin___ubsan_handle_nonnull_arg (&*.Lubsan_data3);
<bb 9> :
my_memcpy (elem1_2(D), elem2_4(D), 1000);
if (elem2_4(D) == 0B)
goto <bb 12>; [0.05%]
else
goto <bb 11>; [99.95%]
<bb 12> :
__builtin___ubsan_handle_nonnull_arg (&*.Lubsan_data4);
<bb 11> :
if (&buffer == 0B)
goto <bb 14>; [0.05%]
else
goto <bb 13>; [99.95%]
<bb 14> :
__builtin___ubsan_handle_nonnull_arg (&*.Lubsan_data5);
<bb 13> :
my_memcpy (elem2_4(D), &buffer, 1000);
buffer ={v} {CLOBBER};
return;
}
;; Function swap_1000 (swap_1000, funcdef_no=0, decl_uid=2388, cgraph_uid=1,
symbol_order=0)
;; 1 loops found
;;
;; Loop 0
;; header 0, latch 1
;; depth 0, outer -1
;; nodes: 0 1 2 3 4 5 6 7 8
;; 2 succs { 8 3 }
;; 3 succs { 4 }
;; 4 succs { 7 5 }
;; 5 succs { 6 }
;; 6 succs { 1 }
;; 7 succs { 6 }
;; 8 succs { 4 }
void swap_1000 (char * elem1, char * elem2, size_t element_size)
{
char buffer[1000];
<bb 2> [local count: 1073741824]:
if (elem1_2(D) == 0B)
goto <bb 3>; [0.00%]
else
goto <bb 8>; [100.00%]
<bb 3> [count: 0]:
__builtin___ubsan_handle_nonnull_arg (&*.Lubsan_data1);
my_memcpy (&buffer, 0B, 1000);
__builtin___ubsan_handle_nonnull_arg (&*.Lubsan_data2);
<bb 4> [local count: 1073741824]:
if (elem2_4(D) == 0B)
goto <bb 5>; [0.00%]
else
goto <bb 7>; [100.00%]
<bb 5> [count: 0]:
__builtin___ubsan_handle_nonnull_arg (&*.Lubsan_data3);
my_memcpy (elem1_2(D), 0B, 1000);
__builtin___ubsan_handle_nonnull_arg (&*.Lubsan_data4);
<bb 6> [local count: 1073741824]:
my_memcpy (elem2_4(D), &buffer, 1000);
buffer ={v} {CLOBBER};
return;
<bb 7> [local count: 1073741824]:
my_memcpy (elem1_2(D), elem2_4(D), 1000);
goto <bb 6>; [100.00%]
<bb 8> [local count: 1073741824]:
my_memcpy (&buffer, elem1_2(D), 1000);
goto <bb 4>; [100.00%]
}
pr98109.c: In function ‘swap_1000’:
pr98109.c:11:5: warning: argument 2 is null but the corresponding size argument
3 value is 1000 [-Wnonnull]
11 | my_memcpy(buffer, elem1, 1000);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pr98109.c:3:7: note: in a call to function ‘my_memcpy’ declared with attribute
‘access (read_only, 2, 3)’
3 | void *my_memcpy(void *destination, const void *source, size_t size)
| ^~~~~~~~~
pr98109.c:12:5: warning: argument 2 is null but the corresponding size argument
3 value is 1000 [-Wnonnull]
12 | my_memcpy(elem1, elem2, 1000);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pr98109.c:3:7: note: in a call to function ‘my_memcpy’ declared with attribute
‘access (read_only, 2, 3)’
3 | void *my_memcpy(void *destination, const void *source, size_t size)
| ^~~~~~~~~
Referenced Bugs:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95507
[Bug 95507] [meta-bug] bogus/missing -Wnonnull
^ permalink raw reply [flat|nested] 6+ messages in thread
* [Bug middle-end/98109] Seemingly wrong warnings from -Wnonnull when combined with -O2 -fsanitize=undefined
2020-12-02 22:54 [Bug middle-end/98109] New: Seemingly wrong warnings from -Wnonnull when combined with -O2 -fsanitize=undefined gabravier at gmail dot com
` (2 preceding siblings ...)
2021-05-19 16:02 ` msebor at gcc dot gnu.org
@ 2022-07-31 9:02 ` b.buschinski at googlemail dot com
2022-08-01 22:01 ` msebor at gcc dot gnu.org
4 siblings, 0 replies; 6+ messages in thread
From: b.buschinski at googlemail dot com @ 2022-07-31 9:02 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98109
Bernd Buschinski <b.buschinski at googlemail dot com> changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |b.buschinski at googlemail dot com
--- Comment #4 from Bernd Buschinski <b.buschinski at googlemail dot com> ---
I also hit this problem, but not 100% sure if this is a duplicate or not.
Because as far as I can remember it used to work with GCC-11 (can not test now
only have 12) and only started failing with GCC 12.
Can someone tell me if this should be a new bug or is just a duplicate?
Known to fail on:
- sys-devel/gcc-12.1.1_p20220625 (Gentoo)
- gcc-12.1.1-1.fc36.x86_64 12.1.1 20220507 (Red Hat 12.1.1-1) (Fedora)
- 12-20220319-1ubuntu1 (Ubuntu 22.04)
Compiler explorer: https://godbolt.org/z/rrWffMe9x
Code:
#include <stdlib.h>
extern void *my_memmem(const void *__haystack, size_t __haystacklen,
const void *__needle, size_t __needlelen)
__THROW __attribute_pure__ __nonnull ((1, 3))
__attribute__((access(__read_only__, 1, 2)))
__attribute__((access(__read_only__, 3, 4)));
#define CONTAINSCONST(_cstring, string)
\
({
\
size_t const tmp_CONST_LEN = sizeof(string) - 1;
\
((_cstring).length >= tmp_CONST_LEN &&
\
(my_memmem((_cstring).buffer, (_cstring).length, string, tmp_CONST_LEN) !=
\
NULL));
\
})
struct my_string {
unsigned char *buffer;
unsigned long long length;
};
int foo(struct my_string const *const ss) {
struct my_string const str_path = *ss;
if (CONTAINSCONST(str_path, "/") ||
CONTAINSCONST(str_path, ".abcd") ||
CONTAINSCONST(str_path, "?")) {
return 1;
}
return 0;
}
// $ gcc -std=gnu99 -Wall -Wextra -Walloc-zero -O2 -fsanitize=undefined -Werror
test2.c -S
// test2.c: In function 'foo':
// test2.c:13:7: error: argument 1 is null but the corresponding size argument
2 value is [5, 18446744073709551615] [-Werror=nonnull]
// 13 | (my_memmem((_cstring).buffer, (_cstring).length, string,
tmp_CONST_LEN) != \
// |
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// test2.c:26:7: note: in expansion of macro 'CONTAINSCONST'
// 26 | CONTAINSCONST(str_path, ".abcd") ||
// | ^~~~~~~~~~~~~
// test2.c:3:14: note: in a call to function 'my_memmem' declared with
attribute 'access (read_only, 3, 4)'
// 3 | extern void *my_memmem(const void *__haystack, size_t __haystacklen,
// | ^~~~~~~~~
// cc1: all warnings being treated as errors
^ permalink raw reply [flat|nested] 6+ messages in thread