Bug Summary

File:.build-ci/../discoverd/tests/test-config.c
Warning:line 59, column 16
Access to field 'nbft' results in a dereference of a null pointer (loaded from variable 'cfg')

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -O3 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name test-config.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=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/__w/nvme-cli/nvme-cli/.build-ci -fcoverage-compilation-dir=/__w/nvme-cli/nvme-cli/.build-ci -resource-dir /usr/bin/../lib/clang/22 -include /__w/nvme-cli/nvme-cli/.build-ci/nvme-config.h -I discoverd/tests/test-config.p -I discoverd/tests -I ../discoverd/tests -I ../discoverd/src -I ccan -I ../ccan -I . -I .. -I libnvme/src -I ../libnvme/src -D _FILE_OFFSET_BITS=64 -D _GNU_SOURCE -U NDEBUG -internal-isystem /usr/bin/../lib/clang/22/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/16/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -std=gnu11 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fcolor-diagnostics -vectorize-loops -vectorize-slp -analyzer-opt-analyze-headers -analyzer-output=html -faddrsig -fdwarf2-cfi-asm -o /__w/nvme-cli/nvme-cli/.build-ci/scan-results/2026-10-24-125112-639-1 -x c ../discoverd/tests/test-config.c
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * This file is part of nvme-cli.
4 * Copyright (c) 2026 Dell Technologies Inc. or its subsidiaries.
5 *
6 * Authors: Martin Belanger <martin.belanger@dell.com>
7 */
8
9#include <stdbool.h>
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13#include <unistd.h>
14
15#include <shared/time-util.h>
16
17#include "config.h"
18
19static bool_Bool check(bool_Bool cond, const char *what)
20{
21 printf(" - %s [%s]\n", what, cond ? "PASS" : "FAIL");
22 return cond;
23}
24
25/* Write @text to a temp file and load it as a discoverd config. */
26static struct discoverd_config *load_text(const char *text)
27{
28 char path[] = "/tmp/nvme-discoverd-config-XXXXXX";
29 struct discoverd_config *cfg;
30 size_t len = strlen(text);
31 int fd;
32
33 fd = mkstemp(path);
34 if (fd < 0) {
35 fprintf(stderrstderr, "mkstemp: failed\n");
36 exit(EXIT_FAILURE1);
37 }
38 if (write(fd, text, len) != (ssize_t)len) {
39 fprintf(stderrstderr, "write: failed\n");
40 exit(EXIT_FAILURE1);
41 }
42 close(fd);
43
44 cfg = config_load(path);
45 unlink(path);
46
47 return cfg;
48}
49
50static bool_Bool test_missing_file_defaults(void)
51{
52 struct discoverd_config *cfg;
53 bool_Bool pass = true1;
54
55 printf("test_missing_file_defaults:\n");
56
57 cfg = config_load("/nonexistent/nvme-discoverd.conf");
2
Value assigned to 'cfg'
58 pass &= check(cfg != NULL((void*)0), "config_load never returns NULL");
3
Assuming 'cfg' is equal to NULL
59 pass &= check(cfg->nbft, "nbft defaults true");
4
Access to field 'nbft' results in a dereference of a null pointer (loaded from variable 'cfg')
60 pass &= check(cfg->epcsd_poll_interval_minutes == 15,
61 "epcsd-poll-interval-minutes defaults 15");
62 pass &= check(cfg->fc_kickstart_interval_minutes == 0,
63 "fc-kickstart-interval-minutes defaults 0");
64 pass &= check(cfg->dc_giveup_timeout_usec == 72 * SHR_USEC_PER_HOUR(60UL * (60UL * 1000000UL)),
65 "dc-giveup-timeout defaults 72hours");
66 pass &= check(!cfg->zeroconf, "zeroconf defaults false");
67
68 config_free(cfg);
69
70 return pass;
71}
72
73static bool_Bool test_discovery_section_parsed(void)
74{
75 struct discoverd_config *cfg;
76 bool_Bool pass = true1;
77
78 printf("test_discovery_section_parsed:\n");
79
80 cfg = load_text("[Global]\n"
81 "nbft = false\n"
82 "\n"
83 "[Discovery]\n"
84 "epcsd-poll-interval-minutes = 30\n"
85 "fc-kickstart-interval-minutes = 5\n"
86 "dc-giveup-timeout = 2hours\n"
87 "zeroconf = true\n");
88 pass &= check(!cfg->nbft, "[Global] nbft parses");
89 pass &= check(cfg->epcsd_poll_interval_minutes == 30,
90 "[Discovery] epcsd-poll-interval-minutes parses");
91 pass &= check(cfg->fc_kickstart_interval_minutes == 5,
92 "[Discovery] fc-kickstart-interval-minutes parses");
93 pass &= check(cfg->dc_giveup_timeout_usec == 2 * SHR_USEC_PER_HOUR(60UL * (60UL * 1000000UL)),
94 "[Discovery] dc-giveup-timeout parses");
95 pass &= check(cfg->zeroconf, "[Discovery] zeroconf parses");
96
97 config_free(cfg);
98
99 return pass;
100}
101
102static bool_Bool test_discovery_key_in_global_ignored(void)
103{
104 struct discoverd_config *cfg;
105 bool_Bool pass = true1;
106
107 printf("test_discovery_key_in_global_ignored:\n");
108
109 cfg = load_text("[Global]\n"
110 "epcsd-poll-interval-minutes = 30\n");
111 pass &= check(cfg->epcsd_poll_interval_minutes == 15,
112 "epcsd-poll-interval-minutes in [Global] ignored");
113
114 config_free(cfg);
115
116 return pass;
117}
118
119static bool_Bool test_global_key_in_discovery_ignored(void)
120{
121 struct discoverd_config *cfg;
122 bool_Bool pass = true1;
123
124 printf("test_global_key_in_discovery_ignored:\n");
125
126 cfg = load_text("[Discovery]\n"
127 "nbft = false\n");
128 pass &= check(cfg->nbft, "nbft in [Discovery] ignored");
129
130 config_free(cfg);
131
132 return pass;
133}
134
135static bool_Bool test_invalid_and_unknown_ignored(void)
136{
137 struct discoverd_config *cfg;
138 bool_Bool pass = true1;
139
140 printf("test_invalid_and_unknown_ignored:\n");
141
142 cfg = load_text("[Discovery]\n"
143 "fc-kickstart-interval-minutes = -1\n"
144 "bogus-key = 1\n"
145 "epcsd-poll-interval-minutes = 30\n"
146 "\n"
147 "[Bogus Section]\n"
148 "epcsd-poll-interval-minutes = 9\n");
149 pass &= check(cfg->fc_kickstart_interval_minutes == 0,
150 "invalid value ignored, default kept");
151 pass &= check(cfg->epcsd_poll_interval_minutes == 30,
152 "valid keys apply despite invalid siblings");
153
154 config_free(cfg);
155
156 return pass;
157}
158
159static bool_Bool test_epcsd_poll_interval_zero_ignored(void)
160{
161 struct discoverd_config *cfg;
162 bool_Bool pass = true1;
163
164 printf("test_epcsd_poll_interval_zero_ignored:\n");
165
166 cfg = load_text("[Discovery]\n"
167 "epcsd-poll-interval-minutes = 0\n");
168 pass &= check(cfg->epcsd_poll_interval_minutes == 15,
169 "0 rejected, default kept");
170
171 config_free(cfg);
172
173 return pass;
174}
175
176int main(void)
177{
178 bool_Bool pass = true1;
179
180 pass &= test_missing_file_defaults();
1
Calling 'test_missing_file_defaults'
181 pass &= test_discovery_section_parsed();
182 pass &= test_discovery_key_in_global_ignored();
183 pass &= test_global_key_in_discovery_ignored();
184 pass &= test_invalid_and_unknown_ignored();
185 pass &= test_epcsd_poll_interval_zero_ignored();
186
187 fflush(stdoutstdout);
188 exit(pass ? EXIT_SUCCESS0 : EXIT_FAILURE1);
189}