Home | History | Annotate | Download | only in Analysis
      1 // RUN: %clang_cc1 -Wno-int-to-pointer-cast -analyze -analyzer-checker=alpha.security.taint,debug.TaintTest %s -verify
      2 
      3 #include <stdarg.h>
      4 
      5 int scanf(const char *restrict format, ...);
      6 int getchar(void);
      7 typedef __typeof(sizeof(int)) size_t;
      8 
      9 #define BUFSIZE 10
     10 int Buffer[BUFSIZE];
     11 
     12 struct XYStruct {
     13   int x;
     14   int y;
     15   char z;
     16 };
     17 
     18 void taintTracking(int x) {
     19   int n;
     20   int *addr = &Buffer[0];
     21   scanf("%d", &n);
     22   addr += n;// expected-warning + {{tainted}}
     23   *addr = n; // expected-warning + {{tainted}}
     24 
     25   double tdiv = n / 30; // expected-warning+ {{tainted}}
     26   char *loc_cast = (char *) n; // expected-warning +{{tainted}}
     27   char tinc = tdiv++; // expected-warning + {{tainted}}
     28   int tincdec = (char)tinc--; // expected-warning+{{tainted}}
     29 
     30   // Tainted ptr arithmetic/array element address.
     31   int tprtarithmetic1 = *(addr+1); // expected-warning + {{tainted}}
     32 
     33   // Dereference.
     34   int *ptr;
     35   scanf("%p", &ptr);
     36   int ptrDeref = *ptr; // expected-warning + {{tainted}}
     37   int _ptrDeref = ptrDeref + 13; // expected-warning + {{tainted}}
     38 
     39   // Pointer arithmetic + dereferencing.
     40   // FIXME: We fail to propagate the taint here because RegionStore does not
     41   // handle ElementRegions with symbolic indexes.
     42   int addrDeref = *addr; // expected-warning + {{tainted}}
     43   int _addrDeref = addrDeref; // expected-warning + {{tainted}}
     44 
     45   // Tainted struct address, casts.
     46   struct XYStruct *xyPtr = 0;
     47   scanf("%p", &xyPtr);
     48   void *tXYStructPtr = xyPtr; // expected-warning + {{tainted}}
     49   struct XYStruct *xyPtrCopy = tXYStructPtr; // expected-warning + {{tainted}}
     50   int ptrtx = xyPtr->x;// expected-warning + {{tainted}}
     51   int ptrty = xyPtr->y;// expected-warning + {{tainted}}
     52 
     53   // Taint on fields of a struct.
     54   struct XYStruct xy = {2, 3, 11};
     55   scanf("%d", &xy.y);
     56   scanf("%d", &xy.x);
     57   int tx = xy.x; // expected-warning + {{tainted}}
     58   int ty = xy.y; // FIXME: This should be tainted as well.
     59   char ntz = xy.z;// no warning
     60   // Now, scanf scans both.
     61   scanf("%d %d", &xy.y, &xy.x);
     62   int ttx = xy.x; // expected-warning + {{tainted}}
     63   int tty = xy.y; // expected-warning + {{tainted}}
     64 }
     65 
     66 void BitwiseOp(int in, char inn) {
     67   // Taint on bitwise operations, integer to integer cast.
     68   int m;
     69   int x = 0;
     70   scanf("%d", &x);
     71   int y = (in << (x << in)) * 5;// expected-warning + {{tainted}}
     72   // The next line tests integer to integer cast.
     73   int z = y & inn; // expected-warning + {{tainted}}
     74   if (y == 5) // expected-warning + {{tainted}}
     75     m = z | z;// expected-warning + {{tainted}}
     76   else
     77     m = inn;
     78   int mm = m; // expected-warning + {{tainted}}
     79 }
     80 
     81 // Test getenv.
     82 char *getenv(const char *name);
     83 void getenvTest(char *home) {
     84   home = getenv("HOME"); // expected-warning + {{tainted}}
     85   if (home != 0) { // expected-warning + {{tainted}}
     86       char d = home[0]; // expected-warning + {{tainted}}
     87     }
     88 }
     89 
     90 typedef struct _FILE FILE;
     91 extern FILE *stdin;
     92 extern FILE *stdout;
     93 extern FILE *stderr;
     94 int fscanf(FILE *restrict stream, const char *restrict format, ...);
     95 int fprintf(FILE *stream, const char *format, ...);
     96 int fclose(FILE *stream);
     97 FILE *fopen(const char *path, const char *mode);
     98 
     99 int fscanfTest(void) {
    100   FILE *fp;
    101   char s[80];
    102   int t;
    103 
    104   // Check if stdin is treated as tainted.
    105   fscanf(stdin, "%s %d", s, &t);
    106   // Note, here, s is not tainted, but the data s points to is tainted.
    107   char *ts = s;
    108   char tss = s[0]; // expected-warning + {{tainted}}
    109   int tt = t; // expected-warning + {{tainted}}
    110   if((fp=fopen("test", "w")) == 0) // expected-warning + {{tainted}}
    111     return 1;
    112   fprintf(fp, "%s %d", s, t); // expected-warning + {{tainted}}
    113   fclose(fp); // expected-warning + {{tainted}}
    114 
    115   // Test fscanf and fopen.
    116   if((fp=fopen("test","r")) == 0) // expected-warning + {{tainted}}
    117     return 1;
    118   fscanf(fp, "%s%d", s, &t); // expected-warning + {{tainted}}
    119   fprintf(stdout, "%s %d", s, t); // expected-warning + {{tainted}}
    120   return 0;
    121 }
    122 
    123 // Check if we propagate taint from stdin when it's used in an assignment.
    124 void stdinTest1() {
    125   int i;
    126   fscanf(stdin, "%d", &i);
    127   int j = i; // expected-warning + {{tainted}}
    128 }
    129 void stdinTest2(FILE *pIn) {
    130   FILE *p = stdin;
    131   FILE *pp = p;
    132   int ii;
    133 
    134   fscanf(pp, "%d", &ii);
    135   int jj = ii;// expected-warning + {{tainted}}
    136 
    137   fscanf(p, "%d", &ii);
    138   int jj2 = ii;// expected-warning + {{tainted}}
    139 
    140   ii = 3;
    141   int jj3 = ii;// no warning
    142 
    143   p = pIn;
    144   fscanf(p, "%d", &ii);
    145   int jj4 = ii;// no warning
    146 }
    147 
    148 void stdinTest3() {
    149   FILE **ppp = &stdin;
    150   int iii;
    151   fscanf(*ppp, "%d", &iii);
    152   int jjj = iii;// expected-warning + {{tainted}}
    153 }
    154 
    155 // Test that stdin does not get invalidated by calls.
    156 void foo();
    157 void stdinTest4() {
    158   int i;
    159   fscanf(stdin, "%d", &i);
    160   foo();
    161   int j = i; // expected-warning + {{tainted}}
    162 }
    163 
    164 int getw(FILE *);
    165 void getwTest() {
    166   int i = getw(stdin); // expected-warning + {{tainted}}
    167 }
    168 
    169 typedef long ssize_t;
    170 ssize_t getline(char ** __restrict, size_t * __restrict, FILE * __restrict);
    171 int  printf(const char * __restrict, ...);
    172 void free(void *ptr);
    173 void getlineTest(void) {
    174   FILE *fp;
    175   char *line = 0;
    176   size_t len = 0;
    177   ssize_t read;
    178   while ((read = getline(&line, &len, stdin)) != -1) {
    179     printf("%s", line); // expected-warning + {{tainted}}
    180   }
    181   free(line); // expected-warning + {{tainted}}
    182 }
    183 
    184 // Test propagation functions - the ones that propagate taint from arguments to
    185 // return value, ptr arguments.
    186 
    187 int atoi(const char *nptr);
    188 long atol(const char *nptr);
    189 long long atoll(const char *nptr);
    190 
    191 void atoiTest() {
    192   char s[80];
    193   scanf("%s", s);
    194   int d = atoi(s); // expected-warning + {{tainted}}
    195   int td = d; // expected-warning + {{tainted}}
    196 
    197   long l = atol(s); // expected-warning + {{tainted}}
    198   int tl = l; // expected-warning + {{tainted}}
    199 
    200   long long ll = atoll(s); // expected-warning + {{tainted}}
    201   int tll = ll; // expected-warning + {{tainted}}
    202 
    203 }
    204 
    205