// 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 #include "Inputs/system-header-simulator.h" void clang_analyzer_eval(int); void clang_analyzer_warnIfReached(); 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); } 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}} fread(Buf, 1, 10, F); // expected-warning {{might be 'indeterminate'}} } } 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}} fwrite(0, 1, 10, F); // expected-warning {{might be 'indeterminate'}} } 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); } 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); } 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); }