Open 0-0x41 opened 1 year ago
I got a false negative error when compiling the following program with gcc(trunk) -fanalyzer -O0 in https://godbolt.org/z/KvoxvPq5c. When I replace the array m
with the variable a
(https://godbolt.org/z/jTzo9bEo9), the NPD appears.
#include "stdio.h"
int main() {
int i = 0;
int *g = &i;
int m[1];
for (int j = 0; j < 1; j++) {
m[j] = 0;
}
if (m[0])
;
else
g = m[i];
printf("NPD_FLAG\n");
*g = 1;
}
Also for this program, I made the following transformations, which produced a false positive. Similarly, when the array m
is replaced by the variable a
, then the false positive disappears (https://godbolt.org/z/cr6EhTYcj).
Here is the analysis result of the program, please take a look, thank you.
#include "stdio.h"
int main() {
int i = 1;
int *g = &i;
int m[1];
for (i = 0; i < 1; i++)
m[i] = 1;
if (m[0])
;
else
g = 0;
printf("NPD_FLAG\n");
*g = 1;
}
<source>:17:8: warning: dereference of NULL 'g' [CWE-476] [-Wanalyzer-null-dereference]
17 | *g = 1;
| ~~~^~~
'main': events 1-8
|
| 7 | for (int j = 0; j < 1; j++){
| | ~~^~~
| | |
| | (1) following 'true' branch (when 'j <= 0')...
| | (3) following 'false' branch (when 'j > 0')...
| 8 | a = 0;
| | ~~~~~
| | |
| | (2) ...to here
|......
| 11 | if (a)
| | ~
| | |
| | (4) ...to here
| | (5) following 'false' branch (when 'a == 0')...
|......
| 14 | g = a;
| | ~~~~~
| | |
| | (6) ...to here
| | (7) 'g' is NULL
|......
| 17 | *g = 1;
| | ~~~~~~
| | |
| | (8) dereference of NULL 'g'
i think it is because gcc static analyzer can not model array very precisely. Modeling array is very hard. Maybe at some limited situation, for example, an array is initialized by never change, static analyzer should handle it.
Indeed, gcc static analyzer does not generate FN / FP if I do initialization operations on it while the array is defined, which may be a combination problem under for loops and arrays.
#include "stdio.h"
int main()
{
int i = 0;
int *g = &i;
int m[1] = {0};
// for (int j = 0; j < 1; j++)
// {
// m[j] = 0;
// }
if (m[0])
;
else
g = m[i];
printf("NPD_FLAG\n");
*g = 1;
}
GSA does not known m[0] after initialization. https://godbolt.org/z/ajxz1jcce But CSA does: https://godbolt.org/z/KWbaf4jbK Input:
#include "stdio.h"
void __analyzer_eval( int);
int main() {
int i = 0;
int *g = &i;
int m[1];
for (int j = 0; j < 1; j++) {
m[j] = 0;
}
__analyzer_eval(m[0]);
if (m[0]){
__analyzer_eval(m[0]);
}
else{
__analyzer_eval(m[0]);
g = m[i];
}
printf("NPD_FLAG\n");
*g = 1;
}
Output:
<source>: In function 'main':
<source>:18:11: warning: assignment to 'int *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
18 | g = m[i];
| ^
<source>:12:5: warning: UNKNOWN
12 | __analyzer_eval(m[0]);
| ^~~~~~~~~~~~~~~~~~~~~
<source>:14:9: warning: UNKNOWN
14 | __analyzer_eval(m[0]);
| ^~~~~~~~~~~~~~~~~~~~~
<source>:17:9: warning: UNKNOWN
17 | __analyzer_eval(m[0]);
| ^~~~~~~~~~~~~~~~~~~~~
Compiler returned: 0
CSA can handle: https://godbolt.org/z/9j7jj71Gd
date: 2022-12-2 commit: 8c8ca873216387bc26046615c806b96f0345ff9d args: -O0 -fanalyzer test:
report: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109190 fix: original: