Description of problem: "man g++" says: -Warray-bounds -Warray-bounds=n This option is only active when -ftree-vrp is active (default for -O2 and above). It warns about subscripts to arrays that are always out of bounds. This warning is enabled by -Wall. -Warray-bounds=1 This is the warning level of -Warray-bounds and is enabled by -Wall; higher levels are not, and must be explicitly requested. -Warray-bounds=2 This warning level also warns about out of bounds access for arrays at the end of a struct and for arrays accessed through pointers. This warning level may give a larger number of false positives and is deactivated by default. i.e. the default enabled by -Wall, should not warn about arrays at the end of a struct. During the compilation of xrootd, package this does not seem to be true for gcc 12. /builddir/build/BUILD/xrootd-5.4.0/src/XrdFrm/XrdFrmMonitor.cc: In function 'XrdFrmMonitor::Init(char const*, char const*, char const*)': /builddir/build/BUILD/xrootd-5.4.0/src/XrdFrm/XrdFrmMonitor.cc:158:12: warning: array subscript 'struct XrdXrootdMonMap[0]' is partly outside array bounds of 'unsigned char[1036]' [-Warray-bounds] 158 | mP->hdr.pseq = 0; | ~~~~~~~~^~~~ /builddir/build/BUILD/xrootd-5.4.0/src/XrdFrm/XrdFrmMonitor.cc:155:26: note: object of size [13, 1036] allocated by 'malloc' 155 | idRec = (char *)malloc(idLen+1); | ~~~~~~^~~~~~~~~ /builddir/build/BUILD/xrootd-5.4.0/src/XrdFrm/XrdFrmMonitor.cc:159:8: warning: array subscript 'struct XrdXrootdMonMap[0]' is partly outside array bounds of 'unsigned char[1036]' [-Warray-bounds] 159 | mP->dictid = 0; | ~~~~^~~~~~ /builddir/build/BUILD/xrootd-5.4.0/src/XrdFrm/XrdFrmMonitor.cc:155:26: note: object of size [13, 1036] allocated by 'malloc' 155 | idRec = (char *)malloc(idLen+1); | ~~~~~~^~~~~~~~~ Lines 154-160 of file src/XrdFrm/XrdFrmMonitor.cc is: idLen = strlen(iBuff) + sizeof(XrdXrootdMonHeader) + sizeof(kXR_int32); idRec = (char *)malloc(idLen+1); mP = (XrdXrootdMonMap *)idRec; fillHeader(&(mP->hdr), XROOTD_MON_MAPIDNT, idLen); mP->hdr.pseq = 0; mP->dictid = 0; strcpy(mP->info, iBuff); The struct XrdXrootdMonMap is defined as: struct XrdXrootdMonMap {XrdXrootdMonHeader hdr; kXR_unt32 dictid; char info[1024+256]; }; The calculation of idLen includes the sizes of the members at the start of the struct and the length of the string that will be saved in "info". In the call to malloc +1 is added for the \0 byte at the end of the string. gcc 12 emits warnings for the assignments of hdr.pseq and dictid, which are within the initial fixed size of the struct. Interestingly, it correctly does not warn about the strcpy into the variable size string at the end of the struct. The way I understand the documentation, the compiler should not warn here. And previous versions of gcc did not do that. 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 -Warray-bounds warning Expected results: No such warning Additional info: The xrootd build in koji is here: https://koji.fedoraproject.org/koji/buildinfo?buildID=1903276
This instance of -Warray-bounds usually triggers when accessing an object of a smaller size through a pointer to a larger type. Based on the warning, the code snippet in comment #0: idLen = strlen(iBuff) + sizeof(XrdXrootdMonHeader) + sizeof(kXR_int32); idRec = (char *)malloc(idLen+1); mP = (XrdXrootdMonMap *)idRec; fillHeader(&(mP->hdr), XROOTD_MON_MAPIDNT, idLen); mP->hdr.pseq = 0; mP->dictid = 0; allocates an array smaller than sizeof (XrdXrootdMonMap) and then uses a XrdXrootdMonMap pointer to access an object of that type in the allocated space. That's not strictly valid and it's what the warning is designed to point out. See GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102151 for additional background. If this doesn't accurately reflect the problem in xrootd please attach a preprocessing translation unit (the result of -E) along with the GCC command line options needed to reproduce the warning.
What you say is correct, and I already said this in the original description - though maybe not very clearly. My complaint is that according to the description on the "man g++" page - at least the way I understand it, -Warray-bounds should not complain about array bounds of an array at the end of a struct when the struct is accessed through a pointer at the default level, i.e. -Warray-bounds or -Warray-bounds=1 - which is enabled by -Wall. Such warnings should only happen with -Warray-bounds=2. The allocated memory here is smaller than the result of sizeof of the struct, but the last member of the struct is an array, so this should be OK and not trigger a warning with -Warray-bounds or -Warray-bounds=1 (though it should trigger a warning with -Warray-bounds=2).
(In reply to Mattias Ellert from comment #2) > The allocated memory here is smaller than the result of sizeof of the > struct, Then that's a bug. > but the last member of the struct is an array, so this should be OK No, I think you are reading the docs wrong. -Warray-bounds=1 does not mean that all warnings are disabled if there's an array at the end of the struct. It only means accesses to that array are not checked. If the accesses to the struct *itself* are outside the storage you have malloc'd, that's still going to get a warning with -Warray-bounds=1. And if you didn't even allocate enough space for that struct, then any access through that pointer are wrong.
(In reply to Jonathan Wakely from comment #3) > (In reply to Mattias Ellert from comment #2) > > The allocated memory here is smaller than the result of sizeof of the > > struct, > > Then that's a bug. No it is not a bug, since the allocated memory is sufficient for storing the data that will be copied there. > > but the last member of the struct is an array, so this should be OK > > No, I think you are reading the docs wrong. -Warray-bounds=1 does not mean > that all warnings are disabled if there's an array at the end of the struct. > It only means accesses to that array are not checked. If the accesses to the > struct *itself* are outside the storage you have malloc'd, that's still > going to get a warning with -Warray-bounds=1. And if you didn't even > allocate enough space for that struct, then any access through that pointer > are wrong. No, I do not expect that all warnings are disabled. That was not the complaint. It just should not give warnings when there is no access to memory outside the allocation. If the allocation was too small to contain mP->hdr.pseq or mP->dictid, then giving a warning when these are assigned would be correct. But now it gives a warning when assigning those members, because the memory allocation does not cover the entire mP->info, a piece of memory not touched by these assignments. The assignment to mP->info with the strcpy, on the following line, correctly does not give a warning because the allocated memory is sufficient for the copy, even though not covering the entire char info[1024+256];
The original purpose of -Warray-bounds=2 is to enable more checking at the cost of more false positives (though it's lost much of that distinction in recent releases). It's not meant to control this aspect of the problem. But it could be argued that this instance of the warning is more about an aliasing violation than about an out of bounds access, so issuing it under the control of an aliasing option like -Wstrict-aliasing might be more appropriate. I submitted a change to that effect upstream a year ago, but unfortunately it wasn't approved. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98503 has some more details.
(In reply to Martin Sebor from comment #5) > The original purpose of -Warray-bounds=2 is to enable more checking at the > cost of more false positives (though it's lost much of that distinction in > recent releases). It's not meant to control this aspect of the problem. According to the description on the man page it is meant to control exactly this aspect of the problem. It is a common programming technique to declare an array as the last member of a struct, and then over- or under-allocate the memory used by the struct to fit the actual number of elements in the array needed by the instance being allocated. The default level -Warray-bounds=1 is supposed to allow this and not warn when this technique is used. If your code is not using this technique you can use -Warray-bounds=2 to get warnings when the allocated memory does not match the size of the array as declared. This techniques is common enough so that the default level enabled by -Wall uses -Warray-bounds=1. Earlier versions of gcc do not trigger this warning in the case reported here, it is a regression in gcc 12 that it issues a warning relevant for -Warray-bounds=2 when -Wall (i.e. -Warray-bounds=1) is used.
GCC supports flexible array members, and as an extension also using trailing zero element arrays. It accepts but explicitly discourages one-element arrays for the same (see https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html). Larger arrays are not supported and -Warray-bounds triggers for them at level 1 since GCC 10. This was an intentional change to help detect bugs, but we didn't update the documentation. I'll take care of that. I would recommend to change the code to avoid the warning. If you can't change it then the warning can be suppressed either by #pragma GCC diagnostic just for the invalid use or on the command line for the whole file.
This bug appears to have been reported against 'rawhide' during the Fedora 36 development cycle. Changing version to 36.
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.
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.