Skip to content

[analyzer] First batch of patches for the Juliet benchmark for taint improvements #66074

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,7 @@ bool isStdin(SVal Val, const ASTContext &ACtx) {
// variable named stdin with the proper type.
if (const auto *D = dyn_cast_or_null<VarDecl>(DeclReg->getDecl())) {
D = D->getCanonicalDecl();
// FIXME: This should look for an exact match.
if (D->getName().contains("stdin") && D->isExternC()) {
if (D->getName() == "stdin" && D->hasExternalStorage() && D->isExternC()) {
const QualType FILETy = ACtx.getFILEType().getCanonicalType();
const QualType Ty = D->getType().getCanonicalType();

Expand Down Expand Up @@ -622,12 +621,14 @@ void GenericTaintChecker::initTaintRules(CheckerContext &C) const {
{{{"getlogin_r"}}, TR::Source({{0}})},

// Props
{{{"accept"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
{{{"atoi"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
{{{"atol"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
{{{"atoll"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
{{{"fgetc"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
{{{"fgetln"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
{{{"fgets"}}, TR::Prop({{2}}, {{0, ReturnValueIndex}})},
{{{"fgetws"}}, TR::Prop({{2}}, {{0, ReturnValueIndex}})},
{{{"fscanf"}}, TR::Prop({{0}}, {{}, 2})},
{{{"fscanf_s"}}, TR::Prop({{0}}, {{}, {2}})},
{{{"sscanf"}}, TR::Prop({{0}}, {{}, 2})},
Expand Down Expand Up @@ -695,6 +696,7 @@ void GenericTaintChecker::initTaintRules(CheckerContext &C) const {
{{{"strndup"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
{{{"strndupa"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
{{{"strlen"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
{{{"wcslen"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
{{{"strnlen"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
{{{"strtol"}}, TR::Prop({{0}}, {{1, ReturnValueIndex}})},
{{{"strtoll"}}, TR::Prop({{0}}, {{1, ReturnValueIndex}})},
Expand Down Expand Up @@ -731,6 +733,8 @@ void GenericTaintChecker::initTaintRules(CheckerContext &C) const {
TR::Prop({{1}}, {{0, ReturnValueIndex}})},
{{CDF_MaybeBuiltin, {{"strcat"}}},
TR::Prop({{1}}, {{0, ReturnValueIndex}})},
{{CDF_MaybeBuiltin, {{"wcsncat"}}},
TR::Prop({{1}}, {{0, ReturnValueIndex}})},
{{CDF_MaybeBuiltin, {{"strdup"}}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
{{CDF_MaybeBuiltin, {{"strdupa"}}},
TR::Prop({{0}}, {{ReturnValueIndex}})},
Expand Down
2 changes: 1 addition & 1 deletion clang/test/Analysis/taint-diagnostic-visitor.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ size_t strlen( const char* str );
void *malloc(size_t size );
void free( void *ptr );
char *fgets(char *str, int n, FILE *stream);
FILE *stdin;
extern FILE *stdin;

void taintDiagnostic(void)
{
Expand Down
50 changes: 45 additions & 5 deletions clang/test/Analysis/taint-generic.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,10 @@
// CHECK-INVALID-ARG-SAME: rules greater or equal to -1

typedef long long rsize_t;
typedef typeof(sizeof(int)) size_t;
typedef __WCHAR_TYPE__ wchar_t;
void clang_analyzer_isTainted_char(char);
void clang_analyzer_isTainted_wchar(wchar_t);
void clang_analyzer_isTainted_charp(char*);
void clang_analyzer_isTainted_int(int);

Expand All @@ -75,6 +78,17 @@ extern FILE *stdin;
#define bool _Bool
#define NULL (void*)0

wchar_t *fgetws(wchar_t *ws, int n, FILE *stream);
wchar_t *wmemset(wchar_t *wcs, wchar_t wc, unsigned long n);
wchar_t *wmemcpy(wchar_t *dest, const wchar_t *src, size_t n);
wchar_t *wmemmove(wchar_t *dest, const wchar_t *src, size_t n);
size_t wcslen(const wchar_t *s);
wchar_t *wcscpy(wchar_t * dest, const wchar_t * src);
wchar_t *wcsncpy(wchar_t *dest, const wchar_t *src, size_t n);
wchar_t *wcscat(wchar_t *dest, const wchar_t *src);
wchar_t *wcsncat(wchar_t *dest,const wchar_t *src, size_t n);
int swprintf(wchar_t *wcs, size_t maxlen, const wchar_t *format, ...);

char *getenv(const char *name);

FILE *fopen(const char *name, const char *mode);
Expand Down Expand Up @@ -430,6 +444,24 @@ int testSprintf_propagates_taint(char *buf, char *msg) {
return 1 / x; // expected-warning {{Division by a tainted value, possibly zero}}
}

void test_wchar_apis_propagate(const char *path) {
FILE *f = fopen(path, "r");
clang_analyzer_isTainted_charp((char*)f); // expected-warning {{YES}}
wchar_t wbuf[10];
fgetws(wbuf, sizeof(wbuf)/sizeof(*wbuf), f);
clang_analyzer_isTainted_wchar(*wbuf); // expected-warning {{YES}}
int n = wcslen(wbuf);
clang_analyzer_isTainted_int(n); // expected-warning {{YES}}

wchar_t dst[100] = L"ABC";
clang_analyzer_isTainted_wchar(*dst); // expected-warning {{NO}}
wcsncat(dst, wbuf, sizeof(wbuf)/sizeof(*wbuf));
clang_analyzer_isTainted_wchar(*dst); // expected-warning {{YES}}

int m = wcslen(dst);
clang_analyzer_isTainted_int(m); // expected-warning {{YES}}
}

int scanf_s(const char *format, ...);
int testScanf_s_(int *out) {
scanf_s("%d", out);
Expand Down Expand Up @@ -544,6 +576,10 @@ void testFread(const char *fname, int *buffer, size_t size, size_t count) {
}

ssize_t recv(int sockfd, void *buf, size_t len, int flags);
int accept(int fd, struct sockaddr *addr, socklen_t *addrlen);
int bind(int fd, const struct sockaddr *addr, socklen_t addrlen);
int listen(int fd, int backlog);

void testRecv(int *buf, size_t len, int flags) {
int fd;
scanf("%d", &fd); // fake a tainted a file descriptor
Expand Down Expand Up @@ -640,7 +676,6 @@ void testRawmemchr(int c) {
clang_analyzer_isTainted_charp(result); // expected-warning {{YES}}
}

typedef char wchar_t;
int mbtowc(wchar_t *pwc, const char *s, size_t n);
void testMbtowc(wchar_t *pwc, size_t n) {
char buf[10];
Expand All @@ -653,8 +688,7 @@ void testMbtowc(wchar_t *pwc, size_t n) {

int wctomb(char *s, wchar_t wc);
void testWctomb(char *buf) {
wchar_t wc;
scanf("%c", &wc);
wchar_t wc = getchar();

int result = wctomb(buf, wc);
clang_analyzer_isTainted_char(*buf); // expected-warning {{YES}}
Expand All @@ -663,8 +697,7 @@ void testWctomb(char *buf) {

int wcwidth(wchar_t c);
void testWcwidth() {
wchar_t wc;
scanf("%c", &wc);
wchar_t wc = getchar();

int width = wcwidth(wc);
clang_analyzer_isTainted_int(width); // expected-warning {{YES}}
Expand Down Expand Up @@ -1107,3 +1140,10 @@ void testProctitle2(char *real_argv[]) {
setproctitle_init(1, argv, 0); // expected-warning {{Untrusted data is passed to a user-defined sink}}
setproctitle_init(1, real_argv, argv); // expected-warning {{Untrusted data is passed to a user-defined sink}}
}

void testAcceptPropagates() {
int listenSocket = socket(2, 1, 6);
clang_analyzer_isTainted_int(listenSocket); // expected-warning {{YES}}
int acceptSocket = accept(listenSocket, 0, 0);
clang_analyzer_isTainted_int(acceptSocket); // expected-warning {{YES}}
}
12 changes: 12 additions & 0 deletions clang/test/Analysis/taint-generic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ int scanf(const char*, ...);
int mySource1();
int mySource3();

typedef struct _FILE FILE;
extern "C" {
extern FILE *stdin;
}
int fscanf(FILE *stream, const char *format, ...);

bool isOutOfRange2(const int*);

void mySink2(int);
Expand Down Expand Up @@ -124,3 +130,9 @@ void testConfigurationMemberFunc() {
foo.myMemberScanf("%d", &x);
Buffer[x] = 1; // expected-warning {{Out of bound memory access }}
}

void testReadingFromStdin(char **p) {
int n;
fscanf(stdin, "%d", &n);
Buffer[n] = 1; // expected-warning {{Out of bound memory access (index is tainted)}}
}