Bug Summary

File:3rdparty/vboot/futility/futility.c
Warning:line 230, column 14
Value stored to 'vstr' during its initialization is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name futility.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 pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/home/coreboot/node-root/workspace/coreboot_scanbuild/3rdparty/vboot -resource-dir /opt/xgcc/lib/clang/17 -D CHROMEOS_ENVIRONMENT -D EC_EFS=0 -D EXTERNAL_TPM_CLEAR_REQUEST=0 -D _GNU_SOURCE -D _FILE_OFFSET_BITS=64 -D HAVE_EXECINFO_H -D HAVE_NSS -I /usr/include/nss -I /usr/include/nspr -I firmware/include -I firmware/lib/include -I firmware/lib/cgptlib/include -I firmware/lib/tpm_lite/include -I firmware/2lib/include -I host/include -I host/lib/include -I host/lib21/include -I host/lib21/include -internal-isystem /opt/xgcc/lib/clang/17/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/13/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -source-date-epoch 1714465709 -Os -Wno-deprecated-declarations -Wno-trigraphs -Wwrite-strings -Wno-format-security -Wno-address-of-packed-member -Wno-unknown-warning -Wno-error=deprecated-declarations -std=gnu11 -fconst-strings -fdebug-compilation-dir=/home/coreboot/node-root/workspace/coreboot_scanbuild/3rdparty/vboot -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-opt-analyze-headers -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /cb-build/coreboot_scanbuild.0/sharedutils-scanbuildtmp/2024-05-02-073004-2299942-1 -x c futility/futility.c
1/* Copyright 2013 The ChromiumOS Authors
2 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file.
4 */
5
6#include <errno(*__errno_location ()).h>
7#include <fcntl.h>
8#include <getopt.h>
9#include <limits.h>
10#include <stdint.h>
11#include <stdio.h>
12#include <stdlib.h>
13#include <string.h>
14#include <sys/stat.h>
15#include <unistd.h>
16
17#include "futility.h"
18
19/******************************************************************************/
20/* Logging stuff */
21
22/* File to use for logging, if present */
23#define LOGFILE"/tmp/futility.log" "/tmp/futility.log"
24
25/* Normally logging will only happen if the logfile already exists. Uncomment
26 * this to force log file creation (and thus logging) always. */
27
28/* #define FORCE_LOGGING_ON */
29
30static int log_fd = -1;
31const char *ft_print_header = NULL((void*)0);
32const char *ft_print_header2 = NULL((void*)0);
33
34/* Write the string and a newline. Silently give up on errors */
35static void log_str(const char *prefix, const char *str)
36{
37 int len, done, n;
38
39 if (log_fd < 0)
40 return;
41
42 if (!str)
43 str = "(NULL)";
44
45 if (prefix && *prefix) {
46 len = strlen(prefix);
47 for (done = 0; done < len; done += n) {
48 n = write(log_fd, prefix + done, len - done);
49 if (n < 0)
50 return;
51 }
52 }
53
54 len = strlen(str);
55 if (len == 0) {
56 str = "(EMPTY)";
57 len = strlen(str);
58 }
59
60 for (done = 0; done < len; done += n) {
61 n = write(log_fd, str + done, len - done);
62 if (n < 0)
63 return;
64 }
65
66 if (write(log_fd, "\n", 1) < 0)
67 return;
68}
69
70static void log_close(void)
71{
72 struct flock lock;
73
74 if (log_fd >= 0) {
75 memset(&lock, 0, sizeof(lock));
76 lock.l_type = F_UNLCK2;
77 lock.l_whence = SEEK_SET0;
78 if (fcntl(log_fd, F_SETLKW7, &lock))
79 perror("Unable to unlock log file");
80
81 close(log_fd);
82 log_fd = -1;
83 }
84}
85
86static void log_open(void)
87{
88 struct flock lock;
89 int ret;
90
91#ifdef FORCE_LOGGING_ON
92 log_fd = open(LOGFILE"/tmp/futility.log", O_WRONLY01 | O_APPEND02000 | O_CREAT0100, 0666);
93#else
94 log_fd = open(LOGFILE"/tmp/futility.log", O_WRONLY01 | O_APPEND02000);
95#endif
96 if (log_fd < 0) {
97
98 if (errno(*__errno_location ()) != EACCES13)
99 return;
100
101 /* Permission problems should improve shortly ... */
102 sleep(1);
103 log_fd = open(LOGFILE"/tmp/futility.log", O_WRONLY01 | O_APPEND02000 | O_CREAT0100, 0666);
104 if (log_fd < 0) /* Nope, they didn't */
105 return;
106 }
107
108 /* Let anyone have a turn */
109 fchmod(log_fd, 0666);
110
111 /* But only one at a time */
112 memset(&lock, 0, sizeof(lock));
113 lock.l_type = F_WRLCK1;
114 lock.l_whence = SEEK_END2;
115
116 ret = fcntl(log_fd, F_SETLKW7, &lock); /* this blocks */
117 if (ret < 0)
118 log_close();
119}
120
121static void log_args(int argc, char *argv[])
122{
123 int i;
124 ssize_t r;
125 pid_t parent;
126 char buf[80];
127 FILE *fp;
128 char caller_buf[PATH_MAX4096];
129
130 log_open();
131
132 /* delimiter */
133 log_str(NULL((void*)0), "##### LOG #####");
134
135 /* Can we tell who called us? */
136 parent = getppid();
137 snprintf(buf, sizeof(buf), "/proc/%d/exe", parent);
138 r = readlink(buf, caller_buf, sizeof(caller_buf) - 1);
139 if (r >= 0) {
140 caller_buf[r] = '\0';
141 log_str("CALLER:", caller_buf);
142 }
143
144 /* From where? */
145 snprintf(buf, sizeof(buf), "/proc/%d/cwd", parent);
146 r = readlink(buf, caller_buf, sizeof(caller_buf) - 1);
147 if (r >= 0) {
148 caller_buf[r] = '\0';
149 log_str("DIR:", caller_buf);
150 }
151
152 /* And maybe the args? */
153 snprintf(buf, sizeof(buf), "/proc/%d/cmdline", parent);
154 fp = fopen(buf, "r");
155 if (fp) {
156 memset(caller_buf, 0, sizeof(caller_buf));
157 r = fread(caller_buf, 1, sizeof(caller_buf) - 1, fp);
158 if (r > 0) {
159 char *s = caller_buf;
160 for (i = 0; i < r && *s; ) {
161 log_str("CMDLINE:", s);
162 while (i < r && *s)
163 i++, s++;
164 i++, s++;
165 }
166 }
167 fclose(fp);
168 }
169
170 /* Now log the stuff about ourselves */
171 for (i = 0; i < argc; i++)
172 log_str(NULL((void*)0), argv[i]);
173
174 log_close();
175}
176
177/******************************************************************************/
178
179static const char *const usage = "\n"
180"Usage: " MYNAME"futility" " [options] COMMAND [args...]\n"
181"\n"
182"This is the unified firmware utility, which contains various of distinct\n"
183"verified boot tools as subcommands.\n"
184"\n"
185"See the README file for more information about the available commands\n";
186
187static const char *const options =
188"Global options:\n"
189"\n"
190" --vb1 Use only vboot v1.0 binary formats\n"
191" --vb21 Use only vboot v2.1 binary formats\n"
192" --debug Be noisy about what's going on\n"
193"\n";
194
195static const struct futil_cmd_t *find_command(const char *name)
196{
197 const struct futil_cmd_t *const *cmd;
198
199 for (cmd = futil_cmds; *cmd; cmd++)
200 if (((*cmd)->version & vboot_version) &&
201 !strcmp((*cmd)->name, name))
202 return *cmd;
203
204 return NULL((void*)0);
205}
206
207static void list_commands(void)
208{
209 const struct futil_cmd_t *const *cmd;
210
211 for (cmd = futil_cmds; *cmd; cmd++)
212 if (vboot_version & (*cmd)->version)
213 printf(" %-20s %s\n",
214 (*cmd)->name, (*cmd)->shorthelp);
215}
216
217static int run_command(const struct futil_cmd_t *cmd, int argc, char *argv[])
218{
219 int i;
220 VB2_DEBUG("\"%s\" ...\n", cmd->name)vb2ex_printf(__func__, "\"%s\" ...\n", cmd->name);
221 for (i = 0; i < argc; i++)
222 VB2_DEBUG(" argv[%d] = \"%s\"\n", i, argv[i])vb2ex_printf(__func__, " argv[%d] = \"%s\"\n", i, argv[i]);
223
224 return cmd->handler(argc, argv);
225}
226
227static int do_help(int argc, char *argv[])
228{
229 const struct futil_cmd_t *cmd;
230 const char *vstr = "";
Value stored to 'vstr' during its initialization is never read
231
232 /* Help about a known command? */
233 if (argc > 1) {
234 cmd = find_command(argv[1]);
235 if (cmd) {
236 /* Let the command provide its own help */
237 argv[0] = argv[1];
238 argv[1] = (char *)"--help";
239 return run_command(cmd, argc, argv);
240 }
241 }
242
243 fputs(usage, stdoutstdout);
244
245 if (vboot_version == VBOOT_VERSION_ALL)
246 fputs(options, stdoutstdout);
247
248 switch (vboot_version) {
249 case VBOOT_VERSION_1_0:
250 vstr = "version 1.0 ";
251 break;
252 case VBOOT_VERSION_2_1:
253 vstr = "version 2.1 ";
254 break;
255 case VBOOT_VERSION_ALL:
256 vstr = "";
257 break;
258 }
259 printf("The following %scommands are built-in:\n\n", vstr);
260 list_commands();
261 printf("\nUse \"" MYNAME"futility" " help COMMAND\" for more information.\n\n");
262
263 return 0;
264}
265
266DECLARE_FUTIL_COMMAND(help, do_help, VBOOT_VERSION_ALL,const struct futil_cmd_t __cmd_help = { .name = "help", .handler
= do_help, .version = VBOOT_VERSION_ALL, .shorthelp = "Show a bit of help (you're looking at it)"
, }
267 "Show a bit of help (you're looking at it)")const struct futil_cmd_t __cmd_help = { .name = "help", .handler
= do_help, .version = VBOOT_VERSION_ALL, .shorthelp = "Show a bit of help (you're looking at it)"
, }
;
268
269static const char ver_help[] =
270 "Show the futility source revision and build date";
271static int do_version(int argc, char *argv[])
272{
273 if (argc > 1)
274 printf("%s - %s\n", argv[0], ver_help);
275 else
276 printf("%s\n", futility_version);
277 return 0;
278}
279
280DECLARE_FUTIL_COMMAND(version, do_version, VBOOT_VERSION_ALL,const struct futil_cmd_t __cmd_version = { .name = "version",
.handler = do_version, .version = VBOOT_VERSION_ALL, .shorthelp
= ver_help, }
281 ver_help)const struct futil_cmd_t __cmd_version = { .name = "version",
.handler = do_version, .version = VBOOT_VERSION_ALL, .shorthelp
= ver_help, }
;
282
283static char *simple_basename(char *str)
284{
285 char *s = strrchr(str, '/');
286 if (s)
287 s++;
288 else
289 s = str;
290 return s;
291}
292
293/* Here we go */
294#define OPT_HELP1000 1000
295test_mockable__attribute__((weak))
296int main(int argc, char *argv[], char *envp[])
297{
298 char *progname;
299 const struct futil_cmd_t *cmd;
300 int i, errorcnt = 0;
301 int vb_ver = VBOOT_VERSION_ALL;
302 int helpind = 0;
303 struct option long_opts[] = {
304 {"debug", 0, &debugging_enabled, 1},
305 {"vb1" , 0, &vb_ver, VBOOT_VERSION_1_0},
306 {"vb21", 0, &vb_ver, VBOOT_VERSION_2_1},
307 {"help", 0, 0, OPT_HELP1000},
308 { 0, 0, 0, 0},
309 };
310
311 log_args(argc, argv);
312
313 /* How were we invoked? */
314 progname = simple_basename(argv[0]);
315
316 /* See if the program name is a command we recognize */
317 cmd = find_command(progname);
318 if (cmd) {
319 /* Yep, just do that */
320 return !!run_command(cmd, argc, argv);
321 }
322
323 /* Parse the global options, stopping at the first non-option. */
324 opterr = 0; /* quiet, you. */
325 while ((i = getopt_long(argc, argv, "+:", long_opts, NULL((void*)0))) != -1) {
326 switch (i) {
327 case OPT_HELP1000:
328 /* Remember where we found this option */
329 /* Note: this might be GNU-specific */
330 helpind = optind - 1;
331 break;
332 case '?':
333 if (optopt)
334 fprintf(stderrstderr, "Unrecognized option: -%c\n",
335 optopt);
336 else
337 fprintf(stderrstderr, "Unrecognized option: %s\n",
338 argv[optind - 1]);
339 errorcnt++;
340 break;
341 case ':':
342 fprintf(stderrstderr, "Missing argument to -%c\n", optopt);
343 errorcnt++;
344 break;
345 case 0: /* handled option */
346 break;
347 default:
348 FATAL("Unrecognized getopt output: %d\n", i)do { fprintf(stderr, "FATAL: %s: " "Unrecognized getopt output: %d\n"
, __func__, i ); exit(1); } while (0)
;
349 }
350 }
351 vboot_version = vb_ver;
352
353 /*
354 * Translate "--help" in the args to "help" as the first parameter,
355 * by rearranging argv[].
356 */
357 if (helpind) {
358 int j;
359 optind--;
360 for (j = helpind; j < optind; j++)
361 argv[j] = argv[j + 1];
362 argv[j] = (char *)"help";
363 }
364
365 /* We require a command name. */
366 if (errorcnt || argc == optind) {
367 do_help(1, argv);
368 return 1;
369 }
370
371 /* For reasons I've forgotten, treat /blah/blah/CMD the same as CMD */
372 argv[optind] = simple_basename(argv[optind]);
373
374 /* Do we recognize the command? */
375 cmd = find_command(argv[optind]);
376 if (cmd) {
377 /* Reset so commands can parse their own options */
378 argc -= optind;
379 argv += optind;
380 optind = 0;
381 return !!run_command(cmd, argc, argv);
382 }
383
384 /* Nope. We've no clue what we're being asked to do. */
385 do_help(1, argv);
386 return 1;
387}