Revert "[llvm] Improve llvm.objectsize computation by computing GEP, alloca and mallo...
[llvm-project.git] / clang / test / Analysis / getline-unixapi.c
blob86635ed8499793ccf897696e713b7193a1d69b7a
1 // RUN: %clang_analyze_cc1 -analyzer-checker=core,unix,debug.ExprInspection -verify %s
3 #include "Inputs/system-header-simulator.h"
4 #include "Inputs/system-header-simulator-for-malloc.h"
5 #include "Inputs/system-header-simulator-for-valist.h"
7 void clang_analyzer_eval(int);
8 void clang_analyzer_dump_int(int);
9 void clang_analyzer_dump_ptr(void*);
10 void clang_analyzer_warnIfReached();
12 void test_getline_null_lineptr() {
13 FILE *F1 = tmpfile();
14 if (!F1)
15 return;
17 char **buffer = NULL;
18 size_t n = 0;
19 getline(buffer, &n, F1); // expected-warning {{Line pointer might be NULL}}
20 fclose(F1);
23 void test_getline_null_size() {
24 FILE *F1 = tmpfile();
25 if (!F1)
26 return;
27 char *buffer = NULL;
28 getline(&buffer, NULL, F1); // expected-warning {{Size pointer might be NULL}}
29 fclose(F1);
32 void test_getline_null_buffer_size_gt0() {
33 FILE *F1 = tmpfile();
34 if (!F1)
35 return;
36 char *buffer = NULL;
37 size_t n = 8;
38 getline(&buffer, &n, F1); // ok since posix 2018
39 free(buffer);
40 fclose(F1);
43 void test_getline_null_buffer_size_gt0_2(size_t n) {
44 FILE *F1 = tmpfile();
45 if (!F1)
46 return;
47 char *buffer = NULL;
48 if (n > 0) {
49 getline(&buffer, &n, F1); // ok since posix 2018
51 free(buffer);
52 fclose(F1);
55 void test_getline_null_buffer_unknown_size(size_t n) {
56 FILE *F1 = tmpfile();
57 if (!F1)
58 return;
59 char *buffer = NULL;
61 getline(&buffer, &n, F1); // ok
62 fclose(F1);
63 free(buffer);
66 void test_getline_null_buffer_undef_size() {
67 FILE *F1 = tmpfile();
68 if (!F1)
69 return;
71 char *buffer = NULL;
72 size_t n;
74 getline(&buffer, &n, F1); // ok since posix 2018
75 fclose(F1);
76 free(buffer);
79 void test_getline_buffer_size_0() {
80 FILE *F1 = tmpfile();
81 if (!F1)
82 return;
84 char *buffer = malloc(10);
85 size_t n = 0;
86 if (buffer != NULL)
87 getline(&buffer, &n, F1); // ok, the buffer is enough for 0 character
88 fclose(F1);
89 free(buffer);
92 void test_getline_buffer_bad_size() {
93 FILE *F1 = tmpfile();
94 if (!F1)
95 return;
97 char *buffer = malloc(10);
98 size_t n = 100;
99 if (buffer != NULL)
100 getline(&buffer, &n, F1); // expected-warning {{The buffer from the first argument is smaller than the size specified by the second parameter}}
101 fclose(F1);
102 free(buffer);
105 void test_getline_buffer_smaller_size() {
106 FILE *F1 = tmpfile();
107 if (!F1)
108 return;
110 char *buffer = malloc(100);
111 size_t n = 10;
112 if (buffer != NULL)
113 getline(&buffer, &n, F1); // ok, there is enough space for 10 characters
114 fclose(F1);
115 free(buffer);
118 void test_getline_buffer_undef_size() {
119 FILE *F1 = tmpfile();
120 if (!F1)
121 return;
123 char *buffer = malloc(100);
124 size_t n;
125 if (buffer != NULL)
126 getline(&buffer, &n, F1); // expected-warning {{The buffer from the first argument is not NULL, but the size specified by the second parameter is undefined}}
127 fclose(F1);
128 free(buffer);
132 void test_getline_null_buffer() {
133 FILE *F1 = tmpfile();
134 if (!F1)
135 return;
136 char *buffer = NULL;
137 size_t n = 0;
138 ssize_t r = getline(&buffer, &n, F1);
139 // getline returns -1 on failure, number of char reads on success (>= 0)
140 if (r < -1) {
141 clang_analyzer_warnIfReached(); // must not happen
142 } else {
143 // The buffer could be allocated both on failure and success
144 clang_analyzer_dump_int(n); // expected-warning {{conj_$}}
145 clang_analyzer_dump_ptr(buffer); // expected-warning {{conj_$}}
147 free(buffer);
148 fclose(F1);
151 void test_getdelim_null_size() {
152 FILE *F1 = tmpfile();
153 if (!F1)
154 return;
155 char *buffer = NULL;
156 getdelim(&buffer, NULL, ',', F1); // expected-warning {{Size pointer might be NULL}}
157 fclose(F1);
160 void test_getdelim_null_buffer_size_gt0() {
161 FILE *F1 = tmpfile();
162 if (!F1)
163 return;
164 char *buffer = NULL;
165 size_t n = 8;
166 getdelim(&buffer, &n, ';', F1); // ok since posix 2018
167 free(buffer);
168 fclose(F1);
171 void test_getdelim_null_buffer_size_gt0_2(size_t n) {
172 FILE *F1 = tmpfile();
173 if (!F1)
174 return;
175 char *buffer = NULL;
176 if (n > 0) {
177 getdelim(&buffer, &n, ' ', F1); // ok since posix 2018
179 free(buffer);
180 fclose(F1);
183 void test_getdelim_null_buffer_unknown_size(size_t n) {
184 FILE *F1 = tmpfile();
185 if (!F1)
186 return;
187 char *buffer = NULL;
188 getdelim(&buffer, &n, '-', F1); // ok
189 fclose(F1);
190 free(buffer);
193 void test_getdelim_null_buffer() {
194 FILE *F1 = tmpfile();
195 if (!F1)
196 return;
197 char *buffer = NULL;
198 size_t n = 0;
199 ssize_t r = getdelim(&buffer, &n, '\r', F1);
200 // getdelim returns -1 on failure, number of char reads on success (>= 0)
201 if (r < -1) {
202 clang_analyzer_warnIfReached(); // must not happen
204 else {
205 // The buffer could be allocated both on failure and success
206 clang_analyzer_dump_int(n); // expected-warning {{conj_$}}
207 clang_analyzer_dump_ptr(buffer); // expected-warning {{conj_$}}
209 free(buffer);
210 fclose(F1);
213 void test_getline_while() {
214 FILE *file = fopen("file.txt", "r");
215 if (file == NULL) {
216 return;
219 char *line = NULL;
220 size_t len = 0;
221 ssize_t read;
223 while ((read = getline(&line, &len, file)) != -1) {
224 printf("%s\n", line);
227 free(line);
228 fclose(file);
231 void test_getline_return_check() {
232 FILE *file = fopen("file.txt", "r");
233 if (file == NULL) {
234 return;
237 char *line = NULL;
238 size_t len = 0;
239 ssize_t r = getline(&line, &len, file);
241 if (r != -1) {
242 if (line[0] == '\0') {} // ok
244 free(line);
245 fclose(file);
248 void test_getline_clear_eof() {
249 FILE *file = fopen("file.txt", "r");
250 if (file == NULL) {
251 return;
254 size_t n = 10;
255 char *buffer = malloc(n);
256 ssize_t read = fread(buffer, n, 1, file);
257 if (feof(file)) {
258 clearerr(file);
259 getline(&buffer, &n, file); // ok
261 fclose(file);
262 free(buffer);
265 void test_getline_not_null(char **buffer, size_t *size) {
266 FILE *file = fopen("file.txt", "r");
267 if (file == NULL) {
268 return;
271 getline(buffer, size, file);
272 fclose(file);
274 if (size == NULL || buffer == NULL) {
275 clang_analyzer_warnIfReached(); // must not happen
279 void test_getline_size_constraint(size_t size) {
280 FILE *file = fopen("file.txt", "r");
281 if (file == NULL) {
282 return;
285 size_t old_size = size;
286 char *buffer = malloc(10);
287 if (buffer != NULL) {
288 ssize_t r = getline(&buffer, &size, file);
289 if (r >= 0) {
290 // Since buffer has a size of 10, old_size must be less than or equal to 10.
291 // Otherwise, there would be UB.
292 clang_analyzer_eval(old_size <= 10); // expected-warning{{TRUE}}
295 fclose(file);
296 free(buffer);
299 void test_getline_negative_buffer() {
300 FILE *file = fopen("file.txt", "r");
301 if (file == NULL) {
302 return;
305 char *buffer = NULL;
306 size_t n = -1;
307 getline(&buffer, &n, file); // ok since posix 2018
308 free(buffer);
309 fclose(file);
312 void test_getline_negative_buffer_2(char *buffer) {
313 FILE *file = fopen("file.txt", "r");
314 if (file == NULL) {
315 return;
318 size_t n = -1;
319 (void)getline(&buffer, &n, file); // ok
320 free(buffer);
321 fclose(file);