[Bug middle-end/99578] gcc-11 -Warray-bounds or -Wstringop-overread warning when accessing a pointer from integer literal
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99578 Andrew Pinski changed: What|Removed |Added CC||huntazhang at tencent dot com --- Comment #18 from Andrew Pinski --- *** Bug 102037 has been marked as a duplicate of this bug. ***
[Bug middle-end/99578] gcc-11 -Warray-bounds or -Wstringop-overread warning when accessing a pointer from integer literal
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99578 Martin Sebor changed: What|Removed |Added CC||florian.bezdeka at siemens dot com --- Comment #17 from Martin Sebor --- *** Bug 100834 has been marked as a duplicate of this bug. ***
[Bug middle-end/99578] gcc-11 -Warray-bounds or -Wstringop-overread warning when accessing a pointer from integer literal
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99578 --- Comment #16 from Martin Sebor --- It's the pointer itself that needs to be volatile to keep GCC from determining its value. This shows the difference: $ cat pr99578-15.c && gcc -O2 -S -Wall pr99578-15.c void f (void) { void* ptr = (void *)0x7ff8ul; __builtin_memcpy (ptr, "\x90\x90\xf\xbxen\x90", 8); // warning } void g (void) { void* volatile ptr = (void *)0x7ff8ul; __builtin_memcpy (ptr, "\x90\x90\xf\xbxen\x90", 8); // okay } pr99578-15.c: In function ‘f’: pr99578-15.c:4:3: warning: ‘__builtin_memcpy’ offset [0, 7] is out of the bounds [0, 0] [-Warray-bounds] 4 | __builtin_memcpy (ptr, "\x90\x90\xf\xbxen\x90", 8); // warning | ^~ Alternatively, store the address a global (modifiable) variable.
[Bug middle-end/99578] gcc-11 -Warray-bounds or -Wstringop-overread warning when accessing a pointer from integer literal
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99578 --- Comment #15 from Andrew Cooper --- (In reply to Martin Sebor from comment #1) > For now, I recommend suppressing the warning either by #pragma GCC > diagnostic or by making the pointer volatile. Trying this with the code sample from comment 14 doesn't work. Not only does the -Werror=array-bounds diagnostic remain, a second is picked up from: passing argument 1 of ‘__builtin_memcpy’ discards ‘volatile’ qualifier from pointer target type [-Werror=discarded-qualifiers]
[Bug middle-end/99578] gcc-11 -Warray-bounds or -Wstringop-overread warning when accessing a pointer from integer literal
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99578 Andrew Cooper changed: What|Removed |Added CC||andrew.cooper3 at citrix dot com --- Comment #14 from Andrew Cooper --- I too have had what appears to be this bug, raised against a microkernel project. The logic is a test case involving interactions at the x86-64 lower canonical boundary, and reads like so: ... uint64_t *ptr = (void *)0x7ff8ul; memcpy(ptr, "\x90\x90\xf\xbxen\x90", 8); ... This yields: include/xtf/libc.h:36:37: error: ‘__builtin_memcpy’ offset [0, 7] is out of the bounds [0, 0] [-Werror=array-bounds] 36 | #define memcpy(d, s, n) __builtin_memcpy(d, s, n) | ^ main.c:81:5: note: in expansion of macro ‘memcpy’ 81 | memcpy(ptr, "\x90\x90\xf\xbxen\x90", 8); | ^~ It is worth pointing out that it is common for kernels to have some virtual addresses derived from compile-time constants, notably the fixmap and frametable.
[Bug middle-end/99578] gcc-11 -Warray-bounds or -Wstringop-overread warning when accessing a pointer from integer literal
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99578 Martin Sebor changed: What|Removed |Added CC||jbeulich at suse dot com --- Comment #13 from Martin Sebor --- *** Bug 100680 has been marked as a duplicate of this bug. ***
[Bug middle-end/99578] gcc-11 -Warray-bounds or -Wstringop-overread warning when accessing a pointer from integer literal
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99578 Andi Kleen changed: What|Removed |Added CC||andi-gcc at firstfloor dot org --- Comment #12 from Andi Kleen --- It looks to me separate bugs are mixed together here. For example I looked at the preallocate_pmd warning again and I don't think there is any union there. Also I noticed that when I replace the *foo[N] with **foo it disappears. So I think that is something different. So there seem to be instances where such warnings happen without union members. Perhaps that one (and perhaps some others) need to be reanalyzed. I also looked at the intel_pm.c and I think that one is a real kernel bug, where the field accessed is really too small. I'll submit a patch for that.
[Bug middle-end/99578] gcc-11 -Warray-bounds or -Wstringop-overread warning when accessing a pointer from integer literal
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99578 Martin Sebor changed: What|Removed |Added CC||sciresm.gccbugzilla at gmail dot c ||om --- Comment #11 from Martin Sebor --- *** Bug 100309 has been marked as a duplicate of this bug. ***
[Bug middle-end/99578] gcc-11 -Warray-bounds or -Wstringop-overread warning when accessing a pointer from integer literal
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99578 Andrew Pinski changed: What|Removed |Added CC||f4bug at amsat dot org --- Comment #10 from Andrew Pinski --- *** Bug 100190 has been marked as a duplicate of this bug. ***
[Bug middle-end/99578] gcc-11 -Warray-bounds or -Wstringop-overread warning when accessing a pointer from integer literal
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99578 --- Comment #9 from Martin Sebor --- (In reply to Richard Biener from comment #7) > Note heuristically 0xe8ffc000 isn't likely such an offset from a NULL > pointer object because the object would be quite large. > > The diagnostic could maybe also clarify that it assumes 0xe8ffc000 is an > offsetted NULL pointer. I can do that in stage 1 when I convert the warning to use the access_ref class (that exposes this information). A better solution we discussed with Jeff is to issue -Wnonnull when a member access through a null pointer is first detected. Using something like __builtin_warning for that would help avoid false positives when this happens early on (in the test case in comment #1 that's in EVRP).
[Bug middle-end/99578] gcc-11 -Warray-bounds or -Wstringop-overread warning when accessing a pointer from integer literal
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99578 --- Comment #8 from Martin Sebor --- (In reply to Arnd Bergmann from comment #6) > I figured out the qnx4 warning in the end: https://godbolt.org/z/hvqjr3 The false positive is a known problem caused by redundancy elimination (the FRE/PRE passes) substituting one member for another when they both refer to the same address. It often happens with union members that share the same starting offset but can also happen with struct members in code that refers to both the end of one and the beginning of the next member with no intervening padding. There's no particular reason why it picks one or the other member (maybe it picks whichever it sees first in some order, I don't know), but the warning only triggers when it substitutes the smaller of the two members in a larger access. In the strnlen test case w/o sanitization it happens to pick the bigger member. This can be seen in the output of -fdump-tree-pre-details: Inserted pretmp_12 = _9(D)->D.2393.D.2392.dl_fname; in predecessor 3 (0004) Replaced _9(D)->D.2393.D.2392.dl_fname with pretmp_12 in all uses of _5 = _9(D)->D.2393.D.2392.dl_fname; Replaced _9(D)->D.2393.D.2389.di_fname with pretmp_12 in all uses of _3 = _9(D)->D.2393.D.2389.di_fname; Removing dead stmt _3 = _9(D)->D.2393.D.2389.di_fname; Removing dead stmt _5 = _9(D)->D.2393.D.2392.dl_fname; The instrumentation introduced by the sanitizers changes the IL in ways that affect the choices made by subsequent transformations. In this case, the sanitizer first inserts a call to __builtin___tsan_read1() to record the access to di_fname[0]. The sanitizers run after PRE but before some FRE iterations. The resulting IL from the thread sanitizer looks like this: [local count: 1073741824]: _13 = __builtin_return_address (0); __builtin___tsan_func_entry (_13); _5 = _9(D)->D.2390.D.2386.di_fname[0]; __builtin___tsan_read1 (_5);<<< record access to di_fname[0] _1 = de_9(D)->D.2390.D.2386.di_fname[0]; if (_1 == 0) goto ; [34.00%] else goto ; [66.00%] [local count: 365072224]: goto ; [100.00%] [local count: 708669601]: _3 = _9(D)->di_status; __builtin___tsan_read1 (_3); _2 = de_9(D)->di_status; pretmp_12 = _9(D)->D.2390.D.2389.dl_fname; <<< temporary added by PRE if (_2 != 0) goto ; [50.00%] else goto ; [50.00%] [local count: 354334800]: _4 = __builtin_strnlen (pretmp_12, 16); _11 = (int) _4; goto ; [100.00%] [local count: 354334800]: _6 = __builtin_strnlen (pretmp_12, 48); _10 = (int) _6; [local count: 1073741824]: # _7 = PHI <0(7), _11(4), _10(5)> __builtin___tsan_func_exit (); return _7; } The IL above is then changed by FRE which replaces dl_fname with di_fname: Value numbering stmt = pretmp_12 = _9(D)->D.2390.D.2389.dl_fname; Setting value number of pretmp_12 to _5 (changed) _5 is available for _5 Replaced _9(D)->D.2390.D.2389.dl_fname with _5 in all uses of pretmp_12 = _9(D)->D.2390.D.2389.dl_fname; The warning is then issued by the strlen pass that runs after FRE5 and that sees the IL below: [local count: 1073741824]: _13 = __builtin_return_address (0); __builtin___tsan_func_entry (_13); _5 = _9(D)->D.2393.D.2389.di_fname[0]; <<< inserted by sanitizer __builtin___tsan_read1 (_5);<<< record access to di_fname[0] _1 = de_9(D)->D.2393.D.2389.di_fname[0];<<< inserted by FRE5 if (_1 == 0) goto ; [34.00%] else goto ; [66.00%] [local count: 708669601]: _3 = _9(D)->di_status; __builtin___tsan_read1 (_3); _2 = de_9(D)->di_status; if (_2 != 0) goto ; [50.00%] else goto ; [50.00%] [local count: 354334800]: _4 = strnlen (_5, 16); _11 = (int) _4; goto ; [100.00%] [local count: 354334800]: _6 = strnlen (_5, 48); <<< -Wstringop-overread _10 = (int) _6; [local count: 1073741824]: # _7 = PHI <0(2), _11(4), _10(5)> __builtin___tsan_func_exit (); return _7; } I'm hoping to change PRE/FRE in GCC 12 to replace the member substitution with one involving + offsetof (type, memer). That will avoid the false positives in these cases with no adverse impact on optimization.
[Bug middle-end/99578] gcc-11 -Warray-bounds or -Wstringop-overread warning when accessing a pointer from integer literal
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99578 Richard Biener changed: What|Removed |Added Status|UNCONFIRMED |NEW Last reconfirmed||2021-03-15 Blocks||56456 Ever confirmed|0 |1 --- Comment #7 from Richard Biener --- Note heuristically 0xe8ffc000 isn't likely such an offset from a NULL pointer object because the object would be quite large. The diagnostic could maybe also clarify that it assumes 0xe8ffc000 is an offsetted NULL pointer. Referenced Bugs: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56456 [Bug 56456] [meta-bug] bogus/missing -Warray-bounds
[Bug middle-end/99578] gcc-11 -Warray-bounds or -Wstringop-overread warning when accessing a pointer from integer literal
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99578 --- Comment #6 from Arnd Bergmann --- I figured out the qnx4 warning in the end: https://godbolt.org/z/hvqjr3 struct qnx4_inode_entry { char di_status; union { struct { char di_fname[16]; char di_pad[32]; }; struct { char dl_fname[48]; }; }; }; int qnx4_readdir(struct qnx4_inode_entry *de) { if (!de->di_fname[0]) return 0; if (de->di_status) return __builtin_strnlen(de->di_fname, sizeof(de->di_fname)); else return __builtin_strnlen(de->dl_fname, sizeof(de->dl_fname)); return 0; } This produces :22:16: warning: '__builtin_strnlen' specified bound 48 exceeds source size 16 [-Wstringop-overread] because the first access on the object seems to decide which layout is assumed. Changing (!de->di_fname[0]) to (!de->dl_fname[0]) shuts up the warning since that is a longer field. This is probably enough as a workaround, if you can confirm that the behavior of the compiler is also intentional for this input.
[Bug middle-end/99578] gcc-11 -Warray-bounds or -Wstringop-overread warning when accessing a pointer from integer literal
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99578 --- Comment #5 from Arnd Bergmann --- (In reply to Martin Sebor from comment #4) > Most warnings designed to detect invalid accesses (not just > -Wstringop-overread but also -Wstringop-overflow and > -Wformat-overflow/-truncation, -Wrestrict, and some forms of -Warray-bounds) > use the same underlying code to determine the identity of the accessed > object, so they all should trigger if they see a constant address. Right, makes sense. > But I tested the warning with the kernel when I implemented it months ago > and don't think I saw any instances of it (though I don't see sharpsl_param > in any of my logs). I still don't. How many do you see? > > Here's the list of -Wstringop- warnings in my fresh build but I'm never sure > I use the right target. Is allyesconfig the right one? For brief testing I usually test 'allmodconfig', which has slightly better coverage and is much faster to build than 'allyesconfig'. However, most of my testing is on random configurations, with a lot of patches on top to address all the known warnings. The sharpsl_param only shows up in unusual builds since this is a legacy Arm platform that needs a custom kernel configuration and is incompatible with normal armv5 builds. Some of these tend to only show up with certain combinations of the various sanitizers and inlining decisions such as -O2 vs -Os. > $ grep Wstringop-over /src/linux-stable/gcc-master.log > arch/x86/mm/pgtable.c:437:13: warning: ‘preallocate_pmds.constprop’ > accessing 8 bytes in a region of size 0 [-Wstringop-overflow=] > arch/x86/mm/pgtable.c:440:13: warning: ‘preallocate_pmds.constprop’ > accessing 8 bytes in a region of size 0 [-Wstringop-overflow=] > arch/x86/mm/pgtable.c:462:9: warning: ‘free_pmds.constprop’ accessing 8 > bytes in a region of size 0 [-Wstringop-overflow=] > arch/x86/mm/pgtable.c:455:9: warning: ‘pgd_prepopulate_user_pmd’ accessing 8 > bytes in a region of size 0 [-Wstringop-overflow=] > arch/x86/mm/pgtable.c:464:9: warning: ‘free_pmds.constprop’ accessing 8 > bytes in a region of size 0 [-Wstringop-overflow=] I don't see these at the moment, maybe the kernel already got fixed for them. > mm/mempolicy.c:3001:26: warning: writing 1 byte into a region of size 0 > [-Wstringop-overflow=] Nor this one. > drivers/gpu/drm/i915/intel_pm.c:3093:9: warning: ‘intel_read_wm_latency’ > accessing 16 bytes in a region of size 10 [-Wstringop-overflow=] > drivers/gpu/drm/i915/intel_pm.c:3057:9: warning: ‘intel_print_wm_latency’ > reading 16 bytes from a region of size 10 [-Wstringop-overread] This looks like a reasonable warning in principle, though I think the code is still correct. I have a patch for this. > drivers/gpu/drm/i915/display/intel_dp.c:4556:22: warning: > ‘drm_dp_channel_eq_ok’ reading 6 bytes from a region of size 4 > [-Wstringop-overread] Different bug, similar verdict: I have a patch to work around it, it seems reasonable to warn about it, but I think the code is correct. Here is one that got added in gcc-11 I just couldn't figure out: https://godbolt.org/z/sjjGc9 On this one I understand why gcc warns (pointer is compared to known constant address), but the code is correct and I don't know how to rework the code other than using #pragma to turn off the warning: In file included from arch/x86/boot/compressed/misc.c:18: In function ‘parse_elf’, inlined from ‘extract_kernel’ at arch/x86/boot/compressed/misc.c:442:2: arch/x86/boot/compressed/../string.h:15:23: error: ‘__builtin_memcpy’ reading 64 bytes from a region of size 0 [-Werror=stringop-overread] 15 | #define memcpy(d,s,l) __builtin_memcpy(d,s,l) | ^~~ arch/x86/boot/compressed/misc.c:283:9: note: in expansion of macro ‘memcpy’ 283 | memcpy(, output, sizeof(ehdr)); | ^~ This one is correct code, but has a simple workaround that does not make the code any uglier: security/commoncap.c: In function ‘cap_inode_getsecurity’: security/commoncap.c:440:33: error: ‘memcpy’ reading 16 bytes from a region of size 0 [-Werror=stringop-overread] 440 | memcpy(>data, >data, sizeof(__le32) * 2 * VFS_CAP_U32); | - if (ret < 0) + if (ret < 0 || !tmpbuf) I also got this one (with -Warray-bounds, but seems related) that looks like a real bug in the kernel: net/core/skbuff.c: In function ‘skb_find_text’: net/core/skbuff.c:3498:26: error: array subscript ‘struct skb_seq_state[0]’ is partly outside array bounds of ‘struct ts_state[1]’ [-Werror=array-bounds] I have a patch, but it needs to be discussed first. > The full breakdown with the warnings forcefully disabled in the top-level > Makefile re-enabled is below: > > DiagnosticCount UniqueFiles > -Wmissing-prototypes759 248 114 > -Wunused-const-variable=391 233 31
[Bug middle-end/99578] gcc-11 -Warray-bounds or -Wstringop-overread warning when accessing a pointer from integer literal
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99578 Martin Sebor changed: What|Removed |Added Component|c |middle-end Keywords||diagnostic --- Comment #4 from Martin Sebor --- Most warnings designed to detect invalid accesses (not just -Wstringop-overread but also -Wstringop-overflow and -Wformat-overflow/-truncation, -Wrestrict, and some forms of -Warray-bounds) use the same underlying code to determine the identity of the accessed object, so they all should trigger if they see a constant address. But I tested the warning with the kernel when I implemented it months ago and don't think I saw any instances of it (though I don't see sharpsl_param in any of my logs). I still don't. How many do you see? Here's the list of -Wstringop- warnings in my fresh build but I'm never sure I use the right target. Is allyesconfig the right one? $ grep Wstringop-over /src/linux-stable/gcc-master.log arch/x86/mm/pgtable.c:437:13: warning: ‘preallocate_pmds.constprop’ accessing 8 bytes in a region of size 0 [-Wstringop-overflow=] arch/x86/mm/pgtable.c:440:13: warning: ‘preallocate_pmds.constprop’ accessing 8 bytes in a region of size 0 [-Wstringop-overflow=] arch/x86/mm/pgtable.c:462:9: warning: ‘free_pmds.constprop’ accessing 8 bytes in a region of size 0 [-Wstringop-overflow=] arch/x86/mm/pgtable.c:455:9: warning: ‘pgd_prepopulate_user_pmd’ accessing 8 bytes in a region of size 0 [-Wstringop-overflow=] arch/x86/mm/pgtable.c:464:9: warning: ‘free_pmds.constprop’ accessing 8 bytes in a region of size 0 [-Wstringop-overflow=] mm/mempolicy.c:3001:26: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] mm/mempolicy.c:3001:26: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] mm/mempolicy.c:3001:26: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] mm/mempolicy.c:3001:26: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] mm/mempolicy.c:3001:26: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] mm/mempolicy.c:3001:26: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] drivers/gpu/drm/i915/intel_pm.c:3093:9: warning: ‘intel_read_wm_latency’ accessing 16 bytes in a region of size 10 [-Wstringop-overflow=] drivers/gpu/drm/i915/intel_pm.c:3057:9: warning: ‘intel_print_wm_latency’ reading 16 bytes from a region of size 10 [-Wstringop-overread] drivers/gpu/drm/i915/intel_pm.c:3058:9: warning: ‘intel_print_wm_latency’ reading 16 bytes from a region of size 10 [-Wstringop-overread] drivers/gpu/drm/i915/intel_pm.c:3059:9: warning: ‘intel_print_wm_latency’ reading 16 bytes from a region of size 10 [-Wstringop-overread] drivers/gpu/drm/i915/intel_pm.c:3086:9: warning: ‘intel_print_wm_latency’ reading 16 bytes from a region of size 10 [-Wstringop-overread] drivers/gpu/drm/i915/intel_pm.c:3087:9: warning: ‘intel_print_wm_latency’ reading 16 bytes from a region of size 10 [-Wstringop-overread] drivers/gpu/drm/i915/intel_pm.c:3088:9: warning: ‘intel_print_wm_latency’ reading 16 bytes from a region of size 10 [-Wstringop-overread] drivers/gpu/drm/i915/intel_pm.c:3103:9: warning: ‘intel_print_wm_latency’ reading 16 bytes from a region of size 10 [-Wstringop-overread] drivers/gpu/drm/i915/intel_pm.c:3104:9: warning: ‘intel_print_wm_latency’ reading 16 bytes from a region of size 10 [-Wstringop-overread] drivers/gpu/drm/i915/intel_pm.c:3105:9: warning: ‘intel_print_wm_latency’ reading 16 bytes from a region of size 10 [-Wstringop-overread] drivers/gpu/drm/i915/display/intel_dp.c:4556:22: warning: ‘drm_dp_channel_eq_ok’ reading 6 bytes from a region of size 4 [-Wstringop-overread] The full breakdown with the warnings forcefully disabled in the top-level Makefile re-enabled is below: DiagnosticCount UniqueFiles -Wmissing-prototypes759 248 114 -Wunused-const-variable=391 233 31 -Wformat-truncation=311 297 229 -Wmaybe-uninitialized 158 133 103 -Wunused-but-set-variable 143 137 88 -Warray-bounds 94 32 12 -Wzero-length-bounds 69 66 16 -Wsuggest-attribute=format 60 26 21 -Wnested-externs 4111 -Woverride-init 36 22 15 -Wrestrict 23 14 10 -Wformat-overflow= 20 19 15 -Wempty-body 15 158 -Wstringop-overflow= 1273 -Wmisleading-indentation 1122 -Wcast-function-type 1122 -Wstringop-overread 10 102 -Wenum-conversion