1 // RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.unix.Stream -analyzer-output text -verify %s
2 
3 #include "Inputs/system-header-simulator.h"
4 
check_note_at_correct_open(void)5 void check_note_at_correct_open(void) {
6   FILE *F1 = tmpfile(); // expected-note {{Stream opened here}}
7   if (!F1)
8     // expected-note@-1 {{'F1' is non-null}}
9     // expected-note@-2 {{Taking false branch}}
10     return;
11   FILE *F2 = tmpfile();
12   if (!F2) {
13     // expected-note@-1 {{'F2' is non-null}}
14     // expected-note@-2 {{Taking false branch}}
15     fclose(F1);
16     return;
17   }
18   rewind(F2);
19   fclose(F2);
20   rewind(F1);
21 }
22 // expected-warning@-1 {{Opened stream never closed. Potential resource leak}}
23 // expected-note@-2 {{Opened stream never closed. Potential resource leak}}
24 
check_note_fopen(void)25 void check_note_fopen(void) {
26   FILE *F = fopen("file", "r"); // expected-note {{Stream opened here}}
27   if (!F)
28     // expected-note@-1 {{'F' is non-null}}
29     // expected-note@-2 {{Taking false branch}}
30     return;
31 }
32 // expected-warning@-1 {{Opened stream never closed. Potential resource leak}}
33 // expected-note@-2 {{Opened stream never closed. Potential resource leak}}
34 
check_note_freopen(void)35 void check_note_freopen(void) {
36   FILE *F = fopen("file", "r"); // expected-note {{Stream opened here}}
37   if (!F)
38     // expected-note@-1 {{'F' is non-null}}
39     // expected-note@-2 {{Taking false branch}}
40     return;
41   F = freopen(0, "w", F); // expected-note {{Stream reopened here}}
42   if (!F)
43     // expected-note@-1 {{'F' is non-null}}
44     // expected-note@-2 {{Taking false branch}}
45     return;
46 }
47 // expected-warning@-1 {{Opened stream never closed. Potential resource leak}}
48 // expected-note@-2 {{Opened stream never closed. Potential resource leak}}
49 
check_note_leak_2(int c)50 void check_note_leak_2(int c) {
51   FILE *F1 = fopen("foo1.c", "r"); // expected-note {{Stream opened here}}
52   if (!F1)
53     // expected-note@-1 {{'F1' is non-null}}
54     // expected-note@-2 {{Taking false branch}}
55     // expected-note@-3 {{'F1' is non-null}}
56     // expected-note@-4 {{Taking false branch}}
57     return;
58   FILE *F2 = fopen("foo2.c", "r"); // expected-note {{Stream opened here}}
59   if (!F2) {
60     // expected-note@-1 {{'F2' is non-null}}
61     // expected-note@-2 {{Taking false branch}}
62     // expected-note@-3 {{'F2' is non-null}}
63     // expected-note@-4 {{Taking false branch}}
64     fclose(F1);
65     return;
66   }
67   if (c)
68     // expected-note@-1 {{Assuming 'c' is not equal to 0}}
69     // expected-note@-2 {{Taking true branch}}
70     // expected-note@-3 {{Assuming 'c' is not equal to 0}}
71     // expected-note@-4 {{Taking true branch}}
72     return;
73   // expected-warning@-1 {{Opened stream never closed. Potential resource leak}}
74   // expected-note@-2 {{Opened stream never closed. Potential resource leak}}
75   // expected-warning@-3 {{Opened stream never closed. Potential resource leak}}
76   // expected-note@-4 {{Opened stream never closed. Potential resource leak}}
77   fclose(F1);
78   fclose(F2);
79 }
80 
check_track_null(void)81 void check_track_null(void) {
82   FILE *F;
83   F = fopen("foo1.c", "r"); // expected-note {{Value assigned to 'F'}} expected-note {{Assuming pointer value is null}}
84   if (F != NULL) {          // expected-note {{Taking false branch}} expected-note {{'F' is equal to NULL}}
85     fclose(F);
86     return;
87   }
88   fclose(F); // expected-warning {{Stream pointer might be NULL}}
89   // expected-note@-1 {{Stream pointer might be NULL}}
90 }
91 
check_eof_notes_feof_after_feof(void)92 void check_eof_notes_feof_after_feof(void) {
93   FILE *F;
94   char Buf[10];
95   F = fopen("foo1.c", "r");
96   if (F == NULL) { // expected-note {{Taking false branch}} expected-note {{'F' is not equal to NULL}}
97     return;
98   }
99   fread(Buf, 1, 1, F);
100   if (feof(F)) { // expected-note {{Taking true branch}}
101     clearerr(F);
102     fread(Buf, 1, 1, F);   // expected-note {{Assuming stream reaches end-of-file here}}
103     if (feof(F)) {         // expected-note {{Taking true branch}}
104       fread(Buf, 1, 1, F); // expected-warning {{Read function called when stream is in EOF state. Function has no effect}}
105       // expected-note@-1 {{Read function called when stream is in EOF state. Function has no effect}}
106     }
107   }
108   fclose(F);
109 }
110 
check_eof_notes_feof_after_no_feof(void)111 void check_eof_notes_feof_after_no_feof(void) {
112   FILE *F;
113   char Buf[10];
114   F = fopen("foo1.c", "r");
115   if (F == NULL) { // expected-note {{Taking false branch}} expected-note {{'F' is not equal to NULL}}
116     return;
117   }
118   fread(Buf, 1, 1, F);
119   if (feof(F)) { // expected-note {{Taking false branch}}
120     fclose(F);
121     return;
122   } else if (ferror(F)) { // expected-note {{Taking false branch}}
123     fclose(F);
124     return;
125   }
126   fread(Buf, 1, 1, F);   // expected-note {{Assuming stream reaches end-of-file here}}
127   if (feof(F)) {         // expected-note {{Taking true branch}}
128     fread(Buf, 1, 1, F); // expected-warning {{Read function called when stream is in EOF state. Function has no effect}}
129     // expected-note@-1 {{Read function called when stream is in EOF state. Function has no effect}}
130   }
131   fclose(F);
132 }
133 
check_eof_notes_feof_or_no_error(void)134 void check_eof_notes_feof_or_no_error(void) {
135   FILE *F;
136   char Buf[10];
137   F = fopen("foo1.c", "r");
138   if (F == NULL) // expected-note {{Taking false branch}} expected-note {{'F' is not equal to NULL}}
139     return;
140   int RRet = fread(Buf, 1, 1, F); // expected-note {{Assuming stream reaches end-of-file here}}
141   if (ferror(F)) {                // expected-note {{Taking false branch}}
142   } else {
143     fread(Buf, 1, 1, F); // expected-warning {{Read function called when stream is in EOF state. Function has no effect}}
144     // expected-note@-1 {{Read function called when stream is in EOF state. Function has no effect}}
145   }
146   fclose(F);
147 }
148