mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-17 05:16:42 +00:00
632 lines
21 KiB
C
632 lines
21 KiB
C
// RUN: %clang_analyze_cc1 -verify %s \
|
|
// RUN: -analyzer-checker=core \
|
|
// RUN: -analyzer-checker=unix.Stream \
|
|
// RUN: -analyzer-config unix.Stream:Pedantic=true \
|
|
// RUN: -analyzer-checker=debug.StreamTester \
|
|
// RUN: -analyzer-checker=debug.ExprInspection
|
|
|
|
#include "Inputs/system-header-simulator.h"
|
|
|
|
void clang_analyzer_eval(int);
|
|
void clang_analyzer_dump(int);
|
|
void clang_analyzer_warnIfReached(void);
|
|
void StreamTesterChecker_make_feof_stream(FILE *);
|
|
void StreamTesterChecker_make_ferror_stream(FILE *);
|
|
void StreamTesterChecker_make_ferror_indeterminate_stream(FILE *);
|
|
|
|
void error_fopen(void) {
|
|
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_fdopen(int fd) {
|
|
FILE *F = fdopen(fd, "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(void) {
|
|
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(void) {
|
|
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}}
|
|
StreamTesterChecker_make_ferror_indeterminate_stream(F);
|
|
clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}}
|
|
fclose(F);
|
|
}
|
|
|
|
void stream_error_ferror(void) {
|
|
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}}
|
|
StreamTesterChecker_make_ferror_indeterminate_stream(F);
|
|
clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}}
|
|
fclose(F);
|
|
}
|
|
|
|
void error_fread(void) {
|
|
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}}
|
|
fread(Buf, 1, 10, F); // expected-warning {{might be 'indeterminate'}}
|
|
}
|
|
}
|
|
fclose(F);
|
|
Ret = fread(Buf, 1, 10, F); // expected-warning {{Use of a stream that might be already closed}}
|
|
}
|
|
|
|
void error_fwrite(void) {
|
|
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}}
|
|
fwrite(0, 1, 10, F); // expected-warning {{might be 'indeterminate'}}
|
|
}
|
|
fclose(F);
|
|
Ret = fwrite(0, 1, 10, F); // expected-warning {{Use of a stream that might be already closed}}
|
|
}
|
|
|
|
void error_fgetc(void) {
|
|
FILE *F = tmpfile();
|
|
if (!F)
|
|
return;
|
|
int Ret = fgetc(F);
|
|
if (0 <= Ret && Ret <= 255) {
|
|
clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{FALSE}}
|
|
} else {
|
|
clang_analyzer_eval(Ret == EOF); // expected-warning {{TRUE}}
|
|
clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{TRUE}}
|
|
if (feof(F)) {
|
|
clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}}
|
|
fgetc(F); // expected-warning {{Read function called when stream is in EOF state}}
|
|
} else {
|
|
clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}}
|
|
fgetc(F); // expected-warning {{might be 'indeterminate'}}
|
|
}
|
|
}
|
|
fclose(F);
|
|
fgetc(F); // expected-warning {{Use of a stream that might be already closed}}
|
|
}
|
|
|
|
void error_fgets(void) {
|
|
FILE *F = tmpfile();
|
|
char Buf[256];
|
|
if (!F)
|
|
return;
|
|
char *Ret = fgets(Buf, sizeof(Buf), F);
|
|
if (Ret == Buf) {
|
|
clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{FALSE}}
|
|
} else {
|
|
clang_analyzer_eval(Ret == NULL); // expected-warning {{TRUE}}
|
|
clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{TRUE}}
|
|
if (feof(F)) {
|
|
clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}}
|
|
fgets(Buf, sizeof(Buf), F); // expected-warning {{Read function called when stream is in EOF state}}
|
|
} else {
|
|
clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}}
|
|
fgets(Buf, sizeof(Buf), F); // expected-warning {{might be 'indeterminate'}}
|
|
}
|
|
}
|
|
fclose(F);
|
|
fgets(Buf, sizeof(Buf), F); // expected-warning {{Use of a stream that might be already closed}}
|
|
}
|
|
|
|
void error_fputc(int fd) {
|
|
FILE *F = fdopen(fd, "w");
|
|
if (!F)
|
|
return;
|
|
int Ret = fputc('X', F);
|
|
if (Ret == EOF) {
|
|
clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}}
|
|
clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}}
|
|
fputc('Y', F); // expected-warning {{might be 'indeterminate'}}
|
|
} else {
|
|
clang_analyzer_eval(Ret == 'X'); // expected-warning {{TRUE}}
|
|
clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{FALSE}}
|
|
fputc('Y', F); // no-warning
|
|
}
|
|
fclose(F);
|
|
fputc('A', F); // expected-warning {{Use of a stream that might be already closed}}
|
|
}
|
|
|
|
void error_fputs(void) {
|
|
FILE *F = tmpfile();
|
|
if (!F)
|
|
return;
|
|
int Ret = fputs("XYZ", F);
|
|
if (Ret >= 0) {
|
|
clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{FALSE}}
|
|
fputs("QWD", F); // no-warning
|
|
} else {
|
|
clang_analyzer_eval(Ret == EOF); // expected-warning {{TRUE}}
|
|
clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}}
|
|
clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}}
|
|
fputs("QWD", F); // expected-warning {{might be 'indeterminate'}}
|
|
}
|
|
fclose(F);
|
|
fputs("ABC", F); // expected-warning {{Use of a stream that might be already closed}}
|
|
}
|
|
|
|
void error_fprintf(void) {
|
|
FILE *F = tmpfile();
|
|
if (!F)
|
|
return;
|
|
int Ret = fprintf(F, "aaa");
|
|
if (Ret >= 0) {
|
|
clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{FALSE}}
|
|
fprintf(F, "bbb"); // no-warning
|
|
} else {
|
|
clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}}
|
|
clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}}
|
|
fprintf(F, "bbb"); // expected-warning {{might be 'indeterminate'}}
|
|
}
|
|
fclose(F);
|
|
fprintf(F, "ccc"); // expected-warning {{Use of a stream that might be already closed}}
|
|
}
|
|
|
|
void error_fscanf(int *A) {
|
|
FILE *F = tmpfile();
|
|
if (!F)
|
|
return;
|
|
int Ret = fscanf(F, "a%ib", A);
|
|
if (Ret >= 0) {
|
|
clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{FALSE}}
|
|
fscanf(F, "bbb"); // no-warning
|
|
} else {
|
|
if (ferror(F)) {
|
|
clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}}
|
|
fscanf(F, "bbb"); // expected-warning {{might be 'indeterminate'}}
|
|
} else if (feof(F)) {
|
|
clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}}
|
|
fscanf(F, "bbb"); // expected-warning {{is in EOF state}}
|
|
clang_analyzer_eval(feof(F)); // expected-warning {{TRUE}}
|
|
} else {
|
|
clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}}
|
|
fscanf(F, "bbb"); // expected-warning {{might be 'indeterminate'}}
|
|
}
|
|
}
|
|
fclose(F);
|
|
fscanf(F, "ccc"); // expected-warning {{Use of a stream that might be already closed}}
|
|
}
|
|
|
|
void error_ungetc(int TestIndeterminate) {
|
|
FILE *F = tmpfile();
|
|
if (!F)
|
|
return;
|
|
int Ret = ungetc('X', F);
|
|
clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{FALSE}}
|
|
if (Ret == EOF) {
|
|
clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}}
|
|
} else {
|
|
clang_analyzer_eval(Ret == 'X'); // expected-warning {{TRUE}}
|
|
}
|
|
fputc('Y', F); // no-warning
|
|
if (TestIndeterminate) {
|
|
StreamTesterChecker_make_ferror_indeterminate_stream(F);
|
|
ungetc('X', F); // expected-warning {{might be 'indeterminate'}}
|
|
}
|
|
fclose(F);
|
|
ungetc('A', F); // expected-warning {{Use of a stream that might be already closed}}
|
|
}
|
|
|
|
void error_getdelim(char *P, size_t Sz) {
|
|
FILE *F = tmpfile();
|
|
if (!F)
|
|
return;
|
|
ssize_t Ret = getdelim(&P, &Sz, '\t', F);
|
|
if (Ret >= 0) {
|
|
clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{FALSE}}
|
|
} else {
|
|
clang_analyzer_eval(Ret == -1); // expected-warning {{TRUE}}
|
|
clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{TRUE}}
|
|
if (feof(F)) {
|
|
clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}}
|
|
getdelim(&P, &Sz, '\n', F); // expected-warning {{Read function called when stream is in EOF state}}
|
|
} else {
|
|
clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}}
|
|
getdelim(&P, &Sz, '\n', F); // expected-warning {{might be 'indeterminate'}}
|
|
}
|
|
}
|
|
fclose(F);
|
|
getdelim(&P, &Sz, '\n', F); // expected-warning {{Use of a stream that might be already closed}}
|
|
}
|
|
|
|
void error_getline(char *P, size_t Sz) {
|
|
FILE *F = tmpfile();
|
|
if (!F)
|
|
return;
|
|
ssize_t Ret = getline(&P, &Sz, F);
|
|
if (Ret >= 0) {
|
|
clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{FALSE}}
|
|
} else {
|
|
clang_analyzer_eval(Ret == -1); // expected-warning {{TRUE}}
|
|
clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{TRUE}}
|
|
if (feof(F)) {
|
|
clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}}
|
|
getline(&P, &Sz, F); // expected-warning {{Read function called when stream is in EOF state}}
|
|
} else {
|
|
clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}}
|
|
getline(&P, &Sz, F); // expected-warning {{might be 'indeterminate'}}
|
|
}
|
|
}
|
|
fclose(F);
|
|
getline(&P, &Sz, F); // expected-warning {{Use of a stream that might be already closed}}
|
|
}
|
|
|
|
void write_after_eof_is_allowed(void) {
|
|
FILE *F = tmpfile();
|
|
if (!F)
|
|
return;
|
|
StreamTesterChecker_make_feof_stream(F);
|
|
if (fputs("QWD", F) >= 0) // no-warning
|
|
clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{FALSE}}
|
|
StreamTesterChecker_make_feof_stream(F);
|
|
if (fputc('Q', F) == 'Q') // no-warning
|
|
clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{FALSE}}
|
|
StreamTesterChecker_make_feof_stream(F);
|
|
if (fwrite("012345678", 1, 10, F) == 10) // no-warning
|
|
clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{FALSE}}
|
|
fclose(F);
|
|
}
|
|
|
|
void freadwrite_zerosize(FILE *F) {
|
|
size_t Ret;
|
|
Ret = fwrite(0, 1, 0, F);
|
|
clang_analyzer_dump(Ret); // expected-warning {{0 }}
|
|
Ret = fwrite(0, 0, 1, F);
|
|
clang_analyzer_dump(Ret); // expected-warning {{0 }}
|
|
Ret = fread(0, 1, 0, F);
|
|
clang_analyzer_dump(Ret); // expected-warning {{0 }}
|
|
Ret = fread(0, 0, 1, F);
|
|
clang_analyzer_dump(Ret); // expected-warning {{0 }}
|
|
}
|
|
|
|
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(void) {
|
|
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);
|
|
}
|
|
|
|
void error_fseek(void) {
|
|
FILE *F = fopen("file", "r");
|
|
if (!F)
|
|
return;
|
|
int rc = fseek(F, 1, SEEK_SET);
|
|
if (rc) {
|
|
clang_analyzer_eval(rc == -1); // expected-warning {{TRUE}}
|
|
int IsFEof = feof(F), IsFError = ferror(F);
|
|
// Get ferror or no error.
|
|
clang_analyzer_eval(IsFError); // expected-warning {{FALSE}} \
|
|
// expected-warning {{TRUE}}
|
|
clang_analyzer_eval(IsFEof); // expected-warning {{FALSE}}
|
|
// Error flags should not change.
|
|
clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}}
|
|
if (IsFError)
|
|
clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}}
|
|
} 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);
|
|
}
|
|
|
|
void error_fseeko(void) {
|
|
FILE *F = fopen("file", "r");
|
|
if (!F)
|
|
return;
|
|
int rc = fseeko(F, 1, SEEK_SET);
|
|
if (rc) {
|
|
// Get ferror or no error.
|
|
clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}} \
|
|
// expected-warning {{TRUE}}
|
|
clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}}
|
|
} else {
|
|
clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}}
|
|
clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}}
|
|
}
|
|
fclose(F);
|
|
}
|
|
|
|
void error_fseek_0(void) {
|
|
FILE *F = fopen("file", "r");
|
|
if (!F)
|
|
return;
|
|
int rc = fseek(F, 0, SEEK_SET);
|
|
if (rc == -1) {
|
|
int IsFEof = feof(F), IsFError = ferror(F);
|
|
// Get ferror or no error, but not feof.
|
|
clang_analyzer_eval(IsFError);
|
|
// expected-warning@-1 {{FALSE}}
|
|
// expected-warning@-2 {{TRUE}}
|
|
clang_analyzer_eval(IsFEof);
|
|
// expected-warning@-1 {{FALSE}}
|
|
// Error flags should not change.
|
|
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);
|
|
}
|
|
|
|
void error_fseeko_0(void) {
|
|
FILE *F = fopen("file", "r");
|
|
if (!F)
|
|
return;
|
|
int rc = fseeko(F, 0, SEEK_SET);
|
|
if (rc) {
|
|
int IsFEof = feof(F), IsFError = ferror(F);
|
|
// Get ferror or no error, but not feof.
|
|
clang_analyzer_eval(IsFError);
|
|
// expected-warning@-1 {{FALSE}}
|
|
// expected-warning@-2 {{TRUE}}
|
|
clang_analyzer_eval(IsFEof);
|
|
// expected-warning@-1 {{FALSE}}
|
|
} else {
|
|
clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}}
|
|
clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}}
|
|
}
|
|
fclose(F);
|
|
}
|
|
|
|
void error_ftell(int TestIndeterminate) {
|
|
FILE *F = fopen("file", "r");
|
|
if (!F)
|
|
return;
|
|
long rc = ftell(F);
|
|
if (rc >= 0)
|
|
clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}}
|
|
else
|
|
clang_analyzer_eval(rc == -1); // expected-warning {{TRUE}}
|
|
clang_analyzer_eval(feof(F) && ferror(F)); // expected-warning {{FALSE}}
|
|
StreamTesterChecker_make_feof_stream(F);
|
|
rc = ftell(F);
|
|
clang_analyzer_eval(feof(F)); // expected-warning {{TRUE}}
|
|
clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}}
|
|
StreamTesterChecker_make_ferror_stream(F);
|
|
rc = ftell(F);
|
|
clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}}
|
|
clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}}
|
|
if (TestIndeterminate) {
|
|
StreamTesterChecker_make_ferror_indeterminate_stream(F);
|
|
ftell(F); // expected-warning {{might be 'indeterminate'}}
|
|
}
|
|
fclose(F);
|
|
}
|
|
|
|
void error_ftello(int TestIndeterminate) {
|
|
FILE *F = fopen("file", "r");
|
|
if (!F)
|
|
return;
|
|
off_t rc = ftello(F);
|
|
if (rc >= 0)
|
|
clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}}
|
|
else
|
|
clang_analyzer_eval(rc == -1); // expected-warning {{TRUE}}
|
|
clang_analyzer_eval(feof(F) && ferror(F)); // expected-warning {{FALSE}}
|
|
StreamTesterChecker_make_feof_stream(F);
|
|
rc = ftello(F);
|
|
clang_analyzer_eval(feof(F)); // expected-warning {{TRUE}}
|
|
clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}}
|
|
StreamTesterChecker_make_ferror_stream(F);
|
|
rc = ftello(F);
|
|
clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}}
|
|
clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}}
|
|
if (TestIndeterminate) {
|
|
StreamTesterChecker_make_ferror_indeterminate_stream(F);
|
|
ftell(F); // expected-warning {{might be 'indeterminate'}}
|
|
}
|
|
fclose(F);
|
|
}
|
|
|
|
void error_fileno(void) {
|
|
FILE *F = fopen("file", "r");
|
|
if (!F)
|
|
return;
|
|
int N = fileno(F);
|
|
clang_analyzer_eval(N >= 0); // expected-warning {{TRUE}}
|
|
clang_analyzer_eval(feof(F) && ferror(F)); // expected-warning {{FALSE}}
|
|
StreamTesterChecker_make_feof_stream(F);
|
|
N = fileno(F);
|
|
clang_analyzer_eval(feof(F)); // expected-warning {{TRUE}}
|
|
clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}}
|
|
StreamTesterChecker_make_ferror_stream(F);
|
|
N = fileno(F);
|
|
clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}}
|
|
clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}}
|
|
StreamTesterChecker_make_ferror_indeterminate_stream(F);
|
|
fileno(F); // no warning
|
|
fclose(F);
|
|
}
|
|
|
|
void error_fflush_on_non_null_stream_clear_error_states(void) {
|
|
FILE *F0 = tmpfile(), *F1 = tmpfile();
|
|
// `fflush` clears a non-EOF stream's error state.
|
|
if (F0) {
|
|
StreamTesterChecker_make_ferror_stream(F0);
|
|
if (fflush(F0) == 0) { // no-warning
|
|
clang_analyzer_eval(ferror(F0)); // expected-warning {{FALSE}}
|
|
clang_analyzer_eval(feof(F0)); // expected-warning {{FALSE}}
|
|
}
|
|
fclose(F0);
|
|
}
|
|
// `fflush` clears an EOF stream's error state.
|
|
if (F1) {
|
|
StreamTesterChecker_make_feof_stream(F1);
|
|
if (fflush(F1) == 0) { // no-warning
|
|
clang_analyzer_eval(ferror(F1)); // expected-warning {{FALSE}}
|
|
clang_analyzer_eval(feof(F1)); // expected-warning {{TRUE}}
|
|
}
|
|
fclose(F1);
|
|
}
|
|
}
|
|
|
|
void error_fflush_on_null_stream_clear_error_states(void) {
|
|
FILE *F0 = tmpfile(), *F1 = tmpfile();
|
|
// `fflush` clears all stream's error states, while retains their EOF states.
|
|
if (F0 && F1) {
|
|
StreamTesterChecker_make_ferror_stream(F0);
|
|
StreamTesterChecker_make_feof_stream(F1);
|
|
if (fflush(NULL) == 0) { // no-warning
|
|
clang_analyzer_eval(ferror(F0)); // expected-warning {{FALSE}}
|
|
clang_analyzer_eval(feof(F0)); // expected-warning {{FALSE}}
|
|
clang_analyzer_eval(ferror(F1)); // expected-warning {{FALSE}}
|
|
clang_analyzer_eval(feof(F1)); // expected-warning {{TRUE}}
|
|
}
|
|
}
|
|
if (F0)
|
|
fclose(F0);
|
|
if (F1)
|
|
fclose(F1);
|
|
}
|
|
|
|
void error_indeterminate(void) {
|
|
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(void) {
|
|
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(void) {
|
|
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(void) {
|
|
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);
|
|
}
|