1 // RUN: %clang_analyze_cc1 -verify %s \ 2 // RUN: -analyzer-checker=core \ 3 // RUN: -analyzer-checker=alpha.unix.Stream \ 4 // RUN: -analyzer-checker=debug.StreamTester \ 5 // RUN: -analyzer-checker=debug.ExprInspection 6 7 #include "Inputs/system-header-simulator.h" 8 9 void clang_analyzer_eval(int); 10 void clang_analyzer_warnIfReached(void); 11 void StreamTesterChecker_make_feof_stream(FILE *); 12 void StreamTesterChecker_make_ferror_stream(FILE *); 13 14 void error_fopen(void) { 15 FILE *F = fopen("file", "r"); 16 if (!F) 17 return; 18 clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}} 19 clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}} 20 fclose(F); 21 } 22 23 void error_freopen(void) { 24 FILE *F = fopen("file", "r"); 25 if (!F) 26 return; 27 F = freopen(0, "w", F); 28 if (!F) 29 return; 30 clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}} 31 clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}} 32 fclose(F); 33 } 34 35 void stream_error_feof(void) { 36 FILE *F = fopen("file", "r"); 37 if (!F) 38 return; 39 StreamTesterChecker_make_feof_stream(F); 40 clang_analyzer_eval(feof(F)); // expected-warning {{TRUE}} 41 clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}} 42 clearerr(F); 43 clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}} 44 clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}} 45 fclose(F); 46 } 47 48 void stream_error_ferror(void) { 49 FILE *F = fopen("file", "r"); 50 if (!F) 51 return; 52 StreamTesterChecker_make_ferror_stream(F); 53 clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}} 54 clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}} 55 clearerr(F); 56 clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}} 57 clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}} 58 fclose(F); 59 } 60 61 void error_fread(void) { 62 FILE *F = tmpfile(); 63 if (!F) 64 return; 65 char Buf[10]; 66 int Ret = fread(Buf, 1, 10, F); 67 if (Ret == 10) { 68 clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{FALSE}} 69 } else { 70 clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{TRUE}} 71 if (feof(F)) { 72 clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}} 73 fread(Buf, 1, 10, F); // expected-warning {{Read function called when stream is in EOF state}} 74 clang_analyzer_eval(feof(F)); // expected-warning {{TRUE}} 75 clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}} 76 } 77 if (ferror(F)) { 78 clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}} 79 fread(Buf, 1, 10, F); // expected-warning {{might be 'indeterminate'}} 80 } 81 } 82 fclose(F); 83 Ret = fread(Buf, 1, 10, F); // expected-warning {{Stream might be already closed}} 84 } 85 86 void error_fwrite(void) { 87 FILE *F = tmpfile(); 88 if (!F) 89 return; 90 const char *Buf = "123456789"; 91 int Ret = fwrite(Buf, 1, 10, F); 92 if (Ret == 10) { 93 clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{FALSE}} 94 } else { 95 clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}} 96 clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}} 97 fwrite(0, 1, 10, F); // expected-warning {{might be 'indeterminate'}} 98 } 99 fclose(F); 100 Ret = fwrite(0, 1, 10, F); // expected-warning {{Stream might be already closed}} 101 } 102 103 void freadwrite_zerosize(FILE *F) { 104 fwrite(0, 1, 0, F); 105 fwrite(0, 0, 1, F); 106 fread(0, 1, 0, F); 107 fread(0, 0, 1, F); 108 } 109 110 void freadwrite_zerosize_eofstate(FILE *F) { 111 fwrite(0, 1, 0, F); 112 fwrite(0, 0, 1, F); 113 fread(0, 1, 0, F); // expected-warning {{Read function called when stream is in EOF state}} 114 fread(0, 0, 1, F); // expected-warning {{Read function called when stream is in EOF state}} 115 } 116 117 void error_fread_fwrite_zerosize(void) { 118 FILE *F = fopen("file", "r"); 119 if (!F) 120 return; 121 122 freadwrite_zerosize(F); 123 clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}} 124 clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}} 125 126 StreamTesterChecker_make_ferror_stream(F); 127 freadwrite_zerosize(F); 128 clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}} 129 clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}} 130 131 StreamTesterChecker_make_feof_stream(F); 132 freadwrite_zerosize_eofstate(F); 133 clang_analyzer_eval(feof(F)); // expected-warning {{TRUE}} 134 clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}} 135 136 fclose(F); 137 } 138 139 void error_fseek(void) { 140 FILE *F = fopen("file", "r"); 141 if (!F) 142 return; 143 int rc = fseek(F, 0, SEEK_SET); 144 if (rc) { 145 int IsFEof = feof(F), IsFError = ferror(F); 146 // Get feof or ferror or no error. 147 clang_analyzer_eval(IsFEof || IsFError); 148 // expected-warning@-1 {{FALSE}} 149 // expected-warning@-2 {{TRUE}} 150 clang_analyzer_eval(IsFEof && IsFError); // expected-warning {{FALSE}} 151 // Error flags should not change. 152 if (IsFEof) 153 clang_analyzer_eval(feof(F)); // expected-warning {{TRUE}} 154 else 155 clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}} 156 if (IsFError) 157 clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}} 158 else 159 clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}} 160 } else { 161 clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}} 162 clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}} 163 // Error flags should not change. 164 clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}} 165 clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}} 166 } 167 fclose(F); 168 } 169 170 void error_indeterminate(void) { 171 FILE *F = fopen("file", "r+"); 172 if (!F) 173 return; 174 const char *Buf = "123456789"; 175 int rc = fseek(F, 0, SEEK_SET); 176 if (rc) { 177 if (feof(F)) { 178 fwrite(Buf, 1, 10, F); // no warning 179 } else if (ferror(F)) { 180 fwrite(Buf, 1, 10, F); // expected-warning {{might be 'indeterminate'}} 181 } else { 182 fwrite(Buf, 1, 10, F); // expected-warning {{might be 'indeterminate'}} 183 } 184 } 185 fclose(F); 186 } 187 188 void error_indeterminate_clearerr(void) { 189 FILE *F = fopen("file", "r+"); 190 if (!F) 191 return; 192 const char *Buf = "123456789"; 193 int rc = fseek(F, 0, SEEK_SET); 194 if (rc) { 195 if (feof(F)) { 196 clearerr(F); 197 fwrite(Buf, 1, 10, F); // no warning 198 } else if (ferror(F)) { 199 clearerr(F); 200 fwrite(Buf, 1, 10, F); // expected-warning {{might be 'indeterminate'}} 201 } else { 202 clearerr(F); 203 fwrite(Buf, 1, 10, F); // expected-warning {{might be 'indeterminate'}} 204 } 205 } 206 fclose(F); 207 } 208 209 void error_indeterminate_feof1(void) { 210 FILE *F = fopen("file", "r+"); 211 if (!F) 212 return; 213 char Buf[10]; 214 if (fread(Buf, 1, 10, F) < 10) { 215 if (feof(F)) { 216 // error is feof, should be non-indeterminate 217 fwrite("1", 1, 1, F); // no warning 218 } 219 } 220 fclose(F); 221 } 222 223 void error_indeterminate_feof2(void) { 224 FILE *F = fopen("file", "r+"); 225 if (!F) 226 return; 227 char Buf[10]; 228 if (fread(Buf, 1, 10, F) < 10) { 229 if (ferror(F) == 0) { 230 // error is feof, should be non-indeterminate 231 fwrite("1", 1, 1, F); // no warning 232 } 233 } 234 fclose(F); 235 } 236