gamesh411 created this revision.
gamesh411 added a reviewer: steakhal.
Herald added subscribers: martong, Szelethus, dkrupp.
Herald added a reviewer: Szelethus.
gamesh411 requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Add more functions as taint sources to GenericTaintChecker.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D120236

Files:
  clang/docs/analyzer/checkers.rst
  clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
  clang/test/Analysis/taint-generic.c

Index: clang/test/Analysis/taint-generic.c
===================================================================
--- clang/test/Analysis/taint-generic.c
+++ clang/test/Analysis/taint-generic.c
@@ -352,6 +352,119 @@
   return 1 / x; // expected-warning {{Division by a tainted value, possibly zero}}
 }
 
+int scanf_s(const char *format, ...);
+int scanf_s_is_source(int *out) {
+  scanf_s("%d", out);
+  return 1 / *out; // expected-warning {{Division by a tainted value, possibly zero}}
+}
+
+int getopt(int argc, char *const argv[], const char *optstring);
+int getopt_is_source(int argc, char **argv) {
+  int opt = getopt(argc, argv, "nt:");
+  return 1 / opt; // expected-warning {{Division by a tainted value, possibly zero}}
+}
+
+struct option {
+  const char *name;
+  int has_arg;
+  int *flag;
+  int val;
+};
+int getopt_long(int argc, char *const argv[], const char *optstring, const struct option *longopts, int *longindex);
+int getopt_long_is_source(int argc, char **argv) {
+  int option_index = 0;
+  struct option long_opts[] = {{0, 0, 0, 0}};
+  int opt = getopt_long(argc, argv, "a:b:02", long_opts, &option_index);
+  return 1 / opt; // expected-warning {{Division by a tainted value, possibly zero}}
+}
+
+int getopt_long_only(int argc, char *const argv[], const char *optstring, const struct option *longopts, int *longindex);
+int getopt_long_only_is_source(int argc, char **argv) {
+  int option_index = 0;
+  struct option long_opts[] = {{0, 0, 0, 0}};
+  int opt = getopt_long_only(argc, argv, "a:b:02", long_opts, &option_index);
+  return 1 / opt; // expected-warning {{Division by a tainted value, possibly zero}}
+}
+
+#define _IO_FILE FILE
+int _IO_getc(_IO_FILE *__fp);
+int underscore_IO_getc_is_source(_IO_FILE *fp) {
+  char c = _IO_getc(fp);
+  return 1 / c; // expected-warning {{Division by a tainted value, possibly zero}}
+}
+
+char *getcwd(char *buf, size_t size);
+int getcwd_is_source(char *buf, size_t size) {
+  char *c = getcwd(buf, size);
+  return system(c); // expected-warning {{Untrusted data is passed to a system call}}
+}
+
+char *getwd(char *buf);
+int getwd_is_source(char *buf) {
+  char *c = getwd(buf);
+  return system(c); // expected-warning {{Untrusted data is passed to a system call}}
+}
+
+typedef signed long long ssize_t;
+ssize_t readlink(const char *path, char *buf, size_t bufsiz);
+int readlink_is_source(char *path, char *buf, size_t bufsiz) {
+  ssize_t s = readlink(path, buf, bufsiz);
+  system(buf);  // expected-warning {{Untrusted data is passed to a system call}}
+  return 1 / s; // expected-warning {{Division by a tainted value, possibly zero}}
+}
+
+char *get_current_dir_name(void);
+int get_current_dir_name_is_source() {
+  char *d = get_current_dir_name();
+  return system(d); // expected-warning {{Untrusted data is passed to a system call}}
+}
+
+int gethostname(char *name, size_t len);
+int gethostname_is_source(char *name, size_t len) {
+  gethostname(name, len);
+  return system(name); // expected-warning {{Untrusted data is passed to a system call}}
+}
+
+struct sockaddr;
+typedef size_t socklen_t;
+int getnameinfo(const struct sockaddr *restrict addr, socklen_t addrlen,
+                       char *restrict host, socklen_t hostlen,
+                       char *restrict serv, socklen_t servlen, int flags);
+int getnameinfo_is_source(const struct sockaddr *restrict addr, socklen_t addrlen,
+                       char *restrict host, socklen_t hostlen,
+                       char *restrict serv, socklen_t servlen, int flags) {
+  getnameinfo(addr, addrlen, host, hostlen, serv, servlen, flags);
+
+  system(host); // expected-warning {{Untrusted data is passed to a system call}}
+  return system(serv); // expected-warning {{Untrusted data is passed to a system call}}
+}
+
+int getseuserbyname(const char *linuxuser, char **selinuxuser, char **level);
+int getseuserbyname_is_source(const char* linuxuser, char **selinuxuser, char**level) {
+  getseuserbyname(linuxuser, selinuxuser, level);
+  system(selinuxuser[0]); // expected-warning {{Untrusted data is passed to a system call}}
+  return system(level[0]);// expected-warning {{Untrusted data is passed to a system call}}
+}
+
+typedef int gid_t;
+int getgroups(int size, gid_t list[]);
+int getgroups_is_source(int size, gid_t list[]) {
+  getgroups(size, list);
+  return 1 / list[0]; // expected-warning {{Division by a tainted value, possibly zero}}
+}
+
+char *getlogin(void);
+int getlogin_is_source() {
+  char* n = getlogin();
+  return system(n); // expected-warning {{Untrusted data is passed to a system call}}
+}
+
+int getlogin_r(char* buf, size_t bufsize);
+int getlogin_r_is_source(char* buf, size_t bufsize) {
+  getlogin_r(buf, bufsize);
+  return system(buf); // expected-warning {{Untrusted data is passed to a system call}}
+}
+
 // Test configuration
 int mySource1(void);
 void mySource2(int*);
Index: clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
+++ clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
@@ -545,7 +545,22 @@
       {{"getchar_unlocked"}, TR::Source({{ReturnValueIndex}})},
       {{"gets"}, TR::Source({{0}, ReturnValueIndex})},
       {{"scanf"}, TR::Source({{}, 1})},
+      {{"scanf_s"}, TR::Source({{}, {1}})},
       {{"wgetch"}, TR::Source({{}, ReturnValueIndex})},
+      {{"getopt"}, TR::Source({{ReturnValueIndex}})},
+      {{"getopt_long"}, TR::Source({{ReturnValueIndex}})},
+      {{"getopt_long_only"}, TR::Source({{ReturnValueIndex}})},
+      {{"_IO_getc"}, TR::Source({{ReturnValueIndex}})},
+      {{"getcwd"}, TR::Source({{0, ReturnValueIndex}})},
+      {{"getwd"}, TR::Source({{0, ReturnValueIndex}})},
+      {{"readlink"}, TR::Source({{1, ReturnValueIndex}})},
+      {{"get_current_dir_name"}, TR::Source({{ReturnValueIndex}})},
+      {{"gethostname"}, TR::Source({{0}})},
+      {{"getnameinfo"}, TR::Source({{2, 4}})},
+      {{"getseuserbyname"}, TR::Source({{1, 2}})},
+      {{"getgroups"}, TR::Source({{1}})},
+      {{"getlogin"}, TR::Source({{ReturnValueIndex}})},
+      {{"getlogin_r"}, TR::Source({{0}})},
 
       // Props
       {{"atoi"}, TR::Prop({{0}}, {{ReturnValueIndex}})},
Index: clang/docs/analyzer/checkers.rst
===================================================================
--- clang/docs/analyzer/checkers.rst
+++ clang/docs/analyzer/checkers.rst
@@ -2355,7 +2355,7 @@
 These operations are handled even if no external taint configuration is provided.
 
 Default sources defined by ``GenericTaintChecker``:
-``fdopen``, ``fopen``, ``freopen``, ``getch``, ``getchar``, ``getchar_unlocked``, ``gets``, ``scanf``, ``socket``, ``wgetch``
+ ``_IO_getc``, ``fdopen``, ``fopen``, ``freopen``, ``get_current_dir_name``, ``getch``, ``getchar``, ``getchar_unlocked``, ``getcw``, ``getcwd``, ``getgroups``, ``gethostname``, ``getlogin``, ``getlogin_r``, ``getnameinfo``, ``getopt``, ``getopt_long``, ``getopt_only``, ``gets``, ``getseuserbyname``, ``readlink``, ``scanf``, ``scanf_s``, ``socket``, ``wgetch``
 
 Default propagations defined by ``GenericTaintChecker``:
 ``atoi``, ``atol``, ``atoll``, ``fgetc``, ``fgetln``, ``fgets``, ``fscanf``, ``sscanf``, ``getc``, ``getc_unlocked``, ``getdelim``, ``getline``, ``getw``, ``pread``, ``read``, ``strchr``, ``strrchr``, ``tolower``, ``toupper``
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to