1 // RUN: %clang_analyze_cc1 -triple hexagon-unknown-linux -analyzer-checker=core,valist.Uninitialized,valist.CopyToSelf -analyzer-disable-checker=core.CallAndMessage -analyzer-output=text -analyzer-store=region -verify %s
2 // RUN: %clang_analyze_cc1 -triple x86_64-pc-linux-gnu -analyzer-checker=core,valist.Uninitialized,valist.CopyToSelf -analyzer-disable-checker=core.CallAndMessage -analyzer-output=text -analyzer-store=region -verify %s
3 
4 #include "Inputs/system-header-simulator-for-valist.h"
5 
6 void f1(int fst, ...) {
7   va_list va;
8   (void)va_arg(va, int); // expected-warning{{va_arg() is called on an uninitialized va_list}}
9   // expected-note@-1{{va_arg() is called on an uninitialized va_list}}
10 }
11 
12 int f2(int fst, ...) {
13   va_list va;
14   va_start(va, fst); // expected-note{{Initialized va_list}}
15   va_end(va); // expected-note{{Ended va_list}}
16   return va_arg(va, int); // expected-warning{{va_arg() is called on an uninitialized va_list}}
17   // expected-note@-1{{va_arg() is called on an uninitialized va_list}}
18 }
19 
20 void f3(int fst, ...) {
21   va_list va, va2;
22   va_start(va, fst);
23   va_copy(va2, va);
24   va_end(va);
25   (void)va_arg(va2, int);
26   va_end(va2);
27 } //no-warning
28 
29 void f4(int cond, ...) {
30   va_list va;
31   if (cond) { // expected-note{{Assuming 'cond' is 0}}
32     // expected-note@-1{{Taking false branch}}
33     va_start(va, cond);
34     (void)va_arg(va,int);
35   }
36   va_end(va); //expected-warning{{va_end() is called on an uninitialized va_list}}
37   // expected-note@-1{{va_end() is called on an uninitialized va_list}}
38 }
39 
40 void f5(va_list fst, ...) {
41   va_start(fst, fst);
42   (void)va_arg(fst, int);
43   va_end(fst);
44 } // no-warning
45 
46 void f7(int *fst, ...) {
47   va_list x;
48   va_list *y = &x;
49   va_start(*y,fst);
50   (void)va_arg(x, int);
51   va_end(x);
52 } // no-warning
53 
54 void f8(int *fst, ...) {
55   va_list x;
56   va_list *y = &x;
57   va_start(*y,fst); // expected-note{{Initialized va_list}}
58   va_end(x); // expected-note{{Ended va_list}}
59   (void)va_arg(*y, int); //expected-warning{{va_arg() is called on an uninitialized va_list}}
60   // expected-note@-1{{va_arg() is called on an uninitialized va_list}}
61 }
62 
63 // This only contains problems which are handled by varargs.Unterminated.
64 void reinit(int *fst, ...) {
65   va_list va;
66   va_start(va, fst);
67   va_start(va, fst);
68   (void)va_arg(va, int);
69 } // no-warning
70 
71 void reinitOk(int *fst, ...) {
72   va_list va;
73   va_start(va, fst);
74   (void)va_arg(va, int);
75   va_end(va);
76   va_start(va, fst);
77   (void)va_arg(va, int);
78   va_end(va);
79 } // no-warning
80 
81 void reinit3(int *fst, ...) {
82   va_list va;
83   va_start(va, fst); // expected-note{{Initialized va_list}}
84   (void)va_arg(va, int);
85   va_end(va); // expected-note{{Ended va_list}}
86   va_start(va, fst); // expected-note{{Initialized va_list}}
87   (void)va_arg(va, int);
88   va_end(va); // expected-note{{Ended va_list}}
89   (void)va_arg(va, int); //expected-warning{{va_arg() is called on an uninitialized va_list}}
90   // expected-note@-1{{va_arg() is called on an uninitialized va_list}}
91 }
92 
93 void copyself(int fst, ...) {
94   va_list va;
95   va_start(va, fst); // expected-note{{Initialized va_list}}
96   va_copy(va, va); // expected-warning{{va_list 'va' is copied onto itself}}
97   // expected-note@-1{{va_list 'va' is copied onto itself}}
98   va_end(va);
99 }
100 
101 void copyselfUninit(int fst, ...) {
102   va_list va;
103   va_copy(va, va); // expected-warning{{va_list 'va' is copied onto itself}}
104   // expected-note@-1{{va_list 'va' is copied onto itself}}
105 }
106 
107 void copyOverwrite(int fst, ...) {
108   va_list va, va2;
109   va_start(va, fst); // expected-note{{Initialized va_list}}
110   va_copy(va, va2); // expected-warning{{Initialized va_list 'va' is overwritten by an uninitialized one}}
111   // expected-note@-1{{Initialized va_list 'va' is overwritten by an uninitialized one}}
112 }
113 
114 void copyUnint(int fst, ...) {
115   va_list va, va2;
116   va_copy(va, va2); // expected-warning{{Uninitialized va_list is copied}}
117   // expected-note@-1{{Uninitialized va_list is copied}}
118 }
119 
120 void g1(int fst, ...) {
121   va_list va;
122   va_end(va); // expected-warning{{va_end() is called on an uninitialized va_list}}
123   // expected-note@-1{{va_end() is called on an uninitialized va_list}}
124 }
125 
126 void g2(int fst, ...) {
127   va_list va;
128   va_start(va, fst); // expected-note{{Initialized va_list}}
129   va_end(va); // expected-note{{Ended va_list}}
130   va_end(va); // expected-warning{{va_end() is called on an uninitialized va_list}}
131   // expected-note@-1{{va_end() is called on an uninitialized va_list}}
132 }
133 
134 void is_sink(int fst, ...) {
135   va_list va;
136   va_end(va); // expected-warning{{va_end() is called on an uninitialized va_list}}
137   // expected-note@-1{{va_end() is called on an uninitialized va_list}}
138   *((volatile int *)0) = 1;
139 }
140 
141 // NOTE: this is invalid, as the man page of va_end requires that "Each invocation of va_start()
142 // must be matched by a corresponding  invocation of va_end() in the same function."
143 void ends_arg(va_list arg) {
144   va_end(arg);
145 } //no-warning
146 
147 void uses_arg(va_list arg) {
148   (void)va_arg(arg, int);
149 } //no-warning
150 
151 void call_vprintf_ok(int isstring, ...) {
152   va_list va;
153   va_start(va, isstring);
154   vprintf(isstring ? "%s" : "%d", va);
155   va_end(va);
156 } //no-warning
157 
158 void call_some_other_func(int n, ...) {
159   va_list va;
160   some_library_function(n, va);
161 } //no-warning
162 
163 void inlined_uses_arg_good(va_list arg) {
164   (void)va_arg(arg, int);
165 }
166 
167 void call_inlined_uses_arg_good(int fst, ...) {
168   va_list va;
169   va_start(va, fst);
170   inlined_uses_arg_good(va);
171   va_end(va);
172 }
173 
174 void va_copy_test(va_list arg) {
175   va_list dst;
176   va_copy(dst, arg);
177   va_end(dst);
178 }
179