// 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}}
}
}