[Bug c/106920] New: -Warray-bound false positive regression with -O2 or -Os
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106920 Bug ID: 106920 Summary: -Warray-bound false positive regression with -O2 or -Os Product: gcc Version: 12.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: npfhrotynz-ptnqh.myvf at noclue dot notk.org Target Milestone: --- Hello, I think I've run into a false positive on this file: https://source.codeaurora.org/external/imx/imx-atf/tree/plat/imx/imx8m/hab.c?h=lf_v2.6 I could trim it down to this #include typedef void hab_rvt_entry_t(void); int main() { hab_rvt_entry_t *a; a = ((hab_rvt_entry_t *)(*(unsigned long *)(0x908))); a(); return 0; } $ gcc -O2 -Warray-bounds -c t.c t.c: In function ‘main’: t.c:7:34: warning: array subscript 0 is outside array bounds of ‘long unsigned int[0]’ [-Warray-bounds] 7 | a = ((hab_rvt_entry_t *)(*(unsigned long *)(0x908))); | ~^~ According to godbolt this passed on 11.3 and starts emitting the warning on 12.1 (it doesn't have 12.0) and still emits it on trunk. Note the warning requires -O2, -O3 or -Os to be emitted. The problem seems to be that it considers an arbitrary address casted to u64* to be a u64[0] ? If so that might be a problem for quite a few embedded products as that is quite common when dealing with hardware registers. (and who doesn't love products that compile with -Werror for release builds...) Thanks!
[Bug c/106920] -Warray-bound false positive regression with -O2 or -Os and constant address
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106920 --- Comment #2 from Dominique Martinet --- Thanks for the very fast reply! since you mentioned null pointers I now see this warning doesn't happen if I try with a larger constant, I just had bad luck that imx-atf uses an address < 4k...? I checked the first dozen of issues from the meta-bug (from start of open bugs list to 86613 included), but there are just too many and didn't see a workaround in the ones I did open. I can see catching bad casts to be useful, but for low level hardware code accessing register addresses directly is the norm -- I'm not too worried now I've noticed the <4k "rule" but there really can't be any assumption made with hardware, as seen here... (And NXP isn't exactly great at working with external entities, I tried reaching out for another compile fix with little success... but that's offtopic.) Well, good to understand the reason behind that warning at least.
[Bug c/106920] -Warray-bound false positive regression with -O2 or -Os and constant address
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106920 --- Comment #5 from Dominique Martinet --- hmm this is a pretty complex topic. My problem like pointed out in https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99578 is more with all the legacy code that I have to deal with, that isn't maintained by anyone, and well the sorry state of embedded systems upstreams in general... So I'm really just sitting there trying to get old code to keep working with my newer gcc version. (I actually wonder why that didn't fail with gcc11, I've been using that for a while...) The solution in that other bug ^ to just not issue warnings for constant addresses is good in general and I was just unlucky that such an address happened below 4k for this code. I don't understand why the ast tree cannot make the difference between a constant address and a constant null pointer macroed to hell, but since that only happens with optimizations enabled I guess some info is lost at that point and there was nothing to do or it would have been done. Anyway, I consider that closed, there's been enough ink spilled in the other thread and thank you all for the quick replies!
[Bug analyzer/103217] New: analyzer false positive on leak warning when using indirect strdup
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103217 Bug ID: 103217 Summary: analyzer false positive on leak warning when using indirect strdup Product: gcc Version: 11.2.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: analyzer Assignee: dmalcolm at gcc dot gnu.org Reporter: npfhrotynz-ptnqh.myvf at noclue dot notk.org Target Milestone: --- Inlining both the reproducer and fanalyzer warning as they are small enough: -- #include #include #include char *xstrdup(const char *src) { char *val = strdup(src); if (!val) abort(); return val; } int main(int argc, char *argv[]) { char *one = NULL, *two = NULL; int rc; while ((rc = getopt(argc, argv, "a:b:")) != -1) { switch (rc) { case 'a': free(one); one = xstrdup(optarg); break; case 'b': free(two); two = xstrdup(optarg); break; } } free(one); free(two); return 0; } -- -- $ gcc -fanalyzer -o t t.c t.c: In function ‘main’: cc1: warning: leak of ‘val’ [CWE-401] [-Wanalyzer-malloc-leak] ‘main’: events 1-4 | |t.c:13:5: | 13 | int main(int argc, char *argv[]) { | | ^~~~ | | | | | (1) entry to ‘main’ |.. | 17 | while ((rc = getopt(argc, argv, "a:b:")) != -1) { | |~~~ | | | | | (2) following ‘true’ branch (when ‘rc != -1’)... | 18 | switch (rc) { | | ~~ | | | | | (3) ...to here |.. | 25 | two = xstrdup(optarg); | | ~~~ | | | | | (4) calling ‘xstrdup’ from ‘main’ | +--> ‘xstrdup’: events 5-9 | |6 | char *xstrdup(const char *src) { | | ^~~ | | | | | (5) entry to ‘xstrdup’ |7 | char *val = strdup(src); | | ~~~ | | | | | (6) allocated here |8 | if (!val) | |~ | || | |(7) assuming ‘val’ is non-NULL | |(8) following ‘false’ branch (when ‘val’ is non-NULL)... |9 | abort(); | 10 | return val; | |~~~ | || | |(9) ...to here | <--+ | ‘main’: event 10 | | 25 | two = xstrdup(optarg); | | ^~~ | | | | | (10) returning to ‘main’ from ‘xstrdup’ | ‘main’: event 11 | |cc1: | (11): ‘val’ leaks here; was allocated at (6) | -- As far as I see the conditions seem to be: - there have to be at least two cases and two variables, adding more than two cases leave the error only on second one; interverting the two makes the error stay on 2nd. Similarly, using the same variable in both cases makes the error go away. - it has to be strdup, replacing strdup with malloc makes the error go away. - it has to be indirected, calling strdup() directly in main (with the same check/abort) makes the error go away. explicit "inline" attribute does not change behaviour. - it doesn't have to be getopt, but there has to be a function call e.g. replacing getopt() with a locally defined iteration function keeps the error, but checking argc/argv directly in the loop makes the error disappear What's also interesting is the event 11 and "(11): ‘val’ leaks here" that points to... nothing at all? There's no line number or any code quoted to refer to. I'm a bit at a loss as to what this could mean, exiting from main? where?
[Bug analyzer/99269] False positive -Wanalyzer-malloc-leak/-Wanalyzer-double-free with -fanalyzer
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99269 Dominique Martinet changed: What|Removed |Added CC||npfhrotynz-ptnqh.myvf@noclu ||e.notk.org --- Comment #1 from Dominique Martinet --- gcc 11.2.1 20210728 (fc34) does not produce any warning with this, so would be tempted to say it's been fixed.
[Bug analyzer/103217] analyzer false positive on leak warning when using indirect strdup
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103217 Dominique Martinet changed: What|Removed |Added Resolution|FIXED |--- Status|RESOLVED|REOPENED --- Comment #4 from Dominique Martinet --- Thanks for the fix! I've compiled gcc from master and can confirm this fixes the warning for the example I provided... But unfortunately it doesn't fix it for my real application, so my reproducer was simplified too much :/ (It fails on this file: https://github.com/cea-hpc/coordinatool/blob/06c5e319e3c934256d51c2af3ba5f7551bac4bff/copytool/coordinatool.c , but this project requires lustre development headers to compile so it's not a good reproducer) Here's a new attempt, this also gives a similar warning without a precise location on gcc master: --- #include #include #include char *xstrdup(const char *src) { char *val = strdup(src); if (!val) abort(); return val; } struct test { char *one, *two; }; int main(int argc, char *argv[]) { struct test *options = calloc(1, sizeof(*options)); int rc; if (!options) abort(); while ((rc = getopt(argc, argv, "a:b:")) != -1) { switch (rc) { case 'a': free(options->one); options->one = xstrdup(optarg); break; case 'b': free(options->two); options->two = xstrdup(optarg); break; } } free(options->one); free(options->two); free(options); return 0; } --- In function ‘main’: cc1: warning: leak of ‘’ [CWE-401] [-Wanalyzer-malloc-leak] ‘main’: events 1-2 | |/tmp/t4.c:16:5: | 16 | int main(int argc, char *argv[]) { | | ^~~~ | | | | | (1) entry to ‘main’ |.. | 19 | if (!options) | |~ | || | |(2) following ‘false’ branch (when ‘options’ is non-NULL)... | ‘main’: event 3 | |cc1: | (3): ...to here | ‘main’: events 4-6 | | 22 | while ((rc = getopt(argc, argv, "a:b:")) != -1) { | |~~^ | | | | | (4) following ‘true’ branch (when ‘rc != -1’)... | 23 | switch (rc) { | | ~~ | | | | | (5) ...to here |.. | 30 | options->two = xstrdup(optarg); | |~~~ | || | |(6) calling ‘xstrdup’ from ‘main’ | +--> ‘xstrdup’: events 7-11 | |5 | char *xstrdup(const char *src) { | | ^~~ | | | | | (7) entry to ‘xstrdup’ |6 | char *val = strdup(src); | | ~~~ | | | | | (8) allocated here |7 | if (!val) | |~ | || | |(9) assuming ‘val’ is non-NULL | |(10) following ‘false’ branch (when ‘val’ is non-NULL)... |8 | abort(); |9 | return val; | |~~~ | || | |(11) ...to here | <--+ | ‘main’: event 12 | | 30 | options->two = xstrdup(optarg); | |^~~ | || | |(12) returning to ‘main’ from ‘xstrdup’ | ‘main’: event 13 | |cc1: | (13): ‘’ leaks here; was allocated at (8) | I'm not sure it's accurate enough for my usecase though: in my project the "option" struct is declared on the stack and not dynamically allocated... and I cannot reproduce with "struct test option = { 0 };" so I'm not sure where this is different; I'll try a bit more and update this ticket if I find a better reproducer. (What do you prefer to move forward -- I've tried reopening the bug but you really fixed something so should I open a new bz instead and keep this resolved?)
[Bug analyzer/103217] analyzer false positive on leak warning when using indirect strdup
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103217 --- Comment #5 from Dominique Martinet --- Ah, this apparently needed the unused fields in the struct, and the extra config_init() call. Here's something trimmed down from the actual program instead of building back up: - #define _POSIX_C_SOURCE 200809L #include #include #include struct state { const char *confpath; const char *host; const char *port; const char *state_dir_prefix; }; static inline char *xstrdup(const char *s) { char *val = strdup(s); if (!val) abort(); return val; } int config_init(struct state *config); int main(int argc, char *argv[]) { int rc; struct state state = { 0 }; config_init(&state); while ((rc = getopt(argc, argv, "H:p:")) != -1) { switch (rc) { case 'H': free((void*)state.host); state.host = xstrdup(optarg); break; case 'p': free((void*)state.port); state.port = xstrdup(optarg); break; } } free((void*)state.host); free((void*)state.port); return rc; } - - /opt/gcc/bin/gcc -fanalyzer -c ../copytool/coordinatool.c In function ‘main’: cc1: warning: leak of ‘’ [CWE-401] [-Wanalyzer-malloc-leak] ‘main’: events 1-4 | |../copytool/coordinatool.c:25:5: | 25 | int main(int argc, char *argv[]) { | | ^~~~ | | | | | (1) entry to ‘main’ |.. | 31 | while ((rc = getopt(argc, argv, "H:p:")) != -1) { | |~~~ | | | | | (2) following ‘true’ branch (when ‘rc != -1’)... | 32 | switch (rc) { | | ~~ | | | | | (3) ...to here |.. | 39 | state.port = xstrdup(optarg); | | ~~~ | | | | | (4) calling ‘xstrdup’ from ‘main’ | +--> ‘xstrdup’: events 5-9 | | 16 | static inline char *xstrdup(const char *s) { | | ^~~ | | | | | (5) entry to ‘xstrdup’ | 17 | char *val = strdup(s); | | ~ | | | | | (6) allocated here | 18 | if (!val) | |~ | || | |(7) assuming ‘val’ is non-NULL | |(8) following ‘false’ branch (when ‘val’ is non-NULL)... | 19 | abort(); | 20 | return val; | |~~~ | || | |(9) ...to here | <--+ | ‘main’: event 10 | | 39 | state.port = xstrdup(optarg); | | ^~~ | | | | | (10) returning to ‘main’ from ‘xstrdup’ | ‘main’: event 11 | |cc1: | (11): ‘’ leaks here; was allocated at (6) | - Thanks!
[Bug analyzer/103217] analyzer false positive on leak warning when using indirect strdup
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103217 --- Comment #10 from Dominique Martinet --- Thank you for this work! I can confirm this indeed fixed the warning in my application as well, time to add a fanalyzer build to my CI :)