public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug middle-end/98109] New: Seemingly wrong warnings from -Wnonnull when combined with -O2 -fsanitize=undefined
@ 2020-12-02 22:54 gabravier at gmail dot com
  2020-12-03  1:08 ` [Bug middle-end/98109] " msebor at gcc dot gnu.org
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: gabravier at gmail dot com @ 2020-12-02 22:54 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98109

            Bug ID: 98109
           Summary: Seemingly wrong warnings from -Wnonnull when combined
                    with -O2 -fsanitize=undefined
           Product: gcc
           Version: 11.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: middle-end
          Assignee: unassigned at gcc dot gnu.org
          Reporter: gabravier at gmail dot com
  Target Milestone: ---

typedef __SIZE_TYPE__ size_t;

void *my_memcpy(void *destination, const void *source, size_t size)
    __attribute__((nonnull (1, 2)))
    __attribute__((access (write_only, 1, 3))) __attribute__((access
(read_only, 2, 3)));

void swap_1000(char *elem1, char *elem2, size_t element_size)
{
    char buffer[1000];

    my_memcpy(buffer, elem1, 1000);
    my_memcpy(elem1, elem2, 1000);
    my_memcpy(elem2, buffer, 1000);
}

When compiling this with -Wnonnull -O2 -fsanitize=undefined, these warnings are
observed :

test.c: In function ‘swap_1000’:
test.c:11:5: warning: argument 2 is null but the corresponding size argument 3
value is 1000 [-Wnonnull]
   11 |     my_memcpy(buffer, elem1, 1000);
      |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
test.c:3:7: note: in a call to function ‘my_memcpy’ declared with attribute
‘read_only (2, 3)’
    3 | void *my_memcpy(void *destination, const void *source, size_t size)
      |       ^~~~~~~~~
test.c:12:5: warning: argument 2 is null but the corresponding size argument 3
value is 1000 [-Wnonnull]
   12 |     my_memcpy(elem1, elem2, 1000);
      |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
test.c:3:7: note: in a call to function ‘my_memcpy’ declared with attribute
‘read_only (2, 3)’
    3 | void *my_memcpy(void *destination, const void *source, size_t size)
      |       ^~~~~~~~~

^ 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
@ 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
  2020-12-03  1:08 ` [Bug middle-end/98109] " msebor at gcc dot gnu.org
@ 2021-05-19 10:44 ` jlegg at feralinteractive dot com
  2021-05-19 16:02 ` msebor at gcc dot gnu.org
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: jlegg at feralinteractive dot com @ 2021-05-19 10:44 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98109

James Legg <jlegg at feralinteractive dot com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |jlegg at feralinteractive dot com

--- Comment #2 from James Legg <jlegg at feralinteractive dot com> ---
The false positives can often be seen when converting a lambda to a function
pointer at lower optimisation levels too. For example, in g++ 11.1.1,
compiling:
int main()
{
        return static_cast<int (*)(int)>([](int x){ return x; })(0);
}

with -Og -Wall -fsanitize=undefined results in:
/tmp/a.cc: In static member function ‘static constexpr int
main()::<lambda(int)>::_FUN(int)’:
/tmp/a.cc:3:63: warning: ‘this’ pointer is null [-Wnonnull]
    3 |         return static_cast<int (*)(int)>([](int x){ return x; })(0);
      |                                                               ^
/tmp/a.cc:3:42: note: in a call to non-static member function
‘main()::<lambda(int)>’
    3 |         return static_cast<int (*)(int)>([](int x){ return x; })(0);
      |                                          ^

^ 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
  2020-12-03  1:08 ` [Bug middle-end/98109] " msebor at gcc dot gnu.org
  2021-05-19 10:44 ` jlegg at feralinteractive dot com
@ 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: msebor at gcc dot gnu.org @ 2021-05-19 16:02 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98109

--- Comment #3 from Martin Sebor <msebor at gcc dot gnu.org> ---
(In reply to James Legg from comment #2)

This is a different problem from the one reported in comment 0 so I opened a
new bug for it: pr100684.

^ 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

* [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
                   ` (3 preceding siblings ...)
  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: msebor at gcc dot gnu.org @ 2022-08-01 22:01 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98109

--- Comment #5 from Martin Sebor <msebor at gcc dot gnu.org> ---
(In reply to Bernd Buschinski from comment #4)
> Can someone tell me if this should be a new bug or is just a duplicate?

It's the same bug.  The sanitizer transforms the source code into the following
IR (note the 0B argument to my_memmem):

  <bb 8> [local count: 390331996]:
  if (str_path$buffer_7 == 0B)
    goto <bb 9>; [0.00%]
  else
    goto <bb 14>; [100.00%]

  <bb 9> [count: 0]:
  __builtin___ubsan_handle_nonnull_arg (&*.Lubsan_data2);
  _12 = my_memmem (0B, str_path$length_11, ".abcd", 5);   <<< warning here
  if (_12 != 0B)
    goto <bb 18>; [54.59%]
  else
    goto <bb 19>; [45.41%]

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2022-08-01 22:01 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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 ` [Bug middle-end/98109] " msebor at gcc dot gnu.org
2021-05-19 10:44 ` jlegg at feralinteractive dot com
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

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).