summaryrefslogtreecommitdiffstats
path: root/test/Analysis/valist-uninitialized.c
blob: 19308537e02cd040fb43959296ca8d4cea03b09f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
// 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
// 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

#include "Inputs/system-header-simulator-for-valist.h"

void f1(int fst, ...) {
  va_list va;
  (void)va_arg(va, int); // expected-warning{{va_arg() is called on an uninitialized va_list}}
  // expected-note@-1{{va_arg() is called on an uninitialized va_list}}
}

int f2(int fst, ...) {
  va_list va;
  va_start(va, fst); // expected-note{{Initialized va_list}}
  va_end(va); // expected-note{{Ended va_list}}
  return va_arg(va, int); // expected-warning{{va_arg() is called on an uninitialized va_list}}
  // expected-note@-1{{va_arg() is called on an uninitialized va_list}}
}

void f3(int fst, ...) {
  va_list va, va2;
  va_start(va, fst);
  va_copy(va2, va);
  va_end(va);
  (void)va_arg(va2, int);
  va_end(va2);
} //no-warning

void f4(int cond, ...) {
  va_list va;
  if (cond) { // expected-note{{Assuming 'cond' is 0}}
    // expected-note@-1{{Taking false branch}}
    va_start(va, cond);
    (void)va_arg(va,int);
  }
  va_end(va); //expected-warning{{va_end() is called on an uninitialized va_list}}
  // expected-note@-1{{va_end() is called on an uninitialized va_list}}
}

void f5(va_list fst, ...) {
  va_start(fst, fst);
  (void)va_arg(fst, int);
  va_end(fst);
} // no-warning

void f7(int *fst, ...) {
  va_list x;
  va_list *y = &x;
  va_start(*y,fst);
  (void)va_arg(x, int);
  va_end(x);
} // no-warning

void f8(int *fst, ...) {
  va_list x;
  va_list *y = &x;
  va_start(*y,fst); // expected-note{{Initialized va_list}}
  va_end(x); // expected-note{{Ended va_list}}
  (void)va_arg(*y, int); //expected-warning{{va_arg() is called on an uninitialized va_list}}
  // expected-note@-1{{va_arg() is called on an uninitialized va_list}}
}

// This only contains problems which are handled by varargs.Unterminated.
void reinit(int *fst, ...) {
  va_list va;
  va_start(va, fst);
  va_start(va, fst);
  (void)va_arg(va, int);
} // no-warning

void reinitOk(int *fst, ...) {
  va_list va;
  va_start(va, fst);
  (void)va_arg(va, int);
  va_end(va);
  va_start(va, fst);
  (void)va_arg(va, int);
  va_end(va);
} // no-warning

void reinit3(int *fst, ...) {
  va_list va;
  va_start(va, fst); // expected-note{{Initialized va_list}}
  (void)va_arg(va, int);
  va_end(va); // expected-note{{Ended va_list}}
  va_start(va, fst); // expected-note{{Initialized va_list}}
  (void)va_arg(va, int);
  va_end(va); // expected-note{{Ended va_list}}
  (void)va_arg(va, int); //expected-warning{{va_arg() is called on an uninitialized va_list}}
  // expected-note@-1{{va_arg() is called on an uninitialized va_list}}
}

void copyself(int fst, ...) {
  va_list va;
  va_start(va, fst); // expected-note{{Initialized va_list}}
  va_copy(va, va); // expected-warning{{va_list 'va' is copied onto itself}}
  // expected-note@-1{{va_list 'va' is copied onto itself}}
  va_end(va);
}

void copyselfUninit(int fst, ...) {
  va_list va;
  va_copy(va, va); // expected-warning{{va_list 'va' is copied onto itself}}
  // expected-note@-1{{va_list 'va' is copied onto itself}}
}

void copyOverwrite(int fst, ...) {
  va_list va, va2;
  va_start(va, fst); // expected-note{{Initialized va_list}}
  va_copy(va, va2); // expected-warning{{Initialized va_list 'va' is overwritten by an uninitialized one}}
  // expected-note@-1{{Initialized va_list 'va' is overwritten by an uninitialized one}}
}

void copyUnint(int fst, ...) {
  va_list va, va2;
  va_copy(va, va2); // expected-warning{{Uninitialized va_list is copied}}
  // expected-note@-1{{Uninitialized va_list is copied}}
}

void g1(int fst, ...) {
  va_list va;
  va_end(va); // expected-warning{{va_end() is called on an uninitialized va_list}}
  // expected-note@-1{{va_end() is called on an uninitialized va_list}}
}

void g2(int fst, ...) {
  va_list va;
  va_start(va, fst); // expected-note{{Initialized va_list}}
  va_end(va); // expected-note{{Ended va_list}}
  va_end(va); // expected-warning{{va_end() is called on an uninitialized va_list}}
  // expected-note@-1{{va_end() is called on an uninitialized va_list}}
}

void is_sink(int fst, ...) {
  va_list va;
  va_end(va); // expected-warning{{va_end() is called on an uninitialized va_list}}
  // expected-note@-1{{va_end() is called on an uninitialized va_list}}
  *((volatile int *)0) = 1;
}

// NOTE: this is invalid, as the man page of va_end requires that "Each invocation of va_start()
// must be matched by a corresponding  invocation of va_end() in the same function."
void ends_arg(va_list arg) {
  va_end(arg);
} //no-warning

void uses_arg(va_list arg) {
  (void)va_arg(arg, int);
} //no-warning

void call_vprintf_ok(int isstring, ...) {
  va_list va;
  va_start(va, isstring);
  vprintf(isstring ? "%s" : "%d", va);
  va_end(va);
} //no-warning

void call_some_other_func(int n, ...) {
  va_list va;
  some_library_function(n, va);
} //no-warning

void inlined_uses_arg_good(va_list arg) {
  (void)va_arg(arg, int);
}

void call_inlined_uses_arg_good(int fst, ...) {
  va_list va;
  va_start(va, fst);
  inlined_uses_arg_good(va);
  va_end(va);
}

void va_copy_test(va_list arg) {
  va_list dst;
  va_copy(dst, arg);
  va_end(dst);
}