// RUN: %clang_analyze_cc1 \
// RUN: -analyzer-checker=alpha.security.cert.env.InvalidPtr\
// RUN: -analyzer-output=text -verify -Wno-unused %s
#include "../Inputs/system-header-simulator.h"
char *getenv(const char *name);
char *setlocale(int category, const char *locale);
char *strerror(int errnum);
typedef struct {
char * field;
} lconv;
lconv *localeconv(void);
typedef struct {
} tm;
char *asctime(const tm *timeptr);
int strcmp(const char*, const char*);
extern void foo(char *e);
extern char* bar(void);
void getenv_test1(void) {
char *p;
p = getenv("VAR");
*p; // no-warning
p = getenv("VAR2");
*p; // no-warning, getenv result was assigned to the same pointer
}
void getenv_test2(void) {
char *p, *p2;
p = getenv("VAR");
// expected-note@-1{{previous function call was here}}
*p; // no-warning
p2 = getenv("VAR2");
// expected-note@-1{{'getenv' call may invalidate the result of the previous 'getenv'}}
*p;
// expected-warning@-1{{dereferencing an invalid pointer}}
// expected-note@-2{{dereferencing an invalid pointer}}
}
void getenv_test3(void) {
char *p, *p2, *p3;
p = getenv("VAR");
*p; // no-warning
p = getenv("VAR2");
// expected-note@-1{{previous function call was here}}
p2 = getenv("VAR2");
// expected-note@-1{{'getenv' call may invalidate the result of the previous 'getenv'}}
p3 = getenv("VAR3");
*p;
// expected-warning@-1{{dereferencing an invalid pointer}}
// expected-note@-2{{dereferencing an invalid pointer}}
}
void getenv_test4(void) {
char *p, *p2, *p3;
p = getenv("VAR");
// expected-note@-1{{previous function call was here}}
p2 = getenv("VAR2");
// expected-note@-1{{'getenv' call may invalidate the result of the previous 'getenv'}}
p3 = getenv("VAR3");
*p;
// expected-warning@-1{{dereferencing an invalid pointer}}
// expected-note@-2{{dereferencing an invalid pointer}}
}
void getenv_test5(void) {
char *p, *p2, *p3;
p = getenv("VAR");
p2 = getenv("VAR2");
// expected-note@-1{{previous function call was here}}
p3 = getenv("VAR3");
// expected-note@-1{{'getenv' call may invalidate the result of the previous 'getenv'}}
*p2;
// expected-warning@-1{{dereferencing an invalid pointer}}
// expected-note@-2{{dereferencing an invalid pointer}}
}
void getenv_test6(void) {
char *p, *p2;
p = getenv("VAR");
*p; // no-warning
p = getenv("VAR2");
// expected-note@-1{{previous function call was here}}
*p; // no-warning
p2 = getenv("VAR3");
// expected-note@-1{{previous function call was here}}
// expected-note@-2{{'getenv' call may invalidate the result of the previous 'getenv'}}
*p;
// expected-warning@-1{{dereferencing an invalid pointer}}
// expected-note@-2{{dereferencing an invalid pointer}}
*p2; // no-warning
p = getenv("VAR4");
// expected-note@-1{{'getenv' call may invalidate the result of the previous 'getenv'}}
*p; // no-warning
*p2;
// expected-warning@-1{{dereferencing an invalid pointer}}
// expected-note@-2{{dereferencing an invalid pointer}}
}
void getenv_test7(void) {
char *p, *p2;
p = getenv("VAR");
// expected-note@-1{{previous function call was here}}
*p; // no-warning
p2 = getenv("VAR2");
// expected-note@-1{{'getenv' call may invalidate the result of the previous 'getenv'}}
foo(p);
// expected-warning@-1{{use of invalidated pointer 'p' in a function call}}
// expected-note@-2{{use of invalidated pointer 'p' in a function call}}
}
void getenv_test8(void) {
static const char *array[] = {
0,
0,
"/var/tmp",
"/usr/tmp",
"/tmp",
"."
};
if( !array[0] )
// expected-note@-1{{Taking true branch}}
array[0] = getenv("TEMPDIR");
// expected-note@-1{{previous function call was here}}
if( !array[1] )
// expected-note@-1{{Taking true branch}}
array[1] = getenv("TMPDIR");
// expected-note@-1{{'getenv' call may invalidate the result of the previous 'getenv'}}
*array[0];
// expected-warning@-1{{dereferencing an invalid pointer}}
// expected-note@-2{{dereferencing an invalid pointer}}
}
void getenv_test9(void) {
char *p, *p2;
p = getenv("something");
p = bar();
p2 = getenv("something");
*p; // no-warning: p does not point to getenv anymore
}
void getenv_test10(void) {
strcmp(getenv("VAR1"), getenv("VAR2"));
// expected-note@-1{{'getenv' call may invalidate the result of the previous 'getenv'}}
// expected-note@-2{{previous function call was here}}
// expected-warning@-3{{use of invalidated pointer 'getenv("VAR1")' in a function call}}
// expected-note@-4{{use of invalidated pointer 'getenv("VAR1")' in a function call}}
}
void dereference_pointer(char* a) {
*a;
// expected-warning@-1{{dereferencing an invalid pointer}}
// expected-note@-2{{dereferencing an invalid pointer}}
}
void getenv_test11(void) {
char *p = getenv("VAR");
// expected-note@-1{{previous function call was here}}
char *pp = getenv("VAR2");
// expected-note@-1{{'getenv' call may invalidate the result of the previous 'getenv'}}
dereference_pointer(p);
// expected-note@-1{{Calling 'dereference_pointer'}}
}
void getenv_test12(int flag1, int flag2) {
char *p = getenv("VAR");
// expected-note@-1{{previous function call was here}}
if (flag1) {
// expected-note@-1{{Assuming 'flag1' is not equal to 0}}
// expected-note@-2{{Taking true branch}}
char *pp = getenv("VAR2");
// expected-note@-1{{'getenv' call may invalidate the result of the previous 'getenv'}}
}
if (flag2) {
// expected-note@-1{{Assuming 'flag2' is not equal to 0}}
// expected-note@-2{{Taking true branch}}
*p;
// expected-warning@-1{{dereferencing an invalid pointer}}
// expected-note@-2{{dereferencing an invalid pointer}}
}
}
void setlocale_test1(void) {
char *p, *p2;
p = setlocale(0, "VAR");
*p; // no-warning
p = setlocale(0, "VAR2");
// expected-note@-1{{previous function call was here}}
*p; // no-warning
p2 = setlocale(0, "VAR3");
// expected-note@-1{{'setlocale' call may invalidate the result of the previous 'setlocale'}}
*p;
// expected-warning@-1{{dereferencing an invalid pointer}}
// expected-note@-2{{dereferencing an invalid pointer}}
}
void setlocale_test2(int flag) {
char *p, *p2;
p = setlocale(0, "VAR");
*p; // no-warning
p = setlocale(0, "VAR2");
// expected-note@-1{{previous function call was here}}
*p; // no-warning
if (flag) {
// expected-note@-1{{Assuming 'flag' is not equal to 0}}
// expected-note@-2{{Taking true branch}}
p2 = setlocale(0, "VAR3");
// expected-note@-1{{'setlocale' call may invalidate the result of the previous 'setlocale'}}
}
*p;
// expected-warning@-1{{dereferencing an invalid pointer}}
// expected-note@-2{{dereferencing an invalid pointer}}
}
void strerror_test1(void) {
char *p, *p2;
p = strerror(0);
*p; // no-warning
p = strerror(1);
// expected-note@-1{{previous function call was here}}
*p; // no-warning
p2 = strerror(2);
// expected-note@-1{{'strerror' call may invalidate the result of the previous 'strerror'}}
*p;
// expected-warning@-1{{dereferencing an invalid pointer}}
// expected-note@-2{{dereferencing an invalid pointer}}
}
void strerror_test2(int errno) {
char *p, *p2;
p = strerror(0);
*p; // no-warning
p = strerror(1);
// expected-note@-1{{previous function call was here}}
*p; // no-warning
if (0 == 1) {
// expected-note@-1{{0 is not equal to 1}}
// expected-note@-2{{Taking false branch}}
p2 = strerror(2);
}
*p; // no-warning
if (errno) {
// expected-note@-1{{Assuming 'errno' is not equal to 0}}
// expected-note@-2{{Taking true branch}}
p2 = strerror(errno);
// expected-note@-1{{'strerror' call may invalidate the result of the previous 'strerror'}}
}
*p;
// expected-warning@-1{{dereferencing an invalid pointer}}
// expected-note@-2{{dereferencing an invalid pointer}}
}
void asctime_test(void) {
const tm *t;
const tm *tt;
char* p = asctime(t);
// expected-note@-1{{previous function call was here}}
char* pp = asctime(tt);
// expected-note@-1{{'asctime' call may invalidate the result of the previous 'asctime'}}
*p;
// expected-warning@-1{{dereferencing an invalid pointer}}
// expected-note@-2{{dereferencing an invalid pointer}}
}
void localeconv_test1(void) {
lconv *lc1 = localeconv();
// expected-note@-1{{previous function call was here}}
lconv *lc2 = localeconv();
// expected-note@-1{{'localeconv' call may invalidate the result of the previous 'localeconv'}}
*lc1;
// expected-warning@-1{{dereferencing an invalid pointer}}
// expected-note@-2{{dereferencing an invalid pointer}}
}
void localeconv_test2(void) {
// TODO: false negative
lconv *lc1 = localeconv();
lconv *lc2 = localeconv();
lc1->field;
}