Bug 2047428 - Dubious -Wrestrict warnings from gcc 12
Summary: Dubious -Wrestrict warnings from gcc 12
Keywords:
Status: CLOSED EOL
Alias: None
Product: Fedora
Classification: Fedora
Component: gcc
Version: 36
Hardware: Unspecified
OS: Unspecified
unspecified
unspecified
Target Milestone: ---
Assignee: Jakub Jelinek
QA Contact: Fedora Extras Quality Assurance
URL:
Whiteboard:
: 2057597 (view as bug list)
Depends On:
Blocks: 2045269 2047028
TreeView+ depends on / blocked
 
Reported: 2022-01-27 19:56 UTC by Mattias Ellert
Modified: 2023-09-23 04:25 UTC (History)
14 users (show)

Fixed In Version:
Doc Type: If docs needed, set a value
Doc Text:
Clone Of:
Environment:
Last Closed: 2023-05-25 16:51:44 UTC
Type: Bug
Embargoed:


Attachments (Terms of Use)
Preprocessed code 1 (using --save-temps) (152.70 KB, application/gzip)
2022-02-01 09:29 UTC, Mattias Ellert
no flags Details
Preprocessed code 2 (using --save-temps) (267.78 KB, application/gzip)
2022-02-01 09:30 UTC, Mattias Ellert
no flags Details
Proposed fix (619 bytes, patch)
2022-04-25 16:36 UTC, Mattias Ellert
no flags Details | Diff


Links
System ID Private Priority Status Summary Last Updated
GNU Compiler Collection 104336 0 P3 RESOLVED bogus -Wrestrict for std::string assignment with 2022-05-03 13:44:59 UTC
GNU Compiler Collection 105329 0 P3 NEW [12/13 Regression] Bogus restrict warning when assigning 1-char string literal to std::string since r12-3347-g8af8abfbba... 2022-05-03 13:45:08 UTC

Description Mattias Ellert 2022-01-27 19:56:59 UTC
Description of problem:

During tha compilation of xrood using gcc 12 there are some -Wrestrict warnings I can't make any sense of.


Number 1:

In file included from /usr/include/c++/12/string:40,
                 from /builddir/build/BUILD/xrootd-5.4.0/src/XrdOssCsi/XrdOssCsiConfig.hh:39,
                 from /builddir/build/BUILD/xrootd-5.4.0/src/XrdOssCsi/XrdOssCsiConfig.cc:32:
In function 'std::char_traits<char>::copy(char*, char const*, unsigned long)',
    inlined from 'std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_S_copy(char*, char const*, unsigned long)' at /usr/include/c++/12/bits/basic_string.h:423:21,
    inlined from 'std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_S_copy(char*, char const*, unsigned long)' at /usr/include/c++/12/bits/basic_string.h:418:7,
    inlined from 'std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_replace(unsigned long, unsigned long, char const*, unsigned long)' at /usr/include/c++/12/bits/basic_string.tcc:532:22,
    inlined from 'std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::assign(char const*)' at /usr/include/c++/12/bits/basic_string.h:1647:19,
    inlined from 'std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::operator=(char const*)' at /usr/include/c++/12/bits/basic_string.h:815:28,
    inlined from 'TagPath::calcPrefixElements()' at /builddir/build/BUILD/xrootd-5.4.0/src/XrdOssCsi/XrdOssCsiConfig.hh:135:46:
/usr/include/c++/12/bits/char_traits.h:431:56: warning: 'memcpy' accessing 9223372036854775810 or more bytes at offsets [2, 9223372036854775807] and 1 may overlap up to 9223372036854775813 bytes at offset -3 [-Wrestrict]
  431 |         return static_cast<char_type*>(__builtin_memcpy(__s1, __s2, __n));
      |                                        ~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~

This is the relevant part of the file src/XrdOssCsi/XrdOssCsiConfig.hh

   void calcPrefixElements()
   {
      prefixstart_.clear();
      prefixend_.clear();
      if (prefix_.empty()) return;
      simplePath(prefix_);
      const size_t idx = prefix_.rfind("/");
      prefixstart_ = prefix_.substr(0,idx);
      if (prefixstart_.empty()) prefixstart_="/";  // ← This is line 135
      prefixend_ = prefix_.substr(idx+1,std::string::npos);
   }

Position 46 on line 135 is the starting quote around the string "/".
It is an assignment of the value "/" to a std::string. The resulting memcpy should at most copy 2 bytes (if the copy includes the terminating \0 byte). I don't see how this can cause an overlap.


Number 2:

In file included from /usr/include/c++/12/string:40,
                 from /builddir/build/BUILD/xrootd-5.4.0/src/XrdPfc/XrdPfc.hh:20,
                 from /builddir/build/BUILD/xrootd-5.4.0/src/XrdPfc/XrdPfcPurge.cc:1:
In function 'std::char_traits<char>::copy(char*, char const*, unsigned long)',
    inlined from 'std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_S_copy(char*, char const*, unsigned long)' at /usr/include/c++/12/bits/basic_string.h:423:21,
    inlined from 'std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_S_copy(char*, char const*, unsigned long)' at /usr/include/c++/12/bits/basic_string.h:418:7,
    inlined from 'std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_replace(unsigned long, unsigned long, char const*, unsigned long)' at /usr/include/c++/12/bits/basic_string.tcc:532:22,
    inlined from 'std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::assign(char const*)' at /usr/include/c++/12/bits/basic_string.h:1647:19,
    inlined from 'std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::operator=(char const*)' at /usr/include/c++/12/bits/basic_string.h:815:28,
    inlined from 'XrdPfc::FPurgeState::begin_traversal(XrdPfc::DirState*, char const*)' at /builddir/build/BUILD/xrootd-5.4.0/src/XrdPfc/XrdPfcPurge.cc:279:24,
    inlined from 'XrdPfc::Cache::Purge()' at /builddir/build/BUILD/xrootd-5.4.0/src/XrdPfc/XrdPfcPurge.cc:829:39:
/usr/include/c++/12/bits/char_traits.h:431:56: warning: 'memcpy' accessing 9223372036854775810 or more bytes at offsets -4611686018427387902 and [-4611686018427387903, 4611686018427387904] may overlap up to 9223372036854775813 bytes at offset -3 [-Wrestrict]
  431 |         return static_cast<char_type*>(__builtin_memcpy(__s1, __s2, __n));
      |                                        ~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~

This is the relevant part of the file src/XrdPfc/XrdPfcPurge.cc:

   void begin_traversal(DirState *root, const char *root_path = "/")
   {
      m_dir_state = root;
      m_dir_level = 0;
      m_current_path = root_path;      // ← This is line 279
      m_dir_usage_stack.push_back(0);

      TRACE_PURGE("FPurgeState::begin_traversal cur_path '" << m_current_path <\
< "', usage=" << m_dir_usage_stack.back() << ", level=" << m_dir_level);
   }

Position 24 on line 279 is the "r" in the filename "root_path".

The last line of the trace says this method is called form line 829, which reads:

            purgeState.begin_traversal(m_fs_state->get_root());

i.e. it is called with one argument and the second argument "root_path" get the default value, which is "/". So again this is an assignment of a the value "/" to a std::string. I don't see how this can cause an overlap.


Version-Release number of selected component (if applicable):

gcc-c++-12.0.1-0.3.fc36

How reproducible:

Always.

Steps to Reproduce:
1. Build xrootd for Fedora 36

Actual results:

Strange -Wrestrict warnings

Expected results:

No such warnings

Additional info:

The xrootd build in koji is here:

https://koji.fedoraproject.org/koji/buildinfo?buildID=1903276

Comment 1 Martin Sebor 2022-02-01 00:16:50 UTC
We'll need a translation unit for the affected source file (the result of compiling with -E) to reproduce the warning to fully analyze it.  My best guess is that the warning points out code that was isolated by some GCC optimization and that's either unreachable, or reachable under unlikely conditions that aren't obvious from the source.  We have seen and suppressed similar warnings issued for code defined in libstdc++ headers and inlined into user programs, but I don't think -Wrestrict was among those.

Comment 2 Mattias Ellert 2022-02-01 09:29:44 UTC
Created attachment 1858279 [details]
Preprocessed code 1 (using --save-temps)

Comment 3 Mattias Ellert 2022-02-01 09:30:54 UTC
Created attachment 1858282 [details]
Preprocessed code 2 (using --save-temps)

Comment 4 Martin Sebor 2022-02-01 21:25:46 UTC
The reduced test case below reproduces a similar warning with -O2 -D_GLIBCXX_ASSERTIONS.  It's a false positive precipitated by a call to std::string::_M_disjunct() function made to handle self-insertion.  GCC's alias analysis isn't "intelligent" enough to rule out the possibility that the "/" literal overlaps with s's buffer, so both branches of libstdc++ code, one to handle the overlapping case, and the nonoverlapping one, are emitted.  The overlapping one is the one that triggers the warning.  We worked around a similar problem before (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98465) and looks like we might need to again.  Longer term, we need to make GCC alias analysis smarter.

I've raised https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104336 upstream.

std::string s;

void f (void)
{
  s = "/";
}

In file included from /build/gcc-master/x86_64-pc-linux-gnu/libstdc++-v3/include/string:40,
                 from t.C:1:
In static member function ‘static std::char_traits<char>::char_type* std::char_traits<char>::copy(char_type*, const char_type*, std::size_t)’,
    inlined from ‘static void std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::_S_copy(_CharT*, const _CharT*, size_type) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]’ at /build/gcc-master/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/basic_string.h:423:21,
    inlined from ‘static void std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::_S_copy(_CharT*, const _CharT*, size_type) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]’ at /build/gcc-master/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/basic_string.h:418:7,
    inlined from ‘std::__cxx11::basic_string<_CharT, _Traits, _Alloc>& std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::_M_replace(size_type, size_type, const _CharT*, size_type) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]’ at /build/gcc-master/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/basic_string.tcc:532:22,
    inlined from ‘std::__cxx11::basic_string<_CharT, _Traits, _Alloc>& std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::assign(const _CharT*) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]’ at /build/gcc-master/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/basic_string.h:1647:19,
    inlined from ‘std::__cxx11::basic_string<_CharT, _Traits, _Alloc>& std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::operator=(const _CharT*) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]’ at /build/gcc-master/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/basic_string.h:815:28,
    inlined from ‘void f()’ at t.C:7:7:
/build/gcc-master/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/char_traits.h:431:56: warning: ‘void* __builtin_memcpy(void*, const void*, long unsigned int)’ accessing 9223372036854775810 or more bytes at offsets -4611686018427387902 and [-4611686018427387903, 4611686018427387904] may overlap up to 9223372036854775813 bytes at offset -3 [-Wrestrict]
  431 |         return static_cast<char_type*>(__builtin_memcpy(__s1, __s2, __n));
      |                                        ~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~

Comment 5 Ben Cotton 2022-02-08 20:21:22 UTC
This bug appears to have been reported against 'rawhide' during the Fedora 36 development cycle.
Changing version to 36.

Comment 6 Artur Frenszek-Iwicki 2022-02-10 19:30:16 UTC
Marking this as blocking colobot's and spirv-tools's FTBFS bugs, as both these packages build with -Werror by default and had their builds fail because of the memcpy warning.

Comment 7 Jonathan Wakely 2022-02-11 12:10:09 UTC
IMHO if a package chooses to build with -Werror then that package needs to be prepared to use -Wno-error=xxx for specific warnings.

GCC doesn't force any package to use -Werror.

Comment 8 Artur Frenszek-Iwicki 2022-02-11 12:23:36 UTC
I mean, in the case of Colobot, it's upstream preference set in CMakeLists.txt.
Those can, of course, be patched to either remove -Werror, or add -Wno-error=restrict,
but I'd rather patch the *code*, if possible (and then submit that upstream).

Either way, I plan on waiting a bit to see the response on the gcc bug report.

Comment 9 Jakub Jelinek 2022-02-11 16:24:54 UTC
Warnings can be disabled with pragmas in the code too etc. Using -Werror means one needs to be prepared to deal with warnings, and also accept that some warnings are false positives and be able to work around them.

Comment 10 Dave Airlie 2022-02-15 22:23:05 UTC
just FYI I've pragma this in the spirv-tools builds for now.

Comment 11 Daniel Mach 2022-02-23 20:25:25 UTC
*** Bug 2057597 has been marked as a duplicate of this bug. ***

Comment 12 Mattias Ellert 2022-04-25 16:36:53 UTC
Created attachment 1874858 [details]
Proposed fix

Proposed fix:

``` {.diff}
--- usr/include/c++/12/bits/basic_string.tcc.orig	2022-04-14 01:23:43.000000000 +0200
+++ usr/include/c++/12/bits/basic_string.tcc	2022-04-25 16:18:57.028352162 +0200
@@ -527,10 +527,10 @@
 		    }
 		  else
 		    {
-		      const size_type __nleft = (__p + __len1) - __s;
-		      this->_S_move(__p, __s, __nleft);
-		      this->_S_copy(__p + __nleft, __p + __len2,
-				    __len2 - __nleft);
+		      const size_type __nleft = (__s + __len2) - (__p + __len1);
+		      this->_S_move(__p, __s, __len2 - __nleft);
+		      this->_S_copy(__p + __len2 - __nleft, __p + __len2,
+				    __nleft);
 		    }
 		}
 	    }
```

Comment 13 Mattias Ellert 2022-04-30 02:43:30 UTC
Any chance of getting this fixed?

I know it is a false positive warning, and therefore maybe not critical. But it is easy to trigger as the reduced test case in comment #4 shows. And it has been reported twice in upstream's bugzilla already.

Comment 14 Ben Cotton 2023-04-25 16:52:27 UTC
This message is a reminder that Fedora Linux 36 is nearing its end of life.
Fedora will stop maintaining and issuing updates for Fedora Linux 36 on 2023-05-16.
It is Fedora's policy to close all bug reports from releases that are no longer
maintained. At that time this bug will be closed as EOL if it remains open with a
'version' of '36'.

Package Maintainer: If you wish for this bug to remain open because you
plan to fix it in a currently maintained version, change the 'version' 
to a later Fedora Linux version. Note that the version field may be hidden.
Click the "Show advanced fields" button if you do not see it.

Thank you for reporting this issue and we are sorry that we were not 
able to fix it before Fedora Linux 36 is end of life. If you would still like 
to see this bug fixed and are able to reproduce it against a later version 
of Fedora Linux, you are encouraged to change the 'version' to a later version
prior to this bug being closed.

Comment 15 Ludek Smid 2023-05-25 16:51:44 UTC
Fedora Linux 36 entered end-of-life (EOL) status on 2023-05-16.

Fedora Linux 36 is no longer maintained, which means that it
will not receive any further security or bug fix updates. As a result we
are closing this bug.

If you can reproduce this bug against a currently maintained version of Fedora Linux
please feel free to reopen this bug against that version. Note that the version
field may be hidden. Click the "Show advanced fields" button if you do not see
the version field.

If you are unable to reopen this bug, please file a new report against an
active release.

Thank you for reporting this bug and we are sorry it could not be fixed.

Comment 16 Red Hat Bugzilla 2023-09-23 04:25:22 UTC
The needinfo request[s] on this closed bug have been removed as they have been unresolved for 120 days


Note You need to log in before you can comment on or make changes to this bug.