Bug Summary

File:src/lib/libc/gen/exec.c
Warning:line 278, column 3
2nd function call argument is an uninitialized value

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name exec.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/lib/libc/obj -resource-dir /usr/local/lib/clang/13.0.0 -include namespace.h -I /usr/src/lib/libc/include -I /usr/src/lib/libc/hidden -D __LIBC__ -D APIWARN -D YP -I /usr/src/lib/libc/yp -I /usr/src/lib/libc -I /usr/src/lib/libc/gdtoa -I /usr/src/lib/libc/arch/amd64/gdtoa -D INFNAN_CHECK -D MULTIPLE_THREADS -D NO_FENV_H -D USE_LOCALE -I /usr/src/lib/libc -I /usr/src/lib/libc/citrus -D RESOLVSORT -D FLOATING_POINT -D PRINTF_WIDE_CHAR -D SCANF_WIDE_CHAR -D FUTEX -D PIC -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/lib/libc/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/lib/libc/gen/exec.c
1/* $OpenBSD: exec.c,v 1.24 2021/09/22 20:40:06 deraadt Exp $ */
2/*-
3 * Copyright (c) 1991, 1993
4 * The Regents of the University of California. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the University nor the names of its contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31#include <sys/types.h>
32#include <sys/uio.h>
33#include <sys/mman.h>
34
35#include <errno(*__errno()).h>
36#include <limits.h>
37#include <paths.h>
38#include <stdarg.h>
39#include <stdio.h>
40#include <stdlib.h>
41#include <string.h>
42#include <unistd.h>
43
44int
45execl(const char *name, const char *arg, ...)
46{
47 va_list ap;
48 char **argv;
49 size_t maplen;
50 int save_errno, n, error;
51
52 va_start(ap, arg)__builtin_va_start(ap, arg);
53 n = 1;
54 while (va_arg(ap, char *)__builtin_va_arg(ap, char *) != NULL((void *)0))
55 n++;
56 va_end(ap)__builtin_va_end(ap);
57
58 maplen = (n + 1) * sizeof(*argv);
59 argv = mmap(NULL((void *)0), maplen, PROT_WRITE0x02|PROT_READ0x01,
60 MAP_ANON0x1000|MAP_PRIVATE0x0002, -1, 0);
61 if (argv == MAP_FAILED((void *)-1))
62 return (-1);
63
64 va_start(ap, arg)__builtin_va_start(ap, arg);
65 n = 1;
66 argv[0] = (char *)arg;
67 while ((argv[n] = va_arg(ap, char *)__builtin_va_arg(ap, char *)) != NULL((void *)0))
68 n++;
69 va_end(ap)__builtin_va_end(ap);
70
71 error = execve(name, argv, environ);
72 save_errno = errno(*__errno());
73 munmap(argv, maplen);
74 errno(*__errno()) = save_errno;
75 return (error);
76}
77DEF_WEAK(execl)__asm__(".weak " "execl" " ; " "execl" " = " "_libc_execl");
78
79int
80execle(const char *name, const char *arg, ...)
81{
82 va_list ap;
83 char **argv, **envp;
84 size_t maplen;
85 int save_errno, n, error;
86
87 va_start(ap, arg)__builtin_va_start(ap, arg);
88 n = 1;
89 while (va_arg(ap, char *)__builtin_va_arg(ap, char *) != NULL((void *)0))
90 n++;
91 va_end(ap)__builtin_va_end(ap);
92
93 maplen = (n + 1) * sizeof(*argv);
94 argv = mmap(NULL((void *)0), maplen, PROT_WRITE0x02|PROT_READ0x01,
95 MAP_ANON0x1000|MAP_PRIVATE0x0002, -1, 0);
96 if (argv == MAP_FAILED((void *)-1))
97 return (-1);
98
99 va_start(ap, arg)__builtin_va_start(ap, arg);
100 n = 1;
101 argv[0] = (char *)arg;
102 while ((argv[n] = va_arg(ap, char *)__builtin_va_arg(ap, char *)) != NULL((void *)0))
103 n++;
104 envp = va_arg(ap, char **)__builtin_va_arg(ap, char **);
105 va_end(ap)__builtin_va_end(ap);
106
107 error = execve(name, argv, envp);
108 save_errno = errno(*__errno());
109 munmap(argv, maplen);
110 errno(*__errno()) = save_errno;
111 return error;
112}
113
114int
115execlp(const char *name, const char *arg, ...)
116{
117 va_list ap;
118 char **argv;
119 size_t maplen;
120 int save_errno, n, error;
121
122 va_start(ap, arg)__builtin_va_start(ap, arg);
123 n = 1;
124 while (va_arg(ap, char *)__builtin_va_arg(ap, char *) != NULL((void *)0))
1
Loop condition is false. Execution continues on line 126
125 n++;
126 va_end(ap)__builtin_va_end(ap);
127
128 maplen = (n + 1) * sizeof(*argv);
129 argv = mmap(NULL((void *)0), maplen, PROT_WRITE0x02|PROT_READ0x01,
130 MAP_ANON0x1000|MAP_PRIVATE0x0002, -1, 0);
131 if (argv == MAP_FAILED((void *)-1))
2
Assuming the condition is false
3
Taking false branch
132 return (-1);
133
134 va_start(ap, arg)__builtin_va_start(ap, arg);
135 n = 1;
136 argv[0] = (char *)arg;
137 while ((argv[n] = va_arg(ap, char *)__builtin_va_arg(ap, char *)) != NULL((void *)0))
4
Assuming the condition is false
5
Loop condition is false. Execution continues on line 139
138 n++;
139 va_end(ap)__builtin_va_end(ap);
140 error = execvp(name, argv);
6
Calling 'execvp'
141 save_errno = errno(*__errno());
142 munmap(argv, maplen);
143 errno(*__errno()) = save_errno;
144 return error;
145}
146
147int
148execv(const char *name, char *const *argv)
149{
150 (void)execve(name, argv, environ);
151 return (-1);
152}
153
154int
155execvpe(const char *name, char *const *argv, char *const *envp)
156{
157 char **memp;
158 int cnt;
159 size_t lp, ln, curlen;
8
'curlen' declared without an initial value
160 char *p;
161 int eacces = 0;
162 char *bp, *cur, *path, buf[PATH_MAX1024];
163 size_t maplen;
164 int save_errno, n;
165
166 /*
167 * Do not allow null name
168 */
169 if (name == NULL((void *)0) || *name == '\0') {
9
Assuming 'name' is not equal to NULL
10
Assuming the condition is false
11
Taking false branch
170 errno(*__errno()) = ENOENT2;
171 return (-1);
172 }
173
174 /* If it's an absolute or relative path name, it's easy. */
175 if (strchr(name, '/')) {
12
Assuming the condition is true
13
Taking true branch
176 bp = (char *)name;
177 cur = path = NULL((void *)0);
178 goto retry;
14
Control jumps to line 228
179 }
180 bp = buf;
181
182 /* Get the path we're searching. */
183 if (!(path = getenv("PATH")))
184 path = _PATH_DEFPATH"/usr/bin:/bin:/usr/sbin:/sbin:/usr/X11R6/bin:/usr/local/bin:/usr/local/sbin";
185
186 curlen = strlen(path) + 1;
187 cur = mmap(NULL((void *)0), curlen, PROT_WRITE0x02|PROT_READ0x01,
188 MAP_ANON0x1000|MAP_PRIVATE0x0002, -1, 0);
189 if (cur == MAP_FAILED((void *)-1))
190 return (-1);
191
192 strlcpy(cur, path, curlen);
193 path = cur;
194 while ((p = strsep(&cur, ":"))) {
17
Loop condition is false. Execution continues on line 271
195 /*
196 * It's a SHELL path -- double, leading and trailing colons
197 * mean the current directory.
198 */
199 if (!*p) {
200 p = ".";
201 lp = 1;
202 } else
203 lp = strlen(p);
204 ln = strlen(name);
205
206 /*
207 * If the path is too long complain. This is a possible
208 * security issue; given a way to make the path too long
209 * the user may execute the wrong program.
210 */
211 if (lp + ln + 2 > sizeof(buf)) {
212 struct iovec iov[3];
213
214 iov[0].iov_base = "execvp: ";
215 iov[0].iov_len = 8;
216 iov[1].iov_base = p;
217 iov[1].iov_len = lp;
218 iov[2].iov_base = ": path too long\n";
219 iov[2].iov_len = 16;
220 (void)writev(STDERR_FILENO2, iov, 3);
221 continue;
222 }
223 bcopy(p, buf, lp);
224 buf[lp] = '/';
225 bcopy(name, buf + lp + 1, ln);
226 buf[lp + ln + 1] = '\0';
227
228retry: (void)execve(bp, argv, envp);
229 switch(errno(*__errno())) {
15
Control jumps to 'case 20:' at line 257
230 case E2BIG7:
231 goto done;
232 case EISDIR21:
233 case ELOOP62:
234 case ENAMETOOLONG63:
235 case ENOENT2:
236 break;
237 case ENOEXEC8:
238 for (cnt = 0; argv[cnt]; ++cnt)
239 ;
240
241 maplen = (cnt + 2) * sizeof(char *);
242 memp = mmap(NULL((void *)0), maplen, PROT_WRITE0x02|PROT_READ0x01,
243 MAP_ANON0x1000|MAP_PRIVATE0x0002, -1, 0);
244 if (memp == MAP_FAILED((void *)-1))
245 goto done;
246
247 memp[0] = "sh";
248 memp[1] = bp;
249 bcopy(argv + 1, memp + 2, cnt * sizeof(char *));
250 (void)execve(_PATH_BSHELL"/bin/sh", memp, envp);
251 save_errno = errno(*__errno());
252 munmap(memp, maplen);
253 errno(*__errno()) = save_errno;
254 goto done;
255 case ENOMEM12:
256 goto done;
257 case ENOTDIR20:
258 break;
16
Execution continues on line 194
259 case ETXTBSY26:
260 /*
261 * We used to retry here, but sh(1) doesn't.
262 */
263 goto done;
264 case EACCES13:
265 eacces = 1;
266 break;
267 default:
268 goto done;
269 }
270 }
271 if (eacces
17.1
'eacces' is 0
)
18
Taking false branch
272 errno(*__errno()) = EACCES13;
273 else if (!errno(*__errno()))
19
Assuming the condition is false
20
Taking false branch
274 errno(*__errno()) = ENOENT2;
275done:
276 if (cur) {
21
Assuming 'cur' is non-null
22
Taking true branch
277 save_errno = errno(*__errno());
278 munmap(cur, curlen);
23
2nd function call argument is an uninitialized value
279 errno(*__errno()) = save_errno;
280 }
281 return (-1);
282}
283DEF_WEAK(execvpe)__asm__(".weak " "execvpe" " ; " "execvpe" " = " "_libc_execvpe"
)
;
284
285int
286execvp(const char *name, char *const *argv)
287{
288 return execvpe(name, argv, environ);
7
Calling 'execvpe'
289}
290DEF_WEAK(execvp)__asm__(".weak " "execvp" " ; " "execvp" " = " "_libc_execvp"
)
;
291