323 lines · c
1// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix,debug.ExprInspection -verify %s2 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"6 7void clang_analyzer_eval(int);8void clang_analyzer_dump_int(int);9void clang_analyzer_dump_ptr(void*);10void clang_analyzer_warnIfReached();11 12void test_getline_null_lineptr() {13 FILE *F1 = tmpfile();14 if (!F1)15 return;16 17 char **buffer = NULL;18 size_t n = 0;19 getline(buffer, &n, F1); // expected-warning {{Line pointer might be NULL}}20 fclose(F1);21}22 23void 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);30}31 32void 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 201839 free(buffer);40 fclose(F1);41}42 43void 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 201850 }51 free(buffer);52 fclose(F1);53}54 55void test_getline_null_buffer_unknown_size(size_t n) {56 FILE *F1 = tmpfile();57 if (!F1)58 return;59 char *buffer = NULL;60 61 getline(&buffer, &n, F1); // ok62 fclose(F1);63 free(buffer);64}65 66void test_getline_null_buffer_undef_size() {67 FILE *F1 = tmpfile();68 if (!F1)69 return;70 71 char *buffer = NULL;72 size_t n;73 74 getline(&buffer, &n, F1); // ok since posix 201875 fclose(F1);76 free(buffer);77}78 79void test_getline_buffer_size_0() {80 FILE *F1 = tmpfile();81 if (!F1)82 return;83 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 character88 fclose(F1);89 free(buffer);90}91 92void test_getline_buffer_bad_size() {93 FILE *F1 = tmpfile();94 if (!F1)95 return;96 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);103}104 105void test_getline_buffer_smaller_size() {106 FILE *F1 = tmpfile();107 if (!F1)108 return;109 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 characters114 fclose(F1);115 free(buffer);116}117 118void test_getline_buffer_undef_size() {119 FILE *F1 = tmpfile();120 if (!F1)121 return;122 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);129}130 131 132void 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 happen142 } else {143 // The buffer could be allocated both on failure and success144 clang_analyzer_dump_int(n); // expected-warning {{conj_$}}145 clang_analyzer_dump_ptr(buffer); // expected-warning {{conj_$}}146 }147 free(buffer);148 fclose(F1);149}150 151void 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);158}159 160void 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 2018167 free(buffer);168 fclose(F1);169}170 171void 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 2018178 }179 free(buffer);180 fclose(F1);181}182 183void 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); // ok189 fclose(F1);190 free(buffer);191}192 193void 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 happen203 }204 else {205 // The buffer could be allocated both on failure and success206 clang_analyzer_dump_int(n); // expected-warning {{conj_$}}207 clang_analyzer_dump_ptr(buffer); // expected-warning {{conj_$}}208 }209 free(buffer);210 fclose(F1);211}212 213void test_getline_while() {214 FILE *file = fopen("file.txt", "r");215 if (file == NULL) {216 return;217 }218 219 char *line = NULL;220 size_t len = 0;221 ssize_t read;222 223 while ((read = getline(&line, &len, file)) != -1) {224 printf("%s\n", line);225 }226 227 free(line);228 fclose(file);229}230 231void test_getline_return_check() {232 FILE *file = fopen("file.txt", "r");233 if (file == NULL) {234 return;235 }236 237 char *line = NULL;238 size_t len = 0;239 ssize_t r = getline(&line, &len, file);240 241 if (r != -1) {242 if (line[0] == '\0') {} // ok243 }244 free(line);245 fclose(file);246}247 248void test_getline_clear_eof() {249 FILE *file = fopen("file.txt", "r");250 if (file == NULL) {251 return;252 }253 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); // ok260 }261 fclose(file);262 free(buffer);263}264 265void test_getline_not_null(char **buffer, size_t *size) {266 FILE *file = fopen("file.txt", "r");267 if (file == NULL) {268 return;269 }270 271 getline(buffer, size, file);272 fclose(file);273 274 if (size == NULL || buffer == NULL) {275 clang_analyzer_warnIfReached(); // must not happen276 }277}278 279void test_getline_size_constraint(size_t size) {280 FILE *file = fopen("file.txt", "r");281 if (file == NULL) {282 return;283 }284 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}}293 }294 }295 fclose(file);296 free(buffer);297}298 299void test_getline_negative_buffer() {300 FILE *file = fopen("file.txt", "r");301 if (file == NULL) {302 return;303 }304 305 char *buffer = NULL;306 size_t n = -1;307 getline(&buffer, &n, file); // ok since posix 2018308 free(buffer);309 fclose(file);310}311 312void test_getline_negative_buffer_2(char *buffer) {313 FILE *file = fopen("file.txt", "r");314 if (file == NULL) {315 return;316 }317 318 size_t n = -1;319 (void)getline(&buffer, &n, file); // ok320 free(buffer);321 fclose(file);322}323