Open 0-0x41 opened 1 year ago
For the following case, I made the following two unrelated code changes that will affect the analysis results of the analyzer. Here is the analysis result of this case before doing nothing, please take a look, thanks a lot.
#include "stdio.h"
int main()
{
int b = 1;
int e = 2;
int f = 3;
int t = 4;
int *g[] = {&e, &e};
int *h = &b;
int *l = &f;
int *j = &f;
for (int d = 0; d <= 1; d++)
{
*j = *h && (h = g[d]);
}
for (int c = 0; c <= 1; c++)
for (int i = 0; i <= 1; i++)
{
int k;
printf("NPD_FLAG\n");
k = (l == &l);
}
}
<source>:15:14: warning: dereference of NULL 'h' [CWE-476] [-Wanalyzer-null-dereference]
15 | *j = *h && (h = g[d]);
| ^~
'main': events 1-9
|
| 13 | for (int d = 0; d <= 1; d++)
| | ~~^~~~
| | |
| | (1) following 'true' branch (when 'd != 2')...
| | (5) following 'true' branch (when 'd != 2')...
| | (7) following 'true' branch (when 'd != 2')...
| 14 | {
| 15 | *j = *h && (h = g[d]);
| | ~~~~~~~~~~~~~~~~~~~~~
| | | | | |
| | | | | (3) following 'true' branch...
| | | | (9) dereference of NULL 'h'
| | | (4) ...to here
| | (2) ...to here
| | (6) ...to here
| | (8) ...to here
(1) Comment out the statement printf("NPD_FLAG\n")
in line 22, the NPD warning goes away (https://godbolt.org/z/bzYnPfEos).
(2) The pointer variables l
and j
point to the same address &f
when they are defined. I think the GCC will do some relevant optimization under -O2, so I make a transformation: int *j = &t
, then the NPD warning disappears, but when I add __analyzer_eval(j)
in line 16, the NPD warning appears again. If the added statement is __analyzer_eval(0 == j)
, the NPD warning does not appear (https://godbolt.org/z/sMMsqxGaP).
The assembly code may indicate the root cause.
I have reduce this case to the following one.
Hi, David. I found a problem through the following case that the optimization has side effects on static analysis.
#include "stdio.h"
extern void __analyzer_describe ();
extern void __analyzer_eval ();
extern void __analyzer_dump ();
int main()
{
int b = 1;
int e = 2;
int f = 3;
int *g[] = {&e, &e};
int *h = &b;
int *j = &f;
for (int d = 0; d <= 1; d++)
{
*j = (*h && (h = g[d]));
// __analyzer_dump ();
__analyzer_eval(h==0);
// __analyzer_describe(0,h);
}
printf("NPD_FLAG %d\n", *j);
}
options: -O2 -fanalyzer Output:
<source>: In function 'main':
<source>:19:9: warning: FALSE
19 | __analyzer_eval(h==0);
| ^~~~~~~~~~~~~~~~~~~~~
<source>:19:9: warning: UNKNOWN
<source>:19:9: warning: TRUE
<source>:19:9: warning: TRUE
<source>:19:9: warning: UNKNOWN
<source>:19:9: warning: TRUE
<source>:19:9: warning: TRUE
<source>:19:9: warning: UNKNOWN
<source>:17:15: warning: dereference of NULL 'h' [CWE-476] [-Wanalyzer-null-dereference]
17 | *j = (*h && (h = g[d]));
| ^~
'main': events 1-9
|
| 15 | for (int d = 0; d <= 1; d++)
| | ~~^~~~
| | |
| | (1) following 'true' branch (when 'd != 2')...
| | (5) following 'true' branch (when 'd != 2')...
| | (7) following 'true' branch (when 'd != 2')...
| 16 | {
| 17 | *j = (*h && (h = g[d]));
| | ~~~~~~~~~~~~~~~~~~~~~~~
| | | | | |
| | | | | (3) following 'true' branch...
| | | | (9) dereference of NULL 'h'
| | | (4) ...to here
| | (2) ...to here
| | (6) ...to here
| | (8) ...to here
|
Compiler returned: 0
options : -O1 -fanalyzer Output:
<source>: In function 'main':
<source>:19:9: warning: FALSE
19 | __analyzer_eval(h==0);
| ^~~~~~~~~~~~~~~~~~~~~
<source>:19:9: warning: UNKNOWN
Compiler returned: 0
-O2: https://godbolt.org/z/GeTaeGMaf -O1: https://godbolt.org/z/adnY8aa3K
The problem that __analyzer_eval(h==0);
is computed too many times has been kind of solved?
https://godbolt.org/z/ba941MdM5
GSA optimization related, CSA does not have this problem.
date: 2022-12-11 commit: 8c8ca873216387bc26046615c806b96f0345ff9d args: -O2 -fanalyzer test:
report: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108767 fix: original: