2020-04-14 22:53:09 +08:00
|
|
|
// RUN: %clang_analyze_cc1 -verify %s \
|
|
|
|
// RUN: -analyzer-checker=core \
|
|
|
|
// RUN: -analyzer-checker=alpha.unix.Stream \
|
|
|
|
// RUN: -analyzer-checker=debug.StreamTester \
|
|
|
|
// RUN: -analyzer-checker=debug.ExprInspection
|
[Analyzer][StreamChecker] Introduction of stream error handling.
Summary:
Store the error flags (EOF or error) of a stream.
Support the functions feof, ferror, clearerr.
Added a test checker for setting the error flags.
Reviewers: Szelethus, NoQ, Charusso, baloghadamsoftware, xazax.hun
Reviewed By: Szelethus
Subscribers: steakhal, ASDenysPetrov, rnkovacs, xazax.hun, baloghadamsoftware, szepet, a.sidorin, mikhail.ramalho, Szelethus, donat.nagy, dkrupp, gamesh411, Charusso, martong, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D75682
2020-04-08 14:52:24 +08:00
|
|
|
|
|
|
|
#include "Inputs/system-header-simulator.h"
|
|
|
|
|
|
|
|
void clang_analyzer_eval(int);
|
[Analyzer][StreamChecker] Added support for 'fread' and 'fwrite'.
Summary:
Stream functions `fread` and `fwrite` are evaluated
and preconditions checked.
A new bug type is added for a (non fatal) warning if `fread`
is called in EOF state.
Reviewers: Szelethus, NoQ, dcoughlin, baloghadamsoftware, martong, xazax.hun
Reviewed By: Szelethus
Subscribers: rnkovacs, xazax.hun, baloghadamsoftware, szepet, a.sidorin, mikhail.ramalho, Szelethus, donat.nagy, dkrupp, gamesh411, Charusso, martong, ASDenysPetrov, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D80015
2020-05-20 14:58:17 +08:00
|
|
|
void clang_analyzer_warnIfReached();
|
[Analyzer][StreamChecker] Introduction of stream error handling.
Summary:
Store the error flags (EOF or error) of a stream.
Support the functions feof, ferror, clearerr.
Added a test checker for setting the error flags.
Reviewers: Szelethus, NoQ, Charusso, baloghadamsoftware, xazax.hun
Reviewed By: Szelethus
Subscribers: steakhal, ASDenysPetrov, rnkovacs, xazax.hun, baloghadamsoftware, szepet, a.sidorin, mikhail.ramalho, Szelethus, donat.nagy, dkrupp, gamesh411, Charusso, martong, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D75682
2020-04-08 14:52:24 +08:00
|
|
|
void StreamTesterChecker_make_feof_stream(FILE *);
|
|
|
|
void StreamTesterChecker_make_ferror_stream(FILE *);
|
|
|
|
|
|
|
|
void error_fopen() {
|
|
|
|
FILE *F = fopen("file", "r");
|
|
|
|
if (!F)
|
|
|
|
return;
|
|
|
|
clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}}
|
|
|
|
clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}}
|
|
|
|
fclose(F);
|
|
|
|
}
|
|
|
|
|
|
|
|
void error_freopen() {
|
|
|
|
FILE *F = fopen("file", "r");
|
|
|
|
if (!F)
|
|
|
|
return;
|
|
|
|
F = freopen(0, "w", F);
|
|
|
|
if (!F)
|
|
|
|
return;
|
|
|
|
clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}}
|
|
|
|
clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}}
|
|
|
|
fclose(F);
|
|
|
|
}
|
|
|
|
|
|
|
|
void stream_error_feof() {
|
|
|
|
FILE *F = fopen("file", "r");
|
|
|
|
if (!F)
|
|
|
|
return;
|
|
|
|
StreamTesterChecker_make_feof_stream(F);
|
|
|
|
clang_analyzer_eval(feof(F)); // expected-warning {{TRUE}}
|
|
|
|
clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}}
|
|
|
|
clearerr(F);
|
|
|
|
clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}}
|
|
|
|
clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}}
|
|
|
|
fclose(F);
|
|
|
|
}
|
|
|
|
|
|
|
|
void stream_error_ferror() {
|
|
|
|
FILE *F = fopen("file", "r");
|
|
|
|
if (!F)
|
|
|
|
return;
|
|
|
|
StreamTesterChecker_make_ferror_stream(F);
|
|
|
|
clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}}
|
|
|
|
clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}}
|
|
|
|
clearerr(F);
|
|
|
|
clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}}
|
|
|
|
clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}}
|
|
|
|
fclose(F);
|
|
|
|
}
|
[Analyzer][StreamChecker] Added evaluation of fseek.
Summary:
Function `fseek` is now evaluated with setting error return value
and error flags.
Reviewers: Szelethus, NoQ, xazax.hun, rnkovacs, dcoughlin, baloghadamsoftware, martong
Reviewed By: Szelethus
Subscribers: ASDenysPetrov, xazax.hun, baloghadamsoftware, szepet, a.sidorin, mikhail.ramalho, Szelethus, donat.nagy, dkrupp, gamesh411, Charusso, martong, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D75851
2020-04-14 17:14:17 +08:00
|
|
|
|
[Analyzer][StreamChecker] Added support for 'fread' and 'fwrite'.
Summary:
Stream functions `fread` and `fwrite` are evaluated
and preconditions checked.
A new bug type is added for a (non fatal) warning if `fread`
is called in EOF state.
Reviewers: Szelethus, NoQ, dcoughlin, baloghadamsoftware, martong, xazax.hun
Reviewed By: Szelethus
Subscribers: rnkovacs, xazax.hun, baloghadamsoftware, szepet, a.sidorin, mikhail.ramalho, Szelethus, donat.nagy, dkrupp, gamesh411, Charusso, martong, ASDenysPetrov, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D80015
2020-05-20 14:58:17 +08:00
|
|
|
void error_fread() {
|
|
|
|
FILE *F = tmpfile();
|
|
|
|
if (!F)
|
|
|
|
return;
|
|
|
|
char Buf[10];
|
|
|
|
int Ret = fread(Buf, 1, 10, F);
|
|
|
|
if (Ret == 10) {
|
|
|
|
clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{FALSE}}
|
|
|
|
} else {
|
|
|
|
clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{TRUE}}
|
|
|
|
if (feof(F)) {
|
|
|
|
clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}}
|
|
|
|
fread(Buf, 1, 10, F); // expected-warning {{Read function called when stream is in EOF state}}
|
|
|
|
clang_analyzer_eval(feof(F)); // expected-warning {{TRUE}}
|
|
|
|
clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}}
|
|
|
|
}
|
|
|
|
if (ferror(F)) {
|
|
|
|
clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}}
|
[Analyzer][StreamChecker] Added check for "indeterminate file position".
Summary:
According to the standard, after a `wread` or `fwrite` call the file position
becomes "indeterminate". It is assumable that a next read or write causes
undefined behavior, so a (fatal error) warning is added for this case.
The indeterminate position can be cleared by some operations, for example
`fseek` or `freopen`, not with `clearerr`.
Reviewers: Szelethus, baloghadamsoftware, martong, NoQ, xazax.hun, dcoughlin
Reviewed By: Szelethus
Subscribers: rnkovacs, NoQ, xazax.hun, baloghadamsoftware, szepet, a.sidorin, mikhail.ramalho, Szelethus, donat.nagy, dkrupp, gamesh411, Charusso, martong, ASDenysPetrov, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D80018
2020-05-27 22:23:42 +08:00
|
|
|
fread(Buf, 1, 10, F); // expected-warning {{might be 'indeterminate'}}
|
[Analyzer][StreamChecker] Added support for 'fread' and 'fwrite'.
Summary:
Stream functions `fread` and `fwrite` are evaluated
and preconditions checked.
A new bug type is added for a (non fatal) warning if `fread`
is called in EOF state.
Reviewers: Szelethus, NoQ, dcoughlin, baloghadamsoftware, martong, xazax.hun
Reviewed By: Szelethus
Subscribers: rnkovacs, xazax.hun, baloghadamsoftware, szepet, a.sidorin, mikhail.ramalho, Szelethus, donat.nagy, dkrupp, gamesh411, Charusso, martong, ASDenysPetrov, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D80015
2020-05-20 14:58:17 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
fclose(F);
|
|
|
|
Ret = fread(Buf, 1, 10, F); // expected-warning {{Stream might be already closed}}
|
|
|
|
}
|
|
|
|
|
|
|
|
void error_fwrite() {
|
|
|
|
FILE *F = tmpfile();
|
|
|
|
if (!F)
|
|
|
|
return;
|
|
|
|
const char *Buf = "123456789";
|
|
|
|
int Ret = fwrite(Buf, 1, 10, F);
|
|
|
|
if (Ret == 10) {
|
|
|
|
clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{FALSE}}
|
|
|
|
} else {
|
|
|
|
clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}}
|
|
|
|
clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}}
|
[Analyzer][StreamChecker] Added check for "indeterminate file position".
Summary:
According to the standard, after a `wread` or `fwrite` call the file position
becomes "indeterminate". It is assumable that a next read or write causes
undefined behavior, so a (fatal error) warning is added for this case.
The indeterminate position can be cleared by some operations, for example
`fseek` or `freopen`, not with `clearerr`.
Reviewers: Szelethus, baloghadamsoftware, martong, NoQ, xazax.hun, dcoughlin
Reviewed By: Szelethus
Subscribers: rnkovacs, NoQ, xazax.hun, baloghadamsoftware, szepet, a.sidorin, mikhail.ramalho, Szelethus, donat.nagy, dkrupp, gamesh411, Charusso, martong, ASDenysPetrov, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D80018
2020-05-27 22:23:42 +08:00
|
|
|
fwrite(0, 1, 10, F); // expected-warning {{might be 'indeterminate'}}
|
[Analyzer][StreamChecker] Added support for 'fread' and 'fwrite'.
Summary:
Stream functions `fread` and `fwrite` are evaluated
and preconditions checked.
A new bug type is added for a (non fatal) warning if `fread`
is called in EOF state.
Reviewers: Szelethus, NoQ, dcoughlin, baloghadamsoftware, martong, xazax.hun
Reviewed By: Szelethus
Subscribers: rnkovacs, xazax.hun, baloghadamsoftware, szepet, a.sidorin, mikhail.ramalho, Szelethus, donat.nagy, dkrupp, gamesh411, Charusso, martong, ASDenysPetrov, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D80015
2020-05-20 14:58:17 +08:00
|
|
|
}
|
|
|
|
fclose(F);
|
|
|
|
Ret = fwrite(0, 1, 10, F); // expected-warning {{Stream might be already closed}}
|
|
|
|
}
|
|
|
|
|
|
|
|
void freadwrite_zerosize(FILE *F) {
|
|
|
|
fwrite(0, 1, 0, F);
|
|
|
|
fwrite(0, 0, 1, F);
|
|
|
|
fread(0, 1, 0, F);
|
|
|
|
fread(0, 0, 1, F);
|
|
|
|
}
|
|
|
|
|
|
|
|
void freadwrite_zerosize_eofstate(FILE *F) {
|
|
|
|
fwrite(0, 1, 0, F);
|
|
|
|
fwrite(0, 0, 1, F);
|
|
|
|
fread(0, 1, 0, F); // expected-warning {{Read function called when stream is in EOF state}}
|
|
|
|
fread(0, 0, 1, F); // expected-warning {{Read function called when stream is in EOF state}}
|
|
|
|
}
|
|
|
|
|
|
|
|
void error_fread_fwrite_zerosize() {
|
|
|
|
FILE *F = fopen("file", "r");
|
|
|
|
if (!F)
|
|
|
|
return;
|
|
|
|
|
|
|
|
freadwrite_zerosize(F);
|
|
|
|
clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}}
|
|
|
|
clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}}
|
|
|
|
|
|
|
|
StreamTesterChecker_make_ferror_stream(F);
|
|
|
|
freadwrite_zerosize(F);
|
|
|
|
clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}}
|
|
|
|
clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}}
|
|
|
|
|
|
|
|
StreamTesterChecker_make_feof_stream(F);
|
|
|
|
freadwrite_zerosize_eofstate(F);
|
|
|
|
clang_analyzer_eval(feof(F)); // expected-warning {{TRUE}}
|
|
|
|
clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}}
|
|
|
|
|
|
|
|
fclose(F);
|
|
|
|
}
|
|
|
|
|
[Analyzer][StreamChecker] Added evaluation of fseek.
Summary:
Function `fseek` is now evaluated with setting error return value
and error flags.
Reviewers: Szelethus, NoQ, xazax.hun, rnkovacs, dcoughlin, baloghadamsoftware, martong
Reviewed By: Szelethus
Subscribers: ASDenysPetrov, xazax.hun, baloghadamsoftware, szepet, a.sidorin, mikhail.ramalho, Szelethus, donat.nagy, dkrupp, gamesh411, Charusso, martong, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D75851
2020-04-14 17:14:17 +08:00
|
|
|
void error_fseek() {
|
|
|
|
FILE *F = fopen("file", "r");
|
|
|
|
if (!F)
|
|
|
|
return;
|
|
|
|
int rc = fseek(F, 0, SEEK_SET);
|
|
|
|
if (rc) {
|
|
|
|
int IsFEof = feof(F), IsFError = ferror(F);
|
|
|
|
// Get feof or ferror or no error.
|
|
|
|
clang_analyzer_eval(IsFEof || IsFError);
|
|
|
|
// expected-warning@-1 {{FALSE}}
|
|
|
|
// expected-warning@-2 {{TRUE}}
|
|
|
|
clang_analyzer_eval(IsFEof && IsFError); // expected-warning {{FALSE}}
|
|
|
|
// Error flags should not change.
|
|
|
|
if (IsFEof)
|
|
|
|
clang_analyzer_eval(feof(F)); // expected-warning {{TRUE}}
|
|
|
|
else
|
|
|
|
clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}}
|
|
|
|
if (IsFError)
|
|
|
|
clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}}
|
|
|
|
else
|
|
|
|
clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}}
|
|
|
|
} else {
|
|
|
|
clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}}
|
|
|
|
clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}}
|
|
|
|
// Error flags should not change.
|
|
|
|
clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}}
|
|
|
|
clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}}
|
|
|
|
}
|
|
|
|
fclose(F);
|
|
|
|
}
|
[Analyzer][StreamChecker] Added check for "indeterminate file position".
Summary:
According to the standard, after a `wread` or `fwrite` call the file position
becomes "indeterminate". It is assumable that a next read or write causes
undefined behavior, so a (fatal error) warning is added for this case.
The indeterminate position can be cleared by some operations, for example
`fseek` or `freopen`, not with `clearerr`.
Reviewers: Szelethus, baloghadamsoftware, martong, NoQ, xazax.hun, dcoughlin
Reviewed By: Szelethus
Subscribers: rnkovacs, NoQ, xazax.hun, baloghadamsoftware, szepet, a.sidorin, mikhail.ramalho, Szelethus, donat.nagy, dkrupp, gamesh411, Charusso, martong, ASDenysPetrov, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D80018
2020-05-27 22:23:42 +08:00
|
|
|
|
|
|
|
void error_indeterminate() {
|
|
|
|
FILE *F = fopen("file", "r+");
|
|
|
|
if (!F)
|
|
|
|
return;
|
|
|
|
const char *Buf = "123456789";
|
|
|
|
int rc = fseek(F, 0, SEEK_SET);
|
|
|
|
if (rc) {
|
|
|
|
if (feof(F)) {
|
|
|
|
fwrite(Buf, 1, 10, F); // no warning
|
|
|
|
} else if (ferror(F)) {
|
|
|
|
fwrite(Buf, 1, 10, F); // expected-warning {{might be 'indeterminate'}}
|
|
|
|
} else {
|
|
|
|
fwrite(Buf, 1, 10, F); // expected-warning {{might be 'indeterminate'}}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fclose(F);
|
|
|
|
}
|
|
|
|
|
|
|
|
void error_indeterminate_clearerr() {
|
|
|
|
FILE *F = fopen("file", "r+");
|
|
|
|
if (!F)
|
|
|
|
return;
|
|
|
|
const char *Buf = "123456789";
|
|
|
|
int rc = fseek(F, 0, SEEK_SET);
|
|
|
|
if (rc) {
|
|
|
|
if (feof(F)) {
|
|
|
|
clearerr(F);
|
|
|
|
fwrite(Buf, 1, 10, F); // no warning
|
|
|
|
} else if (ferror(F)) {
|
|
|
|
clearerr(F);
|
|
|
|
fwrite(Buf, 1, 10, F); // expected-warning {{might be 'indeterminate'}}
|
|
|
|
} else {
|
|
|
|
clearerr(F);
|
|
|
|
fwrite(Buf, 1, 10, F); // expected-warning {{might be 'indeterminate'}}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fclose(F);
|
|
|
|
}
|
|
|
|
|
|
|
|
void error_indeterminate_feof1() {
|
|
|
|
FILE *F = fopen("file", "r+");
|
|
|
|
if (!F)
|
|
|
|
return;
|
|
|
|
char Buf[10];
|
|
|
|
if (fread(Buf, 1, 10, F) < 10) {
|
|
|
|
if (feof(F)) {
|
|
|
|
// error is feof, should be non-indeterminate
|
|
|
|
fwrite("1", 1, 1, F); // no warning
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fclose(F);
|
|
|
|
}
|
|
|
|
|
|
|
|
void error_indeterminate_feof2() {
|
|
|
|
FILE *F = fopen("file", "r+");
|
|
|
|
if (!F)
|
|
|
|
return;
|
|
|
|
char Buf[10];
|
|
|
|
if (fread(Buf, 1, 10, F) < 10) {
|
|
|
|
if (ferror(F) == 0) {
|
|
|
|
// error is feof, should be non-indeterminate
|
|
|
|
fwrite("1", 1, 1, F); // no warning
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fclose(F);
|
|
|
|
}
|