Bug Summary

File:src/sys/arch/amd64/stand/boot/../../../../stand/boot/cmd.c
Warning:line 371, column 2
2nd function call argument is an uninitialized value

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple i386-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name cmd.c -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 static -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -ffreestanding -target-cpu i586 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/stand/boot/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/llvm16/lib/clang/16 -D MDRANDOM -D BOOT_STTY -D _STANDALONE -D __INTERNAL_LIBSA_CREAD -I /usr/src/sys/arch/amd64/stand/boot/../../../.. -I /usr/src/sys/arch/amd64/stand/boot/../libsa -I . -I /usr/src/sys/arch/amd64/stand/boot -D SOFTRAID -D BOOTMAGIC=0xc001d00d -D LINKADDR=0x40120 -D SLOW -D SMALL -D NOBYFOUR -D NO_GZIP -D DYNAMIC_CRC_TABLE -D BUILDFIXED -D HIBERNATE -D HEAP_LIMIT=0xA0000 -I /usr/src/sys/arch/amd64/stand/boot/../../../../stand/boot -Oz -fdebug-compilation-dir=/usr/src/sys/arch/amd64/stand/boot/obj -ferror-limit 19 -fwrapv -fno-builtin -fgnuc-version=4.2.1 -fpack-struct=1 -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 -o /home/ben/Projects/scan/2024-01-11-140451-98009-1 -x c /usr/src/sys/arch/amd64/stand/boot/../../../../stand/boot/cmd.c
1/* $OpenBSD: cmd.c,v 1.70 2023/02/23 19:48:22 miod Exp $ */
2
3/*
4 * Copyright (c) 1997-1999 Michael Shalayeff
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#include <sys/param.h>
30#include <sys/reboot.h>
31
32#include <libsa.h>
33#include <lib/libkern/funcs.h>
34
35#include "cmd.h"
36
37#define CTRL(c)((c)&0x1f) ((c)&0x1f)
38
39static int Xboot(void);
40static int Xecho(void);
41static int Xhelp(void);
42static int Xhexdump(void);
43static int Xls(void);
44static int Xnop(void);
45static int Xreboot(void);
46#ifdef BOOT_STTY1
47static int Xstty(void);
48#endif
49static int Xtime(void);
50#ifdef MACHINE_CMDcmd_machine
51static int Xmachine(void);
52extern const struct cmd_table MACHINE_CMDcmd_machine[];
53#endif
54extern int Xset(void);
55extern int Xenv(void);
56
57#ifdef CHECK_SKIP_CONFcheck_skip_conf
58extern int CHECK_SKIP_CONFcheck_skip_conf(void);
59#endif
60
61extern const struct cmd_table cmd_set[];
62const struct cmd_table cmd_table[] = {
63 {"#", CMDT_CMD0, Xnop}, /* XXX must be first */
64 {"boot", CMDT_CMD0, Xboot},
65 {"echo", CMDT_CMD0, Xecho},
66 {"env", CMDT_CMD0, Xenv},
67 {"help", CMDT_CMD0, Xhelp},
68 {"hexdump",CMDT_CMD0, Xhexdump},
69 {"ls", CMDT_CMD0, Xls},
70#ifdef MACHINE_CMDcmd_machine
71 {"machine",CMDT_MDC3, Xmachine},
72#endif
73 {"reboot", CMDT_CMD0, Xreboot},
74 {"set", CMDT_SET2, Xset},
75#ifdef BOOT_STTY1
76 {"stty", CMDT_CMD0, Xstty},
77#endif
78 {"time", CMDT_CMD0, Xtime},
79 {NULL((void *)0), 0},
80};
81
82static void ls(char *, struct stat *);
83static int readline(char *, size_t, int);
84char *nextword(char *);
85static char *whatcmd(const struct cmd_table **ct, char *);
86static char *qualify(char *);
87
88char cmd_buf[CMD_BUFF_SIZE133];
89
90int
91getcmd(void)
92{
93 cmd.cmd = NULL((void *)0);
94
95 if (!readline(cmd_buf, sizeof(cmd_buf), cmd.timeout))
96 cmd.cmd = cmd_table;
97
98 return docmd();
99}
100
101int
102read_conf(void)
103{
104#ifndef INSECURE
105 struct stat sb;
106#endif
107 int fd, rc = 0;
108
109#ifdef CHECK_SKIP_CONFcheck_skip_conf
110 if (CHECK_SKIP_CONFcheck_skip_conf()) {
111 printf("boot.conf processing skipped at operator request\n");
112 cmd.timeout = 0;
113 return -1; /* Pretend file wasn't found */
114 }
115#endif
116
117 if ((fd = open(qualify(cmd.conf), O_RDONLY0x0000)) < 0) {
118 if (errno != ENOENT2 && errno != ENXIO6) {
119 printf("open(%s): %s\n", cmd.path, strerror(errno));
120 return 0;
121 }
122 return -1;
123 }
124
125#ifndef INSECURE
126 (void) fstat(fd, &sb);
127 if (sb.st_uid || (sb.st_mode & 2)) {
128 printf("non-secure %s, will not proceed\n", cmd.path);
129 close(fd);
130 return -1;
131 }
132#endif
133
134 do {
135 char *p = cmd_buf;
136
137 cmd.cmd = NULL((void *)0);
138 do {
139 rc = read(fd, p, 1);
140 } while (rc > 0 && *p++ != '\n' &&
141 (p-cmd_buf) < sizeof(cmd_buf));
142
143 if (rc < 0) { /* Error from read() */
144 printf("%s: %s\n", cmd.path, strerror(errno));
145 break;
146 }
147
148 if (rc == 0) { /* eof from read() */
149 if (p != cmd_buf) { /* Line w/o trailing \n */
150 *p = '\0';
151 rc = docmd();
152 break;
153 }
154 } else { /* rc > 0, read a char */
155 p--; /* Get back to last character */
156
157 if (*p != '\n') { /* Line was too long */
158 printf("%s: line too long\n", cmd.path);
159
160 /* Don't want to run the truncated command */
161 rc = -1;
162 }
163 *p = '\0';
164 }
165 } while (rc > 0 && !(rc = docmd()));
166
167 close(fd);
168 return rc;
169}
170
171int
172docmd(void)
173{
174 char *p = NULL((void *)0);
175 const struct cmd_table *ct = cmd_table, *cs;
176
177 cmd.argc = 1;
178 if (cmd.cmd == NULL((void *)0)) {
179
180 /* command */
181 for (p = cmd_buf; *p == ' ' || *p == '\t'; p++)
182 ;
183 if (*p == '#' || *p == '\0') { /* comment or empty string */
184#ifdef DEBUG
185 printf("rem\n");
186#endif
187 return 0;
188 }
189 ct = cmd_table;
190 cs = NULL((void *)0);
191 cmd.argv[cmd.argc] = p; /* in case it's shortcut boot */
192 p = whatcmd(&ct, p);
193 if (ct == NULL((void *)0)) {
194 cmd.argc++;
195 ct = cmd_table;
196 } else if (ct->cmd_type == CMDT_SET2 && p != NULL((void *)0)) {
197 cs = cmd_set;
198#ifdef MACHINE_CMDcmd_machine
199 } else if (ct->cmd_type == CMDT_MDC3 && p != NULL((void *)0)) {
200 cs = MACHINE_CMDcmd_machine;
201#endif
202 }
203
204 if (cs != NULL((void *)0)) {
205 p = whatcmd(&cs, p);
206 if (cs == NULL((void *)0)) {
207 printf("%s: syntax error\n", ct->cmd_name);
208 return 0;
209 }
210 ct = cs;
211 }
212 cmd.cmd = ct;
213 }
214
215 cmd.argv[0] = ct->cmd_name;
216 while (p && cmd.argc+1 < sizeof(cmd.argv) / sizeof(cmd.argv[0])) {
217 cmd.argv[cmd.argc++] = p;
218 p = nextword(p);
219 }
220 cmd.argv[cmd.argc] = NULL((void *)0);
221
222 return (*cmd.cmd->cmd_exec)();
223}
224
225static char *
226whatcmd(const struct cmd_table **ct, char *p)
227{
228 char *q;
229 int l;
230
231 q = nextword(p);
232
233 for (l = 0; p[l]; l++)
234 ;
235
236 while ((*ct)->cmd_name != NULL((void *)0) && strncmp(p, (*ct)->cmd_name, l))
237 (*ct)++;
238
239 if ((*ct)->cmd_name == NULL((void *)0))
240 *ct = NULL((void *)0);
241
242 return q;
243}
244
245static int
246readline(char *buf, size_t n, int to)
247{
248#ifdef DEBUG
249 extern int debug;
250#endif
251 char *p = buf, ch;
252
253 /* Only do timeout if greater than 0 */
254 if (to > 0) {
255 time_t tt = getsecs() + to;
256#ifdef DEBUG
257 if (debug > 2)
258 printf ("readline: timeout(%d) at %u\n", to, tt);
259#endif
260 while (!cnischar() && getsecs() < tt)
261 continue;
262
263 if (!cnischar()) {
264 strlcpy(buf, "boot", 5);
265 putchar('\n');
266 return strlen(buf);
267 }
268 } else
269 while (!cnischar())
270 ;
271
272 /* User has typed something. Turn off timeouts. */
273 cmd.timeout = 0;
274
275 while (1) {
276 switch ((ch = getchar())) {
277 case CTRL('u')(('u')&0x1f):
278 while (p > buf) {
279 putchar('\177');
280 p--;
281 }
282 continue;
283 case '\n':
284 case '\r':
285 *p = '\0';
286 break;
287 case '\b':
288 case '\177':
289 if (p > buf) {
290 putchar('\177');
291 p--;
292 }
293 continue;
294 default:
295 if (ch >= ' ' && ch < '\177') {
296 if (p - buf < n-1)
297 *p++ = ch;
298 else {
299 putchar('\007');
300 putchar('\177');
301 }
302 }
303 continue;
304 }
305 break;
306 }
307
308 return p - buf;
309}
310
311/*
312 * Search for spaces/tabs after the current word. If found, \0 the
313 * first one. Then pass a pointer to the first character of the
314 * next word, or NULL if there is no next word.
315 */
316char *
317nextword(char *p)
318{
319 /* skip blanks */
320 while (*p && *p != '\t' && *p != ' ')
321 p++;
322 if (*p) {
323 *p++ = '\0';
324 while (*p == '\t' || *p == ' ')
325 p++;
326 }
327 if (*p == '\0')
328 p = NULL((void *)0);
329 return p;
330}
331
332static void
333print_help(const struct cmd_table *ct)
334{
335 for (; ct->cmd_name != NULL((void *)0); ct++)
336 printf(" %s", ct->cmd_name);
337 putchar('\n');
338}
339
340static int
341Xhelp(void)
342{
343 printf("commands:");
344 print_help(cmd_table);
345#ifdef MACHINE_CMDcmd_machine
346 return Xmachine();
347#else
348 return 0;
349#endif
350}
351
352static int
353Xhexdump(void)
354{
355 long long val[2];
356 char *ep;
357 int i;
358
359 if (cmd.argc != 3) {
1
Assuming field 'argc' is equal to 3
2
Taking false branch
360 printf("hexdump addr size\n");
361 return 0;
362 }
363
364 for (i = 1; i < cmd.argc; i++) {
3
Loop condition is true. Entering loop body
7
Assuming 'i' is >= field 'argc'
8
Loop condition is false. Execution continues on line 371
365 val[i-1] = strtoll(cmd.argv[i], &ep, 0);
366 if (cmd.argv[i][0] == '\0' || *ep != '\0') {
4
Assuming the condition is false
5
Assuming the condition is false
6
Taking false branch
367 printf("bad '%c' in \"%s\"\n", *ep, cmd.argv[i]);
368 return 0;
369 }
370 }
371 hexdump((void *)(unsigned long)val[0], val[1]);
9
2nd function call argument is an uninitialized value
372 return 0;
373}
374
375#ifdef MACHINE_CMDcmd_machine
376static int
377Xmachine(void)
378{
379 printf("machine:");
380 print_help(MACHINE_CMDcmd_machine);
381 return 0;
382}
383#endif
384
385static int
386Xecho(void)
387{
388 int i;
389
390 for (i = 1; i < cmd.argc; i++)
391 printf("%s ", cmd.argv[i]);
392 putchar('\n');
393 return 0;
394}
395
396#ifdef BOOT_STTY1
397static int
398Xstty(void)
399{
400 int sp;
401 char *cp;
402 dev_t dev;
403
404 if (cmd.argc == 1) {
405 printf("%s speed is %d\n", ttyname(0), cnspeed(0, -1));
406 return 0;
407 }
408 dev = ttydev(cmd.argv[1]);
409 if (dev == NODEV(dev_t)(-1)) {
410 printf("%s not a console device\n", cmd.argv[1]);
411 return 0;
412 }
413
414 if (cmd.argc == 2)
415 printf("%s speed is %d\n", cmd.argv[1],
416 cnspeed(dev, -1));
417 else {
418 sp = 0;
419 for (cp = cmd.argv[2]; isdigit(*cp)((*cp) >= '0' && (*cp) <= '9'); cp++)
420 sp = sp * 10 + (*cp - '0');
421 cnspeed(dev, sp);
422 }
423 return 0;
424}
425#endif
426
427static int
428Xtime(void)
429{
430 time_t tt = getsecs();
431
432 if (cmd.argc == 1)
433 printf(ctime(&tt));
434
435 return 0;
436}
437
438static int
439Xls(void)
440{
441 struct stat sb;
442 char *p;
443 int fd;
444
445 if (stat(qualify((cmd.argv[1]? cmd.argv[1]: "/.")), &sb) < 0) {
446 printf("stat(%s): %s\n", cmd.path, strerror(errno));
447 return 0;
448 }
449
450 if ((sb.st_mode & S_IFMT0170000) != S_IFDIR0040000)
451 ls(cmd.path, &sb);
452 else {
453 if ((fd = opendir(cmd.path)) < 0) {
454 printf("opendir(%s): %s\n", cmd.path,
455 strerror(errno));
456 return 0;
457 }
458
459 /* no strlen in lib !!! */
460 for (p = cmd.path; *p; p++)
461 ;
462 *p++ = '/';
463 *p = '\0';
464
465 while (readdir(fd, p) >= 0) {
466 if (stat(cmd.path, &sb) < 0)
467 printf("stat(%s): %s\n", cmd.path,
468 strerror(errno));
469 else
470 ls(p, &sb);
471 }
472 closedir (fd);
473 }
474 return 0;
475}
476
477#define lsrwx(mode,s) \
478 putchar ((mode) & S_IROTH0000004? 'r' : '-'); \
479 putchar ((mode) & S_IWOTH0000002? 'w' : '-'); \
480 putchar ((mode) & S_IXOTH0000001? *(s): (s)[1]);
481
482static void
483ls(char *name, struct stat *sb)
484{
485 putchar("-fc-d-b---l-s-w-"[(sb->st_mode & S_IFMT0170000) >> 12]);
486 lsrwx(sb->st_mode >> 6, (sb->st_mode & S_ISUID0004000? "sS" : "x-"));
487 lsrwx(sb->st_mode >> 3, (sb->st_mode & S_ISGID0002000? "sS" : "x-"));
488 lsrwx(sb->st_mode , (sb->st_mode & S_ISTXT0001000? "tT" : "x-"));
489
490 printf (" %u,%u\t%lu\t%s\n", sb->st_uid, sb->st_gid,
491 (u_long)sb->st_size, name);
492}
493#undef lsrwx
494
495int doboot = 1;
496
497static int
498Xnop(void)
499{
500 if (doboot) {
501 doboot = 0;
502 return (Xboot());
503 }
504
505 return 0;
506}
507
508static int
509Xboot(void)
510{
511 if (cmd.argc > 1 && cmd.argv[1][0] != '-') {
512 qualify((cmd.argv[1]? cmd.argv[1]: cmd.image));
513 if (bootparse(2))
514 return 0;
515 } else {
516 if (bootparse(1))
517 return 0;
518 snprintf(cmd.path, sizeof cmd.path, "%s:%s",
519 cmd.bootdev, cmd.image);
520 }
521
522 return 1;
523}
524
525/*
526 * Qualifies the path adding necessary dev
527 */
528
529static char *
530qualify(char *name)
531{
532 char *p;
533
534 for (p = name; *p; p++)
535 if (*p == ':')
536 break;
537 if (*p == ':')
538 strlcpy(cmd.path, name, sizeof(cmd.path));
539 else
540 snprintf(cmd.path, sizeof cmd.path, "%s:%s",
541 cmd.bootdev, name);
542 return cmd.path;
543}
544
545static int
546Xreboot(void)
547{
548 printf("Rebooting...\n");
549 exit();
550 return 0; /* just in case */
551}
552
553int
554upgrade(void)
555{
556 struct stat sb;
557
558 if (stat(qualify(("/bsd.upgrade")), &sb) < 0)
559 return 0;
560 if ((sb.st_mode & S_IXUSR0000100) == 0) {
561 printf("/bsd.upgrade is not u+x\n");
562 return 0;
563 }
564 return 1;
565}