brintos

brintos / llvm-project-archived public Read only

0
0
Text · 13.8 KiB · 10e6e53 Raw
555 lines · c
1// RUN: %clang_analyze_cc1 -triple=x86_64-pc-linux-gnu -analyzer-checker=core,unix.Stream,debug.ExprInspection \2// RUN:   -analyzer-config eagerly-assume=false,unix.Stream:Pedantic=true -verify %s3// RUN: %clang_analyze_cc1 -triple=armv8-none-linux-eabi -analyzer-checker=core,unix.Stream,debug.ExprInspection \4// RUN:   -analyzer-config eagerly-assume=false,unix.Stream:Pedantic=true -verify %s5// RUN: %clang_analyze_cc1 -triple=aarch64-linux-gnu -analyzer-checker=core,unix.Stream,debug.ExprInspection \6// RUN:   -analyzer-config eagerly-assume=false,unix.Stream:Pedantic=true -verify %s7// RUN: %clang_analyze_cc1 -triple=hexagon -analyzer-checker=core,unix.Stream,debug.ExprInspection \8// RUN:   -analyzer-config eagerly-assume=false,unix.Stream:Pedantic=true -verify %s9 10#include "Inputs/system-header-simulator.h"11#include "Inputs/system-header-simulator-for-malloc.h"12#include "Inputs/system-header-simulator-for-valist.h"13 14void clang_analyzer_eval(int);15 16void check_fread(void) {17  FILE *fp = tmpfile();18  fread(0, 0, 0, fp); // expected-warning {{Stream pointer might be NULL}}19  fclose(fp);20}21 22void check_fwrite(void) {23  FILE *fp = tmpfile();24  fwrite(0, 0, 0, fp); // expected-warning {{Stream pointer might be NULL}}25  fclose(fp);26}27 28void check_fgetc(void) {29  FILE *fp = tmpfile();30  fgetc(fp); // expected-warning {{Stream pointer might be NULL}}31  fclose(fp);32}33 34void check_fgets(void) {35  FILE *fp = tmpfile();36  char buf[256];37  fgets(buf, sizeof(buf), fp); // expected-warning {{Stream pointer might be NULL}}38  fclose(fp);39}40 41void check_fputc(void) {42  FILE *fp = tmpfile();43  fputc('A', fp); // expected-warning {{Stream pointer might be NULL}}44  fclose(fp);45}46 47void check_fputs(void) {48  FILE *fp = tmpfile();49  fputs("ABC", fp); // expected-warning {{Stream pointer might be NULL}}50  fclose(fp);51}52 53void check_fprintf(void) {54  FILE *fp = tmpfile();55  fprintf(fp, "ABC"); // expected-warning {{Stream pointer might be NULL}}56  fclose(fp);57}58 59void check_fscanf(void) {60  FILE *fp = tmpfile();61  fscanf(fp, "ABC"); // expected-warning {{Stream pointer might be NULL}}62  fclose(fp);63}64 65void check_ungetc(void) {66  FILE *fp = tmpfile();67  ungetc('A', fp); // expected-warning {{Stream pointer might be NULL}}68  fclose(fp);69}70 71void check_fseek(void) {72  FILE *fp = tmpfile();73  fseek(fp, 0, 0); // expected-warning {{Stream pointer might be NULL}}74  fclose(fp);75}76 77void check_fseeko(void) {78  FILE *fp = tmpfile();79  fseeko(fp, 0, 0); // expected-warning {{Stream pointer might be NULL}}80  fclose(fp);81}82 83void check_ftell(void) {84  FILE *fp = tmpfile();85  ftell(fp); // expected-warning {{Stream pointer might be NULL}}86  fclose(fp);87}88 89void check_ftello(void) {90  FILE *fp = tmpfile();91  ftello(fp); // expected-warning {{Stream pointer might be NULL}}92  fclose(fp);93}94 95void check_rewind(void) {96  FILE *fp = tmpfile();97  rewind(fp); // expected-warning {{Stream pointer might be NULL}}98  fclose(fp);99}100 101void check_fgetpos(void) {102  FILE *fp = tmpfile();103  fpos_t pos;104  fgetpos(fp, &pos); // expected-warning {{Stream pointer might be NULL}}105  fclose(fp);106}107 108void check_fsetpos(void) {109  FILE *fp = tmpfile();110  fpos_t pos;111  fsetpos(fp, &pos); // expected-warning {{Stream pointer might be NULL}}112  fclose(fp);113}114 115void check_clearerr(void) {116  FILE *fp = tmpfile();117  clearerr(fp); // expected-warning {{Stream pointer might be NULL}}118  fclose(fp);119}120 121void check_feof(void) {122  FILE *fp = tmpfile();123  feof(fp); // expected-warning {{Stream pointer might be NULL}}124  fclose(fp);125}126 127void check_ferror(void) {128  FILE *fp = tmpfile();129  ferror(fp); // expected-warning {{Stream pointer might be NULL}}130  fclose(fp);131}132 133void check_fileno(void) {134  FILE *fp = tmpfile();135  fileno(fp); // expected-warning {{Stream pointer might be NULL}}136  fclose(fp);137}138 139void f_open(void) {140  FILE *p = fopen("foo", "r");141  char buf[1024];142  fread(buf, 1, 1, p); // expected-warning {{Stream pointer might be NULL}}143  fclose(p);144}145 146void f_dopen(int fd) {147  FILE *F = fdopen(fd, "r");148  char buf[1024];149  fread(buf, 1, 1, F); // expected-warning {{Stream pointer might be NULL}}150  fclose(F);151}152 153void f_vfprintf(int fd, va_list args) {154  FILE *F = fdopen(fd, "r");155  vfprintf(F, "%d", args); // expected-warning {{Stream pointer might be NULL}}156  fclose(F);157}158 159void f_vfscanf(int fd, va_list args) {160  FILE *F = fdopen(fd, "r");161  vfscanf(F, "%u", args); // expected-warning {{Stream pointer might be NULL}}162  fclose(F);163}164 165void f_seek(void) {166  FILE *p = fopen("foo", "r");167  if (!p)168    return;169  fseek(p, 1, SEEK_SET); // no-warning170  fseek(p, 1, 3); // expected-warning {{The whence argument to fseek() should be SEEK_SET, SEEK_END, or SEEK_CUR}}171  fclose(p);172}173 174void f_seeko(void) {175  FILE *p = fopen("foo", "r");176  if (!p)177    return;178  fseeko(p, 1, SEEK_SET); // no-warning179  fseeko(p, 1, 3); // expected-warning {{The whence argument to fseek() should be SEEK_SET, SEEK_END, or SEEK_CUR}}180  fclose(p);181}182 183void f_double_close(void) {184  FILE *p = fopen("foo", "r");185  if (!p)186    return;187  fclose(p);188  fclose(p); // expected-warning {{Use of a stream that might be already closed}}189}190 191void f_double_close_alias(void) {192  FILE *p1 = fopen("foo", "r");193  if (!p1)194    return;195  FILE *p2 = p1;196  fclose(p1);197  fclose(p2); // expected-warning {{Use of a stream that might be already closed}}198}199 200void f_use_after_close(void) {201  FILE *p = fopen("foo", "r");202  if (!p)203    return;204  fclose(p);205  clearerr(p); // expected-warning {{Use of a stream that might be already closed}}206}207 208void f_open_after_close(void) {209  FILE *p = fopen("foo", "r");210  if (!p)211    return;212  fclose(p);213  p = fopen("foo", "r");214  if (!p)215    return;216  fclose(p);217}218 219void f_reopen_after_close(void) {220  FILE *p = fopen("foo", "r");221  if (!p)222    return;223  fclose(p);224  // Allow reopen after close.225  p = freopen("foo", "w", p);226  if (!p)227    return;228  fclose(p);229}230 231void f_leak(int c) {232  FILE *p = fopen("foo.c", "r");233  if (!p)234    return;235  if(c)236    return; // expected-warning {{Opened stream never closed. Potential resource leak}}237  fclose(p);238}239 240FILE *f_null_checked(void) {241  FILE *p = fopen("foo.c", "r");242  if (p)243    return p; // no-warning244  else245    return 0;246}247 248void pr7831(FILE *fp) {249  fclose(fp); // no-warning250}251 252// PR 8081 - null pointer crash when 'whence' is not an integer constant253void pr8081(FILE *stream, long offset, int whence) {254  fseek(stream, offset, whence);255}256 257void check_freopen_1(void) {258  FILE *f1 = freopen("foo.c", "r", (FILE *)0); // expected-warning {{Stream pointer might be NULL}}259  f1 = freopen(0, "w", (FILE *)0x123456);      // Do not report this as error.260}261 262void check_freopen_2(void) {263  FILE *f1 = fopen("foo.c", "r");264  if (f1) {265    FILE *f2 = freopen(0, "w", f1);266    if (f2) {267      // Check if f1 and f2 point to the same stream.268      fclose(f1);269      fclose(f2); // expected-warning {{Use of a stream that might be already closed}}270    } else {271      // Reopen failed.272      // f1 is non-NULL but points to a possibly invalid stream.273      rewind(f1); // expected-warning {{Stream might be invalid}}274      // f2 is NULL but the previous error stops the checker.275      rewind(f2);276    }277  }278}279 280void check_freopen_3(void) {281  FILE *f1 = fopen("foo.c", "r");282  if (f1) {283    // Unchecked result of freopen.284    // The f1 may be invalid after this call.285    freopen(0, "w", f1);286    rewind(f1); // expected-warning {{Stream might be invalid}}287    fclose(f1);288  }289}290 291extern FILE *GlobalF;292extern void takeFile(FILE *);293 294void check_escape1(void) {295  FILE *F = tmpfile();296  if (!F)297    return;298  fwrite("1", 1, 1, F); // may fail299  GlobalF = F;300  fwrite("1", 1, 1, F); // no warning301}302 303void check_escape2(void) {304  FILE *F = tmpfile();305  if (!F)306    return;307  fwrite("1", 1, 1, F); // may fail308  takeFile(F);309  fwrite("1", 1, 1, F); // no warning310}311 312void check_escape3(void) {313  FILE *F = tmpfile();314  if (!F)315    return;316  takeFile(F);317  F = freopen(0, "w", F);318  if (!F)319    return;320  fwrite("1", 1, 1, F); // may fail321  fwrite("1", 1, 1, F); // no warning322}323 324void check_escape4(void) {325  FILE *F = tmpfile();326  if (!F)327    return;328  fwrite("1", 1, 1, F); // may fail329 330  // no escape at a non-StreamChecker-handled system call331  setbuf(F, "0");332 333  fwrite("1", 1, 1, F); // expected-warning {{might be 'indeterminate'}}334  fclose(F);335}336 337int Test;338_Noreturn void handle_error(void);339 340void check_leak_noreturn_1(void) {341  FILE *F1 = tmpfile();342  if (!F1)343    return;344  if (Test == 1) {345    handle_error(); // no warning346  }347  rewind(F1);348} // expected-warning {{Opened stream never closed. Potential resource leak}}349 350// Check that "location uniqueing" works.351// This results in reporting only one occurence of resource leak for a stream.352void check_leak_noreturn_2(void) {353  FILE *F1 = tmpfile();354  if (!F1)355    return;356  if (Test == 1) {357    return; // no warning358  }359  rewind(F1);360} // expected-warning {{Opened stream never closed. Potential resource leak}}361// FIXME: This warning should be placed at the `return` above.362// See https://reviews.llvm.org/D83120 about details.363 364void fflush_after_fclose(void) {365  FILE *F = tmpfile();366  int Ret;367  fflush(NULL);                      // no-warning368  if (!F)369    return;370  if ((Ret = fflush(F)) != 0)371    clang_analyzer_eval(Ret == EOF); // expected-warning {{TRUE}}372  fclose(F);373  fflush(F);                         // expected-warning {{Use of a stream that might be already closed}}374}375 376void fflush_on_open_failed_stream(void) {377  FILE *F = tmpfile();378  if (!F) {379    fflush(F); // no-warning380    return;381  }382  fclose(F);383}384 385void getline_null_file() {386  char *buffer = NULL;387  size_t n = 0;388  getline(&buffer, &n, NULL); // expected-warning {{Stream pointer might be NULL}}389}390 391void getdelim_null_file() {392  char *buffer = NULL;393  size_t n = 0;394  getdelim(&buffer, &n, '\n', NULL); // expected-warning {{Stream pointer might be NULL}}395}396 397void getline_buffer_on_error() {398  FILE *file = fopen("file.txt", "r");399  if (file == NULL) {400    return;401  }402 403  char *line = NULL;404  size_t len = 0;405  if (getline(&line, &len, file) == -1) {406    if (line[0] == '\0') {} // expected-warning {{The left operand of '==' is a garbage value}}407  } else {408    if (line[0] == '\0') {} // no warning409  }410 411  free(line);412  fclose(file);413}414 415void getline_ret_value() {416  FILE *file = fopen("file.txt", "r");417  if (file == NULL) {418    return;419  }420 421  size_t n = 0;422  char *buffer = NULL;423  ssize_t r = getline(&buffer, &n, file);424 425  if (r > -1) {426    // The return value does *not* include the terminating null byte.427    // The buffer must be large enough to include it.428    clang_analyzer_eval(n > r); // expected-warning{{TRUE}}429    clang_analyzer_eval(buffer != NULL);  // expected-warning{{TRUE}}430  }431 432  fclose(file);433  free(buffer);434}435 436 437void getline_buffer_size_negative() {438  FILE *file = fopen("file.txt", "r");439  if (file == NULL) {440    return;441  }442 443  size_t n = -1;444  clang_analyzer_eval((ssize_t)n >= 0); // expected-warning{{FALSE}}445  char *buffer = NULL;446  ssize_t r = getline(&buffer, &n, file);447 448  if (r > -1) {449    clang_analyzer_eval((ssize_t)n > r); // expected-warning{{TRUE}}450    clang_analyzer_eval(buffer != NULL);  // expected-warning{{TRUE}}451  }452 453  free(buffer);454  fclose(file);455}456 457void gh_93408_regression(void *buffer) {458  FILE *f = fopen("/tmp/foo.txt", "r");459  fread(buffer, 1, 1, f); // expected-warning {{Stream pointer might be NULL}} no-crash460  fclose(f);461}462 463typedef void VOID;464void gh_93408_regression_typedef(VOID *buffer) {465  FILE *f = fopen("/tmp/foo.txt", "r");466  fread(buffer, 1, 1, f); // expected-warning {{Stream pointer might be NULL}} no-crash467  fclose(f);468}469 470struct FAM {471  int data;472  int tail[];473};474 475struct FAM0 {476  int data;477  int tail[0];478};479 480void gh_93408_regression_FAM(struct FAM *p) {481  FILE *f = fopen("/tmp/foo.txt", "r");482  fread(p->tail, 1, 1, f); // expected-warning {{Stream pointer might be NULL}}483  fclose(f);484}485 486void gh_93408_regression_FAM0(struct FAM0 *p) {487  FILE *f = fopen("/tmp/foo.txt", "r");488  fread(p->tail, 1, 1, f); // expected-warning {{Stream pointer might be NULL}}489  fclose(f);490}491 492struct ZeroSized {493    int data[0];494};495 496void gh_93408_regression_ZeroSized(struct ZeroSized *buffer) {497  FILE *f = fopen("/tmp/foo.txt", "r");498  fread(buffer, 1, 1, f); // expected-warning {{Stream pointer might be NULL}} no-crash499  fclose(f);500}501 502extern FILE *non_standard_stream_ptr;503void test_fopen_does_not_alias_with_standard_streams(void) {504  FILE *f = fopen("file", "r");505  if (!f) return;506  clang_analyzer_eval(f == stdin);  // expected-warning {{FALSE}} no-TRUE507  clang_analyzer_eval(f == stdout); // expected-warning {{FALSE}} no-TRUE508  clang_analyzer_eval(f == stderr); // expected-warning {{FALSE}} no-TRUE509  clang_analyzer_eval(f == non_standard_stream_ptr); // expected-warning {{UNKNOWN}}510  if (f != stdout) {511    fclose(f);512  }513} // no-leak: 'fclose()' is always called because 'f' cannot be 'stdout'.514 515void reopen_std_stream(void) {516  FILE *oldStdout = stdout;517  fclose(stdout);518  FILE *fp = fopen("blah", "w");519  if (!fp) return;520 521  stdout = fp; // Let's make them alias.522  clang_analyzer_eval(fp == oldStdout);     // expected-warning {{FALSE}}523  clang_analyzer_eval(fp == stdout);        // expected-warning {{TRUE}}524  clang_analyzer_eval(oldStdout == stdout); // expected-warning {{FALSE}}525}526 527void only_success_path_does_not_alias_with_stdout(void) {528  if (stdout) return;529  FILE *f = fopen("/tmp/foof", "r"); // no-crash530  clang_analyzer_eval(f == 0);// expected-warning {{TRUE}} expected-warning {{FALSE}}531  if (!f) return;532  fclose(f);533}534 535extern void do_something();536 537void test_no_invalidate_at_system_call() {538  FILE *old_stdin = stdin;539  if ((stdin = fopen("x/y/z", "r")) == NULL)540    return;541  clang_analyzer_eval(old_stdin == stdin); // expected-warning{{FALSE}}542  free(malloc(100));543  clang_analyzer_eval(old_stdin == stdin); // expected-warning{{FALSE}}544  fclose(stdin);545}546 547void test_invalidate_at_non_system_call() {548  FILE *old_stdin = stdin;549  if ((stdin = fopen("x/y/z", "r")) == NULL)550    return;551  clang_analyzer_eval(old_stdin == stdin); // expected-warning{{FALSE}}552  do_something();553  clang_analyzer_eval(old_stdin == stdin); // expected-warning{{UNKNOWN}}554}555