xref: /llvm-project/clang/test/Analysis/errno-stdlibraryfunctions.c (revision 0851d7b00c651d527a37becc206566580bf3c615)
1 // RUN: %clang_analyze_cc1 -verify %s \
2 // RUN:   -analyzer-checker=core \
3 // RUN:   -analyzer-checker=debug.ExprInspection \
4 // RUN:   -analyzer-checker=unix.StdCLibraryFunctions \
5 // RUN:   -analyzer-checker=apiModeling.Errno \
6 // RUN:   -analyzer-checker=unix.Errno \
7 // RUN:   -analyzer-config unix.StdCLibraryFunctions:ModelPOSIX=true
8 
9 #include "Inputs/errno_var.h"
10 #include "Inputs/std-c-library-functions-POSIX.h"
11 
12 #define NULL ((void *) 0)
13 
14 void clang_analyzer_warnIfReached();
15 void clang_analyzer_eval(int);
16 
unsafe_errno_read(int sock,void * data,int data_size)17 int unsafe_errno_read(int sock, void *data, int data_size) {
18   if (send(sock, data, data_size, 0) != data_size) {
19     if (errno == 1) {
20       // expected-warning@-1{{An undefined value may be read from 'errno'}}
21       return 0;
22     }
23   }
24   return 1;
25 }
26 
errno_lseek(int fildes,off_t offset)27 int errno_lseek(int fildes, off_t offset) {
28   off_t result = lseek(fildes, offset, 0);
29   if (result == (off_t)-1) {
30     // Failure path.
31     // check if the function is modeled
32     clang_analyzer_eval(errno != 0); // expected-warning{{TRUE}}
33     return 2;
34   }
35   if (result != offset) {
36     // Not success path (?)
37     // not sure if this is a valid case, allow to check 'errno'
38     if (errno == 1) { // no warning
39       return 1;
40     }
41     clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
42   }
43   if (result == offset) {
44     // The checker does not differentiate for this case.
45     // In general case no relation exists between the arg 2 and the returned
46     // value, only for SEEK_SET.
47     if (errno == 1) { // no warning
48       return 1;
49     }
50     clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
51   }
52   return 0;
53 }
54 
errno_mkstemp(char * template)55 void errno_mkstemp(char *template) {
56   int FD = mkstemp(template);
57   if (FD >= 0) {
58     if (errno) {}                    // expected-warning{{An undefined value may be read from 'errno'}}
59     close(FD);
60   } else {
61     clang_analyzer_eval(FD == -1);   // expected-warning{{TRUE}}
62     clang_analyzer_eval(errno != 0); // expected-warning{{TRUE}}
63     if (errno) {}                    // no warning
64   }
65 }
66 
errno_mkdtemp(char * template)67 void errno_mkdtemp(char *template) {
68   char *Dir = mkdtemp(template);
69   if (Dir == NULL) {
70     clang_analyzer_eval(errno != 0);      // expected-warning{{TRUE}}
71     if (errno) {}                         // no warning
72   } else {
73     clang_analyzer_eval(Dir == template); // expected-warning{{TRUE}}
74     if (errno) {}                         // expected-warning{{An undefined value may be read from 'errno'}}
75   }
76 }
77 
78 typedef char* CHAR_PTR;
errno_mkdtemp2(CHAR_PTR template)79 void errno_mkdtemp2(CHAR_PTR template) {
80   CHAR_PTR Dir = mkdtemp(template);
81   if (Dir == NULL) {
82     clang_analyzer_eval(errno != 0);      // expected-warning{{TRUE}}
83     if (errno) {}                         // no warning
84   } else {
85     clang_analyzer_eval(Dir == template); // expected-warning{{TRUE}}
86     if (errno) {}                         // expected-warning{{An undefined value may be read from 'errno'}}
87   }
88 }
89 
90 typedef char const* CONST_CHAR_PTR;
errno_mkdtemp3(CHAR_PTR template)91 void errno_mkdtemp3(CHAR_PTR template) {
92   CONST_CHAR_PTR Dir = mkdtemp(template);
93   if (Dir == NULL) {
94     clang_analyzer_eval(errno != 0);      // expected-warning{{TRUE}}
95     if (errno) {}                         // no warning
96   } else {
97     clang_analyzer_eval(Dir == template); // expected-warning{{TRUE}}
98     if (errno) {}                         // expected-warning{{An undefined value may be read from 'errno'}}
99   }
100 }
101 
errno_getcwd(char * Buf,size_t Sz)102 void errno_getcwd(char *Buf, size_t Sz) {
103   char *Path = getcwd(Buf, Sz);
104   if (Sz == 0) {
105     clang_analyzer_eval(errno != 0);   // expected-warning{{TRUE}}
106     clang_analyzer_eval(Path == NULL); // expected-warning{{TRUE}}
107     if (errno) {}                      // no warning
108   } else if (Path == NULL) {
109     clang_analyzer_eval(errno != 0);   // expected-warning{{TRUE}}
110     if (errno) {}                      // no warning
111   } else {
112     clang_analyzer_eval(Path == Buf);  // expected-warning{{TRUE}}
113     if (errno) {}                      // expected-warning{{An undefined value may be read from 'errno'}}
114   }
115 }
116 
errno_execv(char * Path,char * Argv[])117 void errno_execv(char *Path, char * Argv[]) {
118   int Ret = execv(Path, Argv);
119   clang_analyzer_eval(Ret == -1);  // expected-warning{{TRUE}}
120   clang_analyzer_eval(errno != 0); // expected-warning{{TRUE}}
121   if (errno) {}                    // no warning
122 }
123 
errno_execvp(char * File,char * Argv[])124 void errno_execvp(char *File, char * Argv[]) {
125   int Ret = execvp(File, Argv);
126   clang_analyzer_eval(Ret == -1);  // expected-warning{{TRUE}}
127   clang_analyzer_eval(errno != 0); // expected-warning{{TRUE}}
128   if (errno) {}                    // no warning
129 }
130 
errno_popen(void)131 void errno_popen(void) {
132   FILE *F = popen("xxx", "r");
133   if (!F) {
134     clang_analyzer_eval(errno != 0); // expected-warning{{TRUE}}
135     if (errno) {}                    // no-warning
136   } else {
137     if (errno) {} // expected-warning{{An undefined value may be read from 'errno' [unix.Errno]}}
138     pclose(F);
139   }
140 }
141 
errno_pclose(void)142 void errno_pclose(void) {
143   FILE *F = popen("xx", "w");
144   if (!F)
145     return;
146   int Ret = pclose(F);
147   if (Ret == -1) {
148     clang_analyzer_eval(errno != 0); // expected-warning{{TRUE}}
149     if (errno) {}                    // no-warning
150   } else {
151     clang_analyzer_eval(Ret >= 0);   // expected-warning{{TRUE}}
152     if (errno) {} // expected-warning{{An undefined value may be read from 'errno'}}
153   }
154 }
155 
errno_realpath(char * Path,char * Buf)156 void errno_realpath(char *Path, char *Buf) {
157   char *Ret = realpath(Path, Buf);
158   if (!Ret) {
159     clang_analyzer_eval(errno != 0);  // expected-warning{{TRUE}}
160     if (errno) {}                     // no-warning
161   } else {
162     if (errno) {} // expected-warning{{An undefined value may be read from 'errno'}}
163   }
164 }
165