Bug Summary

File:src/usr.sbin/vmd/fw_cfg.c
Warning:line 433, column 1
Potential leak of memory pointed to by 'data'

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 fw_cfg.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 -pic-is-pie -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/usr.sbin/vmd/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/usr.sbin/vmd -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.sbin/vmd/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/usr.sbin/vmd/fw_cfg.c
1/* $OpenBSD: fw_cfg.c,v 1.5 2021/11/05 10:18:50 jan Exp $ */
2/*
3 * Copyright (c) 2018 Claudio Jeker <claudio@openbsd.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17#include <sys/types.h>
18#include <sys/uio.h>
19#include <machine/vmmvar.h>
20
21#include <stdlib.h>
22#include <string.h>
23#include <unistd.h>
24
25#include "atomicio.h"
26#include "vmd.h"
27#include "vmm.h"
28#include "fw_cfg.h"
29
30#define FW_CFG_SIGNATURE0x0000 0x0000
31#define FW_CFG_ID0x0001 0x0001
32#define FW_CFG_NOGRAPHIC0x0004 0x0004
33#define FW_CFG_FILE_DIR0x0019 0x0019
34#define FW_CFG_FILE_FIRST0x0020 0x0020
35
36#define FW_CFG_DMA_SIGNATURE0x51454d5520434647ULL 0x51454d5520434647ULL /* QEMU CFG */
37
38struct fw_cfg_dma_access {
39 uint32_t control;
40#define FW_CFG_DMA_ERROR0x0001 0x0001
41#define FW_CFG_DMA_READ0x0002 0x0002
42#define FW_CFG_DMA_SKIP0x0004 0x0004
43#define FW_CFG_DMA_SELECT0x0008 0x0008
44#define FW_CFG_DMA_WRITE0x0010 0x0010 /* not implemented */
45 uint32_t length;
46 uint64_t address;
47};
48
49struct fw_cfg_file {
50 uint32_t size;
51 uint16_t selector;
52 uint16_t reserved;
53 char name[56];
54};
55
56extern char *__progname;
57
58static struct fw_cfg_state {
59 size_t offset;
60 size_t size;
61 uint8_t *data;
62} fw_cfg_state;
63
64static uint64_t fw_cfg_dma_addr;
65
66static int fw_cfg_select_file(uint16_t);
67static void fw_cfg_file_dir(void);
68
69void
70fw_cfg_init(struct vmop_create_params *vmc)
71{
72 const char *bootorder = NULL((void *)0);
73 unsigned int sd = 0;
74
75 /* do not double print chars on serial port */
76 fw_cfg_add_file("etc/screen-and-debug", &sd, sizeof(sd));
77
78 switch (vmc->vmc_bootdevice) {
79 case VMBOOTDEV_DISK1:
80 bootorder = "/pci@i0cf8/*@3\nHALT";
81 break;
82 case VMBOOTDEV_CDROM2:
83 bootorder = "/pci@i0cf8/*@4/*@0/*@0,40000100\nHALT";
84 break;
85 case VMBOOTDEV_NET3:
86 /* XXX not yet */
87 bootorder = "HALT";
88 break;
89 }
90 if (bootorder)
91 fw_cfg_add_file("bootorder", bootorder, strlen(bootorder) + 1);
92}
93
94int
95fw_cfg_dump(int fd)
96{
97 log_debug("%s: sending fw_cfg state", __func__);
98 if (atomicio(vwrite(ssize_t (*)(int, void *, size_t))write, fd, &fw_cfg_dma_addr,
99 sizeof(fw_cfg_dma_addr)) != sizeof(fw_cfg_dma_addr)) {
100 log_warnx("%s: error writing fw_cfg to fd", __func__);
101 return -1;
102 }
103 if (atomicio(vwrite(ssize_t (*)(int, void *, size_t))write, fd, &fw_cfg_state.offset,
104 sizeof(fw_cfg_state.offset)) != sizeof(fw_cfg_state.offset)) {
105 log_warnx("%s: error writing fw_cfg to fd", __func__);
106 return -1;
107 }
108 if (atomicio(vwrite(ssize_t (*)(int, void *, size_t))write, fd, &fw_cfg_state.size,
109 sizeof(fw_cfg_state.size)) != sizeof(fw_cfg_state.size)) {
110 log_warnx("%s: error writing fw_cfg to fd", __func__);
111 return -1;
112 }
113 if (fw_cfg_state.size != 0)
114 if (atomicio(vwrite(ssize_t (*)(int, void *, size_t))write, fd, fw_cfg_state.data,
115 fw_cfg_state.size) != fw_cfg_state.size) {
116 log_warnx("%s: error writing fw_cfg to fd", __func__);
117 return (-1);
118 }
119 return 0;
120}
121
122int
123fw_cfg_restore(int fd)
124{
125 log_debug("%s: receiving fw_cfg state", __func__);
126 if (atomicio(read, fd, &fw_cfg_dma_addr,
127 sizeof(fw_cfg_dma_addr)) != sizeof(fw_cfg_dma_addr)) {
128 log_warnx("%s: error reading fw_cfg from fd", __func__);
129 return -1;
130 }
131 if (atomicio(read, fd, &fw_cfg_state.offset,
132 sizeof(fw_cfg_state.offset)) != sizeof(fw_cfg_state.offset)) {
133 log_warnx("%s: error reading fw_cfg from fd", __func__);
134 return -1;
135 }
136 if (atomicio(read, fd, &fw_cfg_state.size,
137 sizeof(fw_cfg_state.size)) != sizeof(fw_cfg_state.size)) {
138 log_warnx("%s: error reading fw_cfg from fd", __func__);
139 return -1;
140 }
141 fw_cfg_state.data = NULL((void *)0);
142 if (fw_cfg_state.size != 0) {
143 if ((fw_cfg_state.data = malloc(fw_cfg_state.size)) == NULL((void *)0))
144 fatal("%s", __func__);
145 if (atomicio(read, fd, fw_cfg_state.data,
146 fw_cfg_state.size) != fw_cfg_state.size) {
147 log_warnx("%s: error reading fw_cfg from fd", __func__);
148 return -1;
149 }
150 }
151 return 0;
152}
153
154static void
155fw_cfg_reset_state(void)
156{
157 free(fw_cfg_state.data);
158 fw_cfg_state.offset = 0;
159 fw_cfg_state.size = 0;
160 fw_cfg_state.data = NULL((void *)0);
161}
162
163static void
164fw_cfg_set_state(void *data, size_t len)
165{
166 if ((fw_cfg_state.data = malloc(len)) == NULL((void *)0)) {
167 log_warn("%s", __func__);
168 return;
169 }
170 memcpy(fw_cfg_state.data, data, len);
171 fw_cfg_state.size = len;
172 fw_cfg_state.offset = 0;
173}
174
175static void
176fw_cfg_select(uint16_t selector)
177{
178 uint16_t one = 1;
179 uint32_t id = htole32(0x3)((__uint32_t)(0x3));
180
181 fw_cfg_reset_state();
182 switch (selector) {
16
Control jumps to 'case 25:' at line 192
183 case FW_CFG_SIGNATURE0x0000:
184 fw_cfg_set_state("QEMU", 4);
185 break;
186 case FW_CFG_ID0x0001:
187 fw_cfg_set_state(&id, sizeof(id));
188 break;
189 case FW_CFG_NOGRAPHIC0x0004:
190 fw_cfg_set_state(&one, sizeof(one));
191 break;
192 case FW_CFG_FILE_DIR0x0019:
193 fw_cfg_file_dir();
17
Calling 'fw_cfg_file_dir'
194 break;
195 default:
196 if (!fw_cfg_select_file(selector))
197 log_debug("%s: unhandled selector %x",
198 __func__, selector);
199 break;
200 }
201}
202
203static void
204fw_cfg_handle_dma(struct fw_cfg_dma_access *fw)
205{
206 uint32_t len = 0, control = fw->control;
207
208 fw->control = 0;
209 if (control & FW_CFG_DMA_SELECT0x0008) {
13
Assuming the condition is true
14
Taking true branch
210 uint16_t selector = control >> 16;
211 log_debug("%s: selector 0x%04x", __func__, selector);
212 fw_cfg_select(selector);
15
Calling 'fw_cfg_select'
213 }
214
215 /* calculate correct length of operation */
216 if (fw_cfg_state.offset < fw_cfg_state.size)
217 len = fw_cfg_state.size - fw_cfg_state.offset;
218 if (len > fw->length)
219 len = fw->length;
220
221 if (control & FW_CFG_DMA_WRITE0x0010) {
222 fw->control |= FW_CFG_DMA_ERROR0x0001;
223 } else if (control & FW_CFG_DMA_READ0x0002) {
224 if (write_mem(fw->address,
225 fw_cfg_state.data + fw_cfg_state.offset, len)) {
226 log_warnx("%s: write_mem error", __func__);
227 fw->control |= FW_CFG_DMA_ERROR0x0001;
228 }
229 /* clear rest of buffer */
230 if (len < fw->length)
231 if (write_mem(fw->address + len, NULL((void *)0),
232 fw->length - len)) {
233 log_warnx("%s: write_mem error", __func__);
234 fw->control |= FW_CFG_DMA_ERROR0x0001;
235 }
236 }
237 fw_cfg_state.offset += len;
238
239 if (fw_cfg_state.offset == fw_cfg_state.size)
240 fw_cfg_reset_state();
241}
242
243uint8_t
244vcpu_exit_fw_cfg(struct vm_run_params *vrp)
245{
246 uint32_t data = 0;
247 struct vm_exit *vei = vrp->vrp_exit;
248
249 get_input_data(vei, &data);
250
251 switch (vei->vei.vei_port) {
252 case FW_CFG_IO_SELECT0x510:
253 if (vei->vei.vei_dir == VEI_DIR_IN) {
254 log_warnx("%s: fw_cfg: read from selector port "
255 "unsupported", __progname);
256 set_return_data(vei, 0);
257 break;
258 }
259 log_debug("%s: selector 0x%04x", __func__, data);
260 fw_cfg_select(data);
261 break;
262 case FW_CFG_IO_DATA0x511:
263 if (vei->vei.vei_dir == VEI_DIR_OUT) {
264 log_debug("%s: fw_cfg: discarding data written to "
265 "data port", __progname);
266 break;
267 }
268 /* fw_cfg only defines 1-byte reads via IO port */
269 if (fw_cfg_state.offset < fw_cfg_state.size) {
270 set_return_data(vei,
271 fw_cfg_state.data[fw_cfg_state.offset++]);
272 if (fw_cfg_state.offset == fw_cfg_state.size)
273 fw_cfg_reset_state();
274 } else
275 set_return_data(vei, 0);
276 break;
277 }
278
279 return 0xFF;
280}
281
282uint8_t
283vcpu_exit_fw_cfg_dma(struct vm_run_params *vrp)
284{
285 struct fw_cfg_dma_access fw_dma;
286 uint32_t data = 0;
287 struct vm_exit *vei = vrp->vrp_exit;
288
289 if (vei->vei.vei_size != 4) {
1
Assuming field 'vei_size' is equal to 4
2
Taking false branch
290 log_debug("%s: fw_cfg_dma: discarding data written to "
291 "dma addr", __progname);
292 if (vei->vei.vei_dir == VEI_DIR_OUT)
293 fw_cfg_dma_addr = 0;
294 return 0xFF;
295 }
296
297 if (vei->vei.vei_dir == VEI_DIR_OUT) {
3
Assuming field 'vei_dir' is equal to VEI_DIR_OUT
4
Taking true branch
298 get_input_data(vei, &data);
299 switch (vei->vei.vei_port) {
5
Control jumps to 'case 1304:' at line 303
300 case FW_CFG_IO_DMA_ADDR_HIGH0x514:
301 fw_cfg_dma_addr = (uint64_t)be32toh(data)(__uint32_t)(__builtin_constant_p(data) ? (__uint32_t)(((__uint32_t
)(data) & 0xff) << 24 | ((__uint32_t)(data) & 0xff00
) << 8 | ((__uint32_t)(data) & 0xff0000) >> 8
| ((__uint32_t)(data) & 0xff000000) >> 24) : __swap32md
(data))
<< 32;
302 break;
303 case FW_CFG_IO_DMA_ADDR_LOW0x518:
304 fw_cfg_dma_addr |= be32toh(data)(__uint32_t)(__builtin_constant_p(data) ? (__uint32_t)(((__uint32_t
)(data) & 0xff) << 24 | ((__uint32_t)(data) & 0xff00
) << 8 | ((__uint32_t)(data) & 0xff0000) >> 8
| ((__uint32_t)(data) & 0xff000000) >> 24) : __swap32md
(data))
;
6
'?' condition is false
305
306 /* writing least significant half triggers operation */
307 if (read_mem(fw_cfg_dma_addr, &fw_dma, sizeof(fw_dma)))
7
Assuming the condition is false
8
Taking false branch
308 break;
309 /* adjust byteorder */
310 fw_dma.control = be32toh(fw_dma.control)(__uint32_t)(__builtin_constant_p(fw_dma.control) ? (__uint32_t
)(((__uint32_t)(fw_dma.control) & 0xff) << 24 | ((__uint32_t
)(fw_dma.control) & 0xff00) << 8 | ((__uint32_t)(fw_dma
.control) & 0xff0000) >> 8 | ((__uint32_t)(fw_dma.control
) & 0xff000000) >> 24) : __swap32md(fw_dma.control)
)
;
9
'?' condition is false
311 fw_dma.length = be32toh(fw_dma.length)(__uint32_t)(__builtin_constant_p(fw_dma.length) ? (__uint32_t
)(((__uint32_t)(fw_dma.length) & 0xff) << 24 | ((__uint32_t
)(fw_dma.length) & 0xff00) << 8 | ((__uint32_t)(fw_dma
.length) & 0xff0000) >> 8 | ((__uint32_t)(fw_dma.length
) & 0xff000000) >> 24) : __swap32md(fw_dma.length))
;
10
'?' condition is false
312 fw_dma.address = be64toh(fw_dma.address)(__uint64_t)(__builtin_constant_p(fw_dma.address) ? (__uint64_t
)((((__uint64_t)(fw_dma.address) & 0xff) << 56) | (
(__uint64_t)(fw_dma.address) & 0xff00ULL) << 40 | (
(__uint64_t)(fw_dma.address) & 0xff0000ULL) << 24 |
((__uint64_t)(fw_dma.address) & 0xff000000ULL) << 8
| ((__uint64_t)(fw_dma.address) & 0xff00000000ULL) >>
8 | ((__uint64_t)(fw_dma.address) & 0xff0000000000ULL) >>
24 | ((__uint64_t)(fw_dma.address) & 0xff000000000000ULL
) >> 40 | ((__uint64_t)(fw_dma.address) & 0xff00000000000000ULL
) >> 56) : __swap64md(fw_dma.address))
;
11
'?' condition is false
313
314 fw_cfg_handle_dma(&fw_dma);
12
Calling 'fw_cfg_handle_dma'
315
316 /* just write control byte back */
317 data = be32toh(fw_dma.control)(__uint32_t)(__builtin_constant_p(fw_dma.control) ? (__uint32_t
)(((__uint32_t)(fw_dma.control) & 0xff) << 24 | ((__uint32_t
)(fw_dma.control) & 0xff00) << 8 | ((__uint32_t)(fw_dma
.control) & 0xff0000) >> 8 | ((__uint32_t)(fw_dma.control
) & 0xff000000) >> 24) : __swap32md(fw_dma.control)
)
;
318 if (write_mem(fw_cfg_dma_addr, &data, sizeof(data)))
319 break;
320
321 /* done, reset base address */
322 fw_cfg_dma_addr = 0;
323 break;
324 }
325 } else {
326 uint64_t sig = htobe64(FW_CFG_DMA_SIGNATURE)(__uint64_t)(__builtin_constant_p(0x51454d5520434647ULL) ? (__uint64_t
)((((__uint64_t)(0x51454d5520434647ULL) & 0xff) << 56
) | ((__uint64_t)(0x51454d5520434647ULL) & 0xff00ULL) <<
40 | ((__uint64_t)(0x51454d5520434647ULL) & 0xff0000ULL)
<< 24 | ((__uint64_t)(0x51454d5520434647ULL) & 0xff000000ULL
) << 8 | ((__uint64_t)(0x51454d5520434647ULL) & 0xff00000000ULL
) >> 8 | ((__uint64_t)(0x51454d5520434647ULL) & 0xff0000000000ULL
) >> 24 | ((__uint64_t)(0x51454d5520434647ULL) & 0xff000000000000ULL
) >> 40 | ((__uint64_t)(0x51454d5520434647ULL) & 0xff00000000000000ULL
) >> 56) : __swap64md(0x51454d5520434647ULL))
;
327 switch (vei->vei.vei_port) {
328 case FW_CFG_IO_DMA_ADDR_HIGH0x514:
329 set_return_data(vei, sig >> 32);
330 break;
331 case FW_CFG_IO_DMA_ADDR_LOW0x518:
332 set_return_data(vei, sig & 0xffffffff);
333 break;
334 }
335 }
336 return 0xFF;
337}
338
339static uint16_t file_id = FW_CFG_FILE_FIRST0x0020;
340
341struct fw_cfg_file_entry {
342 TAILQ_ENTRY(fw_cfg_file_entry)struct { struct fw_cfg_file_entry *tqe_next; struct fw_cfg_file_entry
**tqe_prev; }
entry;
343 struct fw_cfg_file file;
344 void *data;
345};
346
347TAILQ_HEAD(, fw_cfg_file_entry)struct { struct fw_cfg_file_entry *tqh_first; struct fw_cfg_file_entry
**tqh_last; }
fw_cfg_files =
348 TAILQ_HEAD_INITIALIZER(fw_cfg_files){ ((void *)0), &(fw_cfg_files).tqh_first };
349
350static struct fw_cfg_file_entry *
351fw_cfg_lookup_file(const char *name)
352{
353 struct fw_cfg_file_entry *f;
354
355 TAILQ_FOREACH(f, &fw_cfg_files, entry)for((f) = ((&fw_cfg_files)->tqh_first); (f) != ((void *
)0); (f) = ((f)->entry.tqe_next))
{
356 if (strcmp(name, f->file.name) == 0)
357 return f;
358 }
359 return NULL((void *)0);
360}
361
362void
363fw_cfg_add_file(const char *name, const void *data, size_t len)
364{
365 struct fw_cfg_file_entry *f;
366
367 if (fw_cfg_lookup_file(name))
368 fatalx("%s: fw_cfg: file %s exists", __progname, name);
369
370 if ((f = calloc(sizeof(*f), 1)) == NULL((void *)0))
371 fatal("%s", __func__);
372
373 if ((f->data = malloc(len)) == NULL((void *)0))
374 fatal("%s", __func__);
375
376 if (strlcpy(f->file.name, name, sizeof(f->file.name)) >=
377 sizeof(f->file.name))
378 fatalx("%s: fw_cfg: file name too long", __progname);
379
380 f->file.size = htobe32(len)(__uint32_t)(__builtin_constant_p(len) ? (__uint32_t)(((__uint32_t
)(len) & 0xff) << 24 | ((__uint32_t)(len) & 0xff00
) << 8 | ((__uint32_t)(len) & 0xff0000) >> 8 |
((__uint32_t)(len) & 0xff000000) >> 24) : __swap32md
(len))
;
381 f->file.selector = htobe16(file_id++)(__uint16_t)(__builtin_constant_p(file_id++) ? (__uint16_t)((
(__uint16_t)(file_id++) & 0xffU) << 8 | ((__uint16_t
)(file_id++) & 0xff00U) >> 8) : __swap16md(file_id++
))
;
382 memcpy(f->data, data, len);
383
384 TAILQ_INSERT_TAIL(&fw_cfg_files, f, entry)do { (f)->entry.tqe_next = ((void *)0); (f)->entry.tqe_prev
= (&fw_cfg_files)->tqh_last; *(&fw_cfg_files)->
tqh_last = (f); (&fw_cfg_files)->tqh_last = &(f)->
entry.tqe_next; } while (0)
;
385}
386
387static int
388fw_cfg_select_file(uint16_t id)
389{
390 struct fw_cfg_file_entry *f;
391
392 id = htobe16(id)(__uint16_t)(__builtin_constant_p(id) ? (__uint16_t)(((__uint16_t
)(id) & 0xffU) << 8 | ((__uint16_t)(id) & 0xff00U
) >> 8) : __swap16md(id))
;
393 TAILQ_FOREACH(f, &fw_cfg_files, entry)for((f) = ((&fw_cfg_files)->tqh_first); (f) != ((void *
)0); (f) = ((f)->entry.tqe_next))
394 if (f->file.selector == id) {
395 size_t size = be32toh(f->file.size)(__uint32_t)(__builtin_constant_p(f->file.size) ? (__uint32_t
)(((__uint32_t)(f->file.size) & 0xff) << 24 | ((
__uint32_t)(f->file.size) & 0xff00) << 8 | ((__uint32_t
)(f->file.size) & 0xff0000) >> 8 | ((__uint32_t)
(f->file.size) & 0xff000000) >> 24) : __swap32md
(f->file.size))
;
396 fw_cfg_set_state(f->data, size);
397 log_debug("%s: accessing file %s", __func__,
398 f->file.name);
399 return 1;
400 }
401 return 0;
402}
403
404static void
405fw_cfg_file_dir(void)
406{
407 struct fw_cfg_file_entry *f;
408 struct fw_cfg_file *fp;
409 uint32_t count = 0;
410 uint32_t *data;
411 size_t size;
412
413 TAILQ_FOREACH(f, &fw_cfg_files, entry)for((f) = ((&fw_cfg_files)->tqh_first); (f) != ((void *
)0); (f) = ((f)->entry.tqe_next))
18
Assuming 'f' is equal to null
19
Loop condition is false. Execution continues on line 416
414 count++;
415
416 size = sizeof(count) + count * sizeof(struct fw_cfg_file);
417 if ((data = malloc(size)) == NULL((void *)0))
20
Memory is allocated
21
Assuming the condition is false
22
Taking false branch
418 fatal("%s", __func__);
419 *data = htobe32(count)(__uint32_t)(__builtin_constant_p(count) ? (__uint32_t)(((__uint32_t
)(count) & 0xff) << 24 | ((__uint32_t)(count) &
0xff00) << 8 | ((__uint32_t)(count) & 0xff0000) >>
8 | ((__uint32_t)(count) & 0xff000000) >> 24) : __swap32md
(count))
;
23
'?' condition is false
420 fp = (struct fw_cfg_file *)(data + 1);
421
422 log_debug("%s: file directory with %d files", __func__, count);
423 TAILQ_FOREACH(f, &fw_cfg_files, entry)for((f) = ((&fw_cfg_files)->tqh_first); (f) != ((void *
)0); (f) = ((f)->entry.tqe_next))
{
24
Assuming 'f' is equal to null
25
Loop condition is false. Execution continues on line 432
424 log_debug(" %6dB %04x %s", be32toh(f->file.size)(__uint32_t)(__builtin_constant_p(f->file.size) ? (__uint32_t
)(((__uint32_t)(f->file.size) & 0xff) << 24 | ((
__uint32_t)(f->file.size) & 0xff00) << 8 | ((__uint32_t
)(f->file.size) & 0xff0000) >> 8 | ((__uint32_t)
(f->file.size) & 0xff000000) >> 24) : __swap32md
(f->file.size))
,
425 be16toh(f->file.selector)(__uint16_t)(__builtin_constant_p(f->file.selector) ? (__uint16_t
)(((__uint16_t)(f->file.selector) & 0xffU) << 8 |
((__uint16_t)(f->file.selector) & 0xff00U) >> 8
) : __swap16md(f->file.selector))
, f->file.name);
426 memcpy(fp, &f->file, sizeof(f->file));
427 fp++;
428 }
429
430 /* XXX should sort by name but SeaBIOS does not care */
431
432 fw_cfg_set_state(data, size);
433}
26
Potential leak of memory pointed to by 'data'