Bug Summary

File:.build-ci/../plugins/huawei/huawei-nvme.c
Warning:line 157, column 7
Null passed to a callee that requires a non-null 1st parameter

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 huawei-nvme.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 nvme.p -I . -I .. -I src -I ../src -I ccan -I ../ccan -I libnvme/src -I ../libnvme/src -I shared -I ../shared -I /usr/include/json-c -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=gnu99 -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-08-08-045408-589-1 -x c ../plugins/huawei/huawei-nvme.c
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Copyright (c) 2017-2019 Huawei Corporation or its affiliates.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * Author: Zou Ming<zouming.zouming@huawei.com>,
16 * Yang Feng <philip.yang@huawei.com>
17 */
18#include <stdio.h>
19#include <string.h>
20#include <stdlib.h>
21#include <inttypes.h>
22#include <errno(*__errno_location ()).h>
23#include <limits.h>
24#include <fcntl.h>
25#include <unistd.h>
26#include <dirent.h>
27
28#include <sys/stat.h>
29
30#include <libnvme.h>
31
32#include "common.h"
33#include "nvme-cmds.h"
34#include "nvme.h"
35#include "nvme-print.h"
36#include "plugin.h"
37
38#include "suffix-util.h"
39
40#define CREATE_CMD
41#include "huawei-nvme.h"
42
43#define HW_SSD_PCI_VENDOR_ID0x19E5 0x19E5
44#define ARRAY_NAME_LEN80 80
45#define NS_NAME_LEN40 40
46
47#define MIN_ARRAY_NAME_LEN16 16
48#define MIN_NS_NAME_LEN16 16
49
50struct huawei_list_item {
51 char node[1024];
52 struct nvme_id_ctrl ctrl;
53 unsigned int nsid;
54 struct nvme_id_ns ns;
55 unsigned int block;
56 char ns_name[NS_NAME_LEN40];
57 char array_name[ARRAY_NAME_LEN80];
58 bool_Bool huawei_device;
59};
60
61struct huawei_list_element_len {
62 unsigned int node;
63 unsigned int ns_name;
64 unsigned int nguid;
65 unsigned int ns_id;
66 unsigned int usage;
67 unsigned int array_name;
68};
69
70static int huawei_get_nvme_info(struct libnvme_transport_handle *hdl,
71 struct huawei_list_item *item, const char *node)
72{
73 struct stat nvme_stat_info;
74 int err;
75 int len;
76
77 memset(item, 0, sizeof(*item));
78
79 err = nvme_identify_ctrl(hdl, &item->ctrl);
80 if (err)
81 return err;
82
83 /*identify huawei device*/
84 if (strstr(item->ctrl.mn, "Huawei")_Generic (0 ? (item->ctrl.mn) : (void *) 1, const void *: (
const char *) (strstr (item->ctrl.mn, "Huawei")), default:
strstr (item->ctrl.mn, "Huawei"))
== NULL((void*)0) &&
85 le16_to_cpu(item->ctrl.vid) != HW_SSD_PCI_VENDOR_ID0x19E5) {
86 item->huawei_device = false0;
87 return 0;
88 }
89
90 item->huawei_device = true1;
91 err = libnvme_get_nsid(hdl, &item->nsid);
92 err = nvme_identify_ns(hdl, item->nsid, &item->ns);
93 if (err)
94 return err;
95
96 err = fstat(libnvme_transport_handle_get_fd(hdl), &nvme_stat_info);
97 if (err < 0)
98 return err;
99
100 strncpy(item->node, node, sizeof(item->node));
101 item->node[sizeof(item->node) - 1] = '\0';
102 item->block = S_ISBLK(nvme_stat_info.st_mode)((((nvme_stat_info.st_mode)) & 0170000) == (0060000));
103
104 if (item->ns.vs[0] == 0) {
105 len = snprintf(item->ns_name, NS_NAME_LEN40, "%s", "----");
106 if (len < 0)
107 return -EINVAL22;
108 } else {
109 memcpy(item->ns_name, item->ns.vs, NS_NAME_LEN40);
110 item->ns_name[NS_NAME_LEN40 - 1] = '\0';
111 }
112
113 if (item->ctrl.vs[0] == 0) {
114 len = snprintf(item->array_name, ARRAY_NAME_LEN80, "%s", "----");
115 if (len < 0)
116 return -EINVAL22;
117 } else {
118 memcpy(item->array_name, item->ctrl.vs, ARRAY_NAME_LEN80);
119 item->array_name[ARRAY_NAME_LEN80 - 1] = '\0';
120 }
121 return 0;
122}
123
124#ifdef CONFIG_JSONC
125static void format(char *formatter, size_t fmt_sz, char *tofmt, size_t tofmtsz)
126{
127 fmt_sz = snprintf(formatter, fmt_sz, "%-*.*s", (int)tofmtsz, (int)tofmtsz, tofmt);
128
129 /* trim() the obnoxious trailing white lines */
130 while (fmt_sz) {
131 if (formatter[fmt_sz - 1] != ' ' && formatter[fmt_sz - 1] != '\0') {
132 formatter[fmt_sz] = '\0';
133 break;
134 }
135 fmt_sz--;
136 }
137}
138
139static void huawei_json_print_list_items(struct huawei_list_item *list_items,
140 unsigned int len)
141{
142 struct json_object *root;
143 struct json_object *devices;
144 struct json_object *device_attrs;
145 char formatter[128] = { 0 };
146 int index, i = 0;
147
148 root = json_create_object()json_object_new_object();
149 devices = json_create_array()json_object_new_array();
150 for (i = 0; i < len; i++) {
1
Assuming 'i' is < 'len'
2
Loop condition is true. Entering loop body
151 device_attrs = json_create_object()json_object_new_object();
152
153 json_object_add_value_string(device_attrs,
154 "DevicePath",
155 list_items[i].node);
156
157 if (sscanf(list_items[i].node, "/dev/nvme%d", &index) == 1)
3
Null passed to a callee that requires a non-null 1st parameter
158 json_object_add_value_int(device_attrs,json_object_object_add(device_attrs, "Index", json_object_new_int
(index))
159 "Index",json_object_object_add(device_attrs, "Index", json_object_new_int
(index))
160 index)json_object_object_add(device_attrs, "Index", json_object_new_int
(index))
;
161
162 format(formatter, sizeof(formatter),
163 list_items[i].ns_name,
164 sizeof(list_items[i].ns_name));
165
166 json_object_add_value_string(device_attrs,
167 "NS Name",
168 formatter);
169
170 format(formatter, sizeof(formatter),
171 list_items[i].array_name,
172 sizeof(list_items[i].array_name));
173
174 json_object_add_value_string(device_attrs,
175 "Array Name",
176 formatter);
177
178 json_array_add_value_object(devices, device_attrs)json_object_array_add(devices, device_attrs);
179 }
180 json_object_add_value_array(root, "Devices", devices)json_object_object_add(root, "Devices", devices);
181 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
182 printf("\n");
183 json_free_object(root)json_object_put(root);
184}
185#endif /* CONFIG_JSONC */
186
187static void huawei_print_list_head(struct huawei_list_element_len element_len)
188{
189 char dash[128];
190 int i;
191
192 for (i = 0; i < 128; i++)
193 dash[i] = '-';
194 dash[127] = '\0';
195
196 printf("%-*.*s %-*.*s %-*.*s %-*.*s %-*.*s %-*.*s\n",
197 element_len.node, element_len.node, "Node",
198 element_len.ns_name, element_len.ns_name, "NS Name",
199 element_len.nguid, element_len.nguid, "Nguid",
200 element_len.ns_id, element_len.ns_id, "NS ID",
201 element_len.usage, element_len.usage, "Usage",
202 element_len.array_name, element_len.array_name, "Array Name");
203
204 printf("%-.*s %-.*s %-.*s %-.*s %-.*s %-.*s\n",
205 element_len.node, dash, element_len.ns_name, dash,
206 element_len.nguid, dash, element_len.ns_id, dash,
207 element_len.usage, dash, element_len.array_name, dash);
208}
209
210static void huawei_print_list_item(struct huawei_list_item *list_item,
211 struct huawei_list_element_len element_len)
212{
213 __u8 lba_index;
214
215 nvme_id_ns_flbas_to_lbaf_inuse(list_item->ns.flbas, &lba_index);
216 unsigned long long lba = 1ULL << list_item->ns.lbaf[lba_index].ds;
217 double nsze = le64_to_cpu(list_item->ns.nsze) * lba;
218 double nuse = le64_to_cpu(list_item->ns.nuse) * lba;
219
220 const char *s_suffix = shr_suffix_si_get(&nsze);
221 const char *u_suffix = shr_suffix_si_get(&nuse);
222
223 char usage[128];
224 char nguid_buf[2 * sizeof(list_item->ns.nguid) + 1];
225 char *nguid = nguid_buf;
226 int i;
227
228 sprintf(usage, "%6.2f %2sB / %6.2f %2sB", nuse, u_suffix, nsze, s_suffix);
229
230 memset(nguid, 0, sizeof(nguid_buf));
231 for (i = 0; i < sizeof(list_item->ns.nguid); i++)
232 nguid += sprintf(nguid, "%02x", list_item->ns.nguid[i]);
233
234 printf("%-*.*s %-*.*s %-*.*s %-*d %-*.*s %-*.*s\n",
235 element_len.node, element_len.node, list_item->node,
236 element_len.ns_name, element_len.ns_name, list_item->ns_name,
237 element_len.nguid, element_len.nguid, nguid_buf,
238 element_len.ns_id, list_item->nsid,
239 element_len.usage, element_len.usage, usage,
240 element_len.array_name, element_len.array_name,
241 list_item->array_name);
242
243}
244
245static unsigned int choose_len(unsigned int old_len, unsigned int cur_len, unsigned int default_len)
246{
247 unsigned int temp_len;
248
249 temp_len = (cur_len > default_len) ? cur_len : default_len;
250 if (temp_len > old_len)
251 return temp_len;
252 return old_len;
253}
254
255static unsigned int huawei_get_ns_len(struct huawei_list_item *list_items, unsigned int len,
256 unsigned int default_len)
257{
258 int i;
259 unsigned int min_len = default_len;
260
261 for (i = 0 ; i < len ; i++)
262 min_len = choose_len(min_len, strlen(list_items->ns_name), default_len);
263
264 return min_len;
265}
266
267static int huawei_get_array_len(struct huawei_list_item *list_items, unsigned int len,
268 unsigned int default_len)
269{
270 int i;
271 int min_len = default_len;
272
273 for (i = 0 ; i < len ; i++)
274 min_len = choose_len(min_len, strlen(list_items->array_name), default_len);
275
276 return min_len;
277}
278
279static void huawei_print_list_items(struct huawei_list_item *list_items, unsigned int len)
280{
281 unsigned int i;
282 struct huawei_list_element_len element_len;
283
284 element_len.node = 16;
285 element_len.nguid = 2 * sizeof(list_items->ns.nguid) + 1;
286 element_len.ns_id = 9;
287 element_len.usage = 26;
288 element_len.ns_name = huawei_get_ns_len(list_items, len, MIN_NS_NAME_LEN16);
289 element_len.array_name = huawei_get_array_len(list_items, len, MIN_ARRAY_NAME_LEN16);
290
291 huawei_print_list_head(element_len);
292
293 for (i = 0 ; i < len ; i++)
294 huawei_print_list_item(&list_items[i], element_len);
295}
296
297static int filter_namespace(const struct dirent *d)
298{
299 int i, n;
300
301 if (d->d_name[0] == '.')
302 return 0;
303
304 if (strstr(d->d_name, "nvme")_Generic (0 ? (d->d_name) : (void *) 1, const void *: (const
char *) (strstr (d->d_name, "nvme")), default: strstr (d->
d_name, "nvme"))
)
305 if (sscanf(d->d_name, "nvme%dn%d", &i, &n) == 2)
306 return 1;
307
308 return 0;
309}
310
311static int huawei_list(int argc, char **argv, struct command *acmd,
312 struct plugin *plugin)
313{
314 const char *desc = "Retrieve basic information for the given huawei device";
315 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
316 char path[264];
317 struct dirent **devices;
318 struct huawei_list_item *list_items;
319 unsigned int i, n;
320 unsigned int huawei_num = 0;
321 nvme_print_flags_t fmt;
322 int ret;
323
324 NVME_ARGS(opts)nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0
, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT
, &nvme_args.verbose, 0, "Increase output verbosity", 0, }
, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0,
"suppress output messages, overwrites verbose mode", 0, }, {
"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary", 0, }, {"timeout", 0
, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, {"set-options", 0
, "KEY=VALUE", CFG_STRING, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
;
325
326 ret = parse_args(argc, argv, desc, opts);
327 if (ret)
328 return ret;
329
330 ret = validate_output_format(nvme_args.output_format, &fmt);
331 if (ret < 0 || (fmt != JSON && fmt != NORMAL))
332 return ret;
333
334 ret = nvme_create_global_ctx(&ctx);
335 if (ret)
336 return ret;
337
338 n = scandir("/dev", &devices, filter_namespace, alphasort);
339 if (n <= 0)
340 return n;
341
342 list_items = calloc(n, sizeof(*list_items));
343 if (!list_items) {
344 nvme_show_error("can not allocate controller list payload")nvme_show_message(1, "can not allocate controller list payload"
)
;
345 ret = ENOMEM12;
346 goto out_free_devices;
347 }
348
349 for (i = 0; i < n; i++) {
350 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
351
352 snprintf(path, sizeof(path), "/dev/%s", devices[i]->d_name);
353 ret = libnvme_open(ctx, path, &hdl);
354 if (ret) {
355 nvme_show_error("Cannot open device %s: %s",nvme_show_message(1, "Cannot open device %s: %s", path, libnvme_strerror
(-ret))
356 path, libnvme_strerror(-ret))nvme_show_message(1, "Cannot open device %s: %s", path, libnvme_strerror
(-ret))
;
357 continue;
358 }
359 ret = huawei_get_nvme_info(hdl, &list_items[huawei_num], path);
360 if (ret)
361 goto out_free_list_items;
362
363 if (list_items[huawei_num].huawei_device == true1)
364 huawei_num++;
365 }
366
367 if (huawei_num > 0) {
368#ifdef CONFIG_JSONC
369 if (fmt == JSON)
370 huawei_json_print_list_items(list_items, huawei_num);
371 else
372#endif /* CONFIG_JSONC */
373 huawei_print_list_items(list_items, huawei_num);
374 }
375out_free_list_items:
376 free(list_items);
377out_free_devices:
378 for (i = 0; i < n; i++)
379 free(devices[i]);
380 free(devices);
381
382 return ret;
383}
384
385static void huawei_do_id_ctrl(__u8 *vs, struct json_object *root)
386{
387 char array_name[ARRAY_NAME_LEN80 + 1] = {0};
388
389 memcpy(array_name, vs, ARRAY_NAME_LEN80);
390 if (root)
391 json_object_add_value_string(root, "array name", strlen(array_name) > 1 ? array_name : "NULL");
392 else
393 printf("array name : %s\n", strlen(array_name) > 1 ? array_name : "NULL");
394}
395
396static int huawei_id_ctrl(int argc, char **argv, struct command *acmd, struct plugin *plugin)
397{
398 return __id_ctrl(argc, argv, acmd, plugin, huawei_do_id_ctrl);
399}