|  | // RUN: %clang_analyze_cc1 -verify %s \ | 
|  | // RUN: -analyzer-checker=core \ | 
|  | // RUN: -analyzer-checker=unix.Stream \ | 
|  | // RUN: -analyzer-checker=debug.ExprInspection | 
|  |  | 
|  | #include "Inputs/system-header-simulator.h" | 
|  | #include "Inputs/system-header-simulator-for-valist.h" | 
|  |  | 
|  | void clang_analyzer_eval(int); | 
|  | void clang_analyzer_dump(int); | 
|  |  | 
|  | void test_fread(void) { | 
|  | FILE *F = fopen("file", "r+"); | 
|  | if (!F) | 
|  | return; | 
|  |  | 
|  | char Buf[3] = {10, 10, 10}; | 
|  | fread(Buf, 1, 3, F); | 
|  | // The check applies to success and failure. | 
|  | clang_analyzer_dump(Buf[0]); // expected-warning {{conj_$}} Should not preserve the previous value, thus should not be 10. | 
|  | clang_analyzer_dump(Buf[2]); // expected-warning {{conj_$}} | 
|  | if (feof(F)) { | 
|  | char Buf1[3] = {10, 10, 10}; | 
|  | fread(Buf1, 1, 3, F); // expected-warning {{is in EOF state}} | 
|  | clang_analyzer_dump(Buf1[0]); // expected-warning {{10 S32b}} | 
|  | clang_analyzer_dump(Buf1[2]); // expected-warning {{10 S32b}} | 
|  | } | 
|  |  | 
|  | fclose(F); | 
|  | } | 
|  |  | 
|  | void test_fwrite(void) { | 
|  | FILE *F = fopen("file", "r+"); | 
|  | if (!F) | 
|  | return; | 
|  |  | 
|  | char Buf[3] = {10, 10, 10}; | 
|  | fwrite(Buf, 1, 3, F); | 
|  | // The check applies to success and failure. | 
|  | clang_analyzer_dump(Buf[0]); // expected-warning {{10 S32b}} | 
|  | clang_analyzer_dump(Buf[2]); // expected-warning {{10 S32b}} | 
|  |  | 
|  | fclose(F); | 
|  | } | 
|  |  | 
|  | void test_fgets() { | 
|  | FILE *F = tmpfile(); | 
|  | if (!F) | 
|  | return; | 
|  |  | 
|  | char Buf[3] = {10, 10, 10}; | 
|  | fgets(Buf, 3, F); | 
|  | // The check applies to success and failure. | 
|  | clang_analyzer_dump(Buf[0]); // expected-warning {{conj_$}} Should not preserve the previous value, thus should not be 10. | 
|  | clang_analyzer_dump(Buf[2]); // expected-warning {{conj_$}} | 
|  | if (feof(F)) { | 
|  | char Buf1[3] = {10, 10, 10}; | 
|  | fgets(Buf1, 3, F); // expected-warning {{is in EOF state}} | 
|  | clang_analyzer_dump(Buf1[0]); // expected-warning {{10 S32b}} | 
|  | clang_analyzer_dump(Buf1[2]); // expected-warning {{10 S32b}} | 
|  | } | 
|  |  | 
|  | fclose(F); | 
|  | } | 
|  |  | 
|  | void test_fputs() { | 
|  | FILE *F = tmpfile(); | 
|  | if (!F) | 
|  | return; | 
|  |  | 
|  | char *Buf = "aaa"; | 
|  | fputs(Buf, F); | 
|  | // The check applies to success and failure. | 
|  | clang_analyzer_dump(Buf[0]); // expected-warning {{97 S32b}} | 
|  | clang_analyzer_dump(Buf[2]); // expected-warning {{97 S32b}} | 
|  | clang_analyzer_dump(Buf[3]); // expected-warning {{0 S32b}} | 
|  |  | 
|  | fclose(F); | 
|  | } | 
|  |  | 
|  | void test_fscanf() { | 
|  | FILE *F = tmpfile(); | 
|  | if (!F) | 
|  | return; | 
|  |  | 
|  | int a = 1; | 
|  | unsigned b; | 
|  | int Ret = fscanf(F, "%d %u", &a, &b); | 
|  | if (Ret == 0) { | 
|  | clang_analyzer_dump(a); // expected-warning {{conj_$}} | 
|  | // FIXME: should be {{1 S32b}}. | 
|  | clang_analyzer_dump(b); // expected-warning {{conj_$}} | 
|  | // FIXME: should be {{uninitialized value}}. | 
|  | } else if (Ret == 1) { | 
|  | clang_analyzer_dump(a); // expected-warning {{conj_$}} | 
|  | clang_analyzer_dump(b); // expected-warning {{conj_$}} | 
|  | // FIXME: should be {{uninitialized value}}. | 
|  | } else if (Ret >= 2) { | 
|  | clang_analyzer_dump(a); // expected-warning {{conj_$}} | 
|  | clang_analyzer_dump(b); // expected-warning {{conj_$}} | 
|  | clang_analyzer_eval(Ret == 2); // expected-warning {{FALSE}} expected-warning {{TRUE}} | 
|  | // FIXME: should be only TRUE. | 
|  | } else { | 
|  | clang_analyzer_dump(a); // expected-warning {{1 S32b}} | 
|  | clang_analyzer_dump(b); // expected-warning {{uninitialized value}} | 
|  | } | 
|  |  | 
|  | fclose(F); | 
|  | } | 
|  |  | 
|  | void test_getdelim(char *P, size_t Sz) { | 
|  | FILE *F = tmpfile(); | 
|  | if (!F) | 
|  | return; | 
|  |  | 
|  | char *P1 = P; | 
|  | size_t Sz1 = Sz; | 
|  | ssize_t Ret = getdelim(&P, &Sz, '\t', F); | 
|  | if (Ret < 0) { | 
|  | clang_analyzer_eval(P == P1); // expected-warning {{FALSE}} \ | 
|  | // expected-warning {{TRUE}} | 
|  | clang_analyzer_eval(Sz == Sz1); // expected-warning {{FALSE}} \ | 
|  | // expected-warning {{TRUE}} | 
|  | } else { | 
|  | clang_analyzer_eval(P == P1); // expected-warning {{FALSE}} \ | 
|  | // expected-warning {{TRUE}} | 
|  | clang_analyzer_eval(Sz == Sz1); // expected-warning {{FALSE}} \ | 
|  | // expected-warning {{TRUE}} | 
|  | } | 
|  |  | 
|  | fclose(F); | 
|  | } | 
|  |  | 
|  | void test_fgetpos() { | 
|  | FILE *F = tmpfile(); | 
|  | if (!F) | 
|  | return; | 
|  |  | 
|  | fpos_t Pos = 1; | 
|  | int Ret = fgetpos(F, &Pos); | 
|  | if (Ret == 0) { | 
|  | clang_analyzer_dump(Pos); // expected-warning {{conj_$}} | 
|  | } else { | 
|  | clang_analyzer_dump(Pos); // expected-warning {{1 S32b}} | 
|  | } | 
|  |  | 
|  | fclose(F); | 
|  | } | 
|  |  | 
|  | void test_fprintf() { | 
|  | FILE *F1 = tmpfile(); | 
|  | if (!F1) | 
|  | return; | 
|  |  | 
|  | unsigned a = 42; | 
|  | char *output = "HELLO"; | 
|  | int r = fprintf(F1, "%s\t%u\n", output, a); | 
|  | // fprintf does not invalidate any of its input | 
|  | // 69 is ascii for 'E' | 
|  | clang_analyzer_dump(a); // expected-warning {{42 S32b}} | 
|  | clang_analyzer_dump(output[1]); // expected-warning {{69 S32b}} | 
|  | fclose(F1); | 
|  | } | 
|  |  | 
|  | int test_vfscanf_inner(const char *fmt, ...) { | 
|  | FILE *F1 = tmpfile(); | 
|  | if (!F1) | 
|  | return EOF; | 
|  |  | 
|  | va_list ap; | 
|  | va_start(ap, fmt); | 
|  |  | 
|  | int r = vfscanf(F1, fmt, ap); | 
|  |  | 
|  | fclose(F1); | 
|  | va_end(ap); | 
|  | return r; | 
|  | } | 
|  |  | 
|  | void test_vfscanf() { | 
|  | int i = 42; | 
|  | int j = 43; | 
|  | int r = test_vfscanf_inner("%d", &i); | 
|  | if (r != EOF) { | 
|  | // i gets invalidated by the call to test_vfscanf_inner, not by vfscanf. | 
|  | clang_analyzer_dump(i); // expected-warning {{conj_$}} | 
|  | clang_analyzer_dump(j); // expected-warning {{43 S32b}} | 
|  | } | 
|  | } |