Bug Summary

File:.build-ci/../libnvme/src/nvme/util-fabrics.c
Warning:line 66, column 4
Opened stream never closed. Potential resource leak

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 util-fabrics.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 -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 libnvme/src/libnvme3.so.1.0.0.p -I libnvme/src -I ../libnvme/src -I ccan -I ../ccan -I . -I .. -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 -fvisibility=hidden -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-09-23-073103-589-1 -x c ../libnvme/src/nvme/util-fabrics.c
1// SPDX-License-Identifier: LGPL-2.1-or-later
2/*
3 * This file is part of libnvme.
4 * Copyright (c) 2026, Dell Technologies Inc. or its subsidiaries.
5 *
6 * Authors: Martin Belanger <Martin.Belanger@dell.com>
7 */
8
9#include <limits.h>
10#include <string.h>
11#include <unistd.h>
12
13#include <ccan/endian/endian.h>
14#include <ccan/minmax/minmax.h>
15
16#include <shared/compiler-attributes-util.h>
17
18#include <libnvme.h>
19
20#include <shared/string-util.h>
21
22#include "cleanup-linux.h"
23#include "private-fabrics.h"
24#include "util.h"
25
26__shr_public__attribute__((visibility("default"))) struct nvmf_ext_attr *libnvmf_exat_ptr_next(
27 struct nvmf_ext_attr *p)
28{
29 __u16 size = libnvmf_exat_size(le16_to_cpu(p->exatlen));
30
31 return (struct nvmf_ext_attr *)((uintptr_t)p + (ptrdiff_t)size);
32}
33
34const struct ifaddrs *libnvmf_getifaddrs(struct libnvme_global_ctx *ctx)
35{
36 if (!ctx->ifaddrs_cache) {
37 struct ifaddrs *p;
38
39 if (!getifaddrs(&p))
40 ctx->ifaddrs_cache = p;
41 }
42
43 return ctx->ifaddrs_cache;
44}
45
46/**
47 * read_file - read contents of file into @buffer.
48 * @fname: File name
49 * @buffer: Where to save file's contents
50 * @bufsz: Size of @buffer. On success, @bufsz gets decremented by the
51 * number of characters that were writtent to @buffer.
52 *
53 * Return: The number of characters read. If the file cannot be opened or
54 * nothing is read from the file, then this function returns 0.
55 */
56static size_t read_file(const char * fname, char *buffer, size_t *bufsz)
57{
58 char *p;
59 __cleanup_file__attribute__((cleanup(shr_cleanup_file))) FILE *file = NULL((void*)0);
60 size_t len;
61
62 file = fopen(fname, "re");
2
Stream opened here
3
Assuming that 'fopen' is successful
63 if (!file
3.1
'file' is non-null
)
4
Taking false branch
64 return 0;
65
66 p = fgets(buffer, *bufsz, file);
5
Assuming that the 3rd argument to 'fgets' is not NULL
6
Opened stream never closed. Potential resource leak
67
68 if (!p)
69 return 0;
70
71 /* Strip unwanted trailing chars */
72 len = strcspn(buffer, " \t\n\r");
73 *bufsz -= len;
74
75 return len;
76}
77
78static size_t copy_value(char *buf, size_t buflen, const char *value)
79{
80 size_t val_len;
81
82 memset(buf, 0, buflen);
83
84 /* Remove leading " */
85 if (value[0] == '"')
86 value++;
87
88 /* Remove trailing " */
89 val_len = strcspn(value, "\"");
90
91 memcpy(buf, value, min(val_len, buflen-1)({ typeof(val_len) _a = (val_len); typeof(buflen-1) _b = (buflen
-1); do { } while (0); _a < _b ? _a : _b; })
);
92
93 return val_len;
94}
95
96size_t libnvmf_get_entity_name(char *buffer, size_t bufsz)
97{
98 size_t len = !gethostname(buffer, bufsz) ? strlen(buffer) : 0;
99
100 /* Fill the rest of buffer with zeros */
101 memset(&buffer[len], '\0', bufsz-len);
102
103 return len;
104}
105
106size_t libnvmf_get_entity_version(char *buffer, size_t bufsz)
107{
108 __cleanup_file__attribute__((cleanup(shr_cleanup_file))) FILE *file = NULL((void*)0);
109 size_t num_bytes = 0;
110
111 /* /proc/sys/kernel/ostype typically contains the string "Linux" */
112 num_bytes += read_file("/proc/sys/kernel/ostype",
1
Calling 'read_file'
113 &buffer[num_bytes], &bufsz);
114
115 /* /proc/sys/kernel/osrelease contains the Linux
116 * version (e.g. 5.8.0-63-generic)
117 */
118 if (bufsz) {
119 buffer[num_bytes++] = ' '; /* Append a space */
120 bufsz--;
121 }
122 num_bytes += read_file("/proc/sys/kernel/osrelease",
123 &buffer[num_bytes], &bufsz);
124
125 /* /etc/os-release contains Key-Value pairs. We only care about the key
126 * PRETTY_NAME, which contains the Distro's version. For example:
127 * "SUSE Linux Enterprise Server 15 SP4", "Ubuntu 20.04.3 LTS", or
128 * "Fedora Linux 35 (Server Edition)"
129 */
130 file = fopen("/etc/os-release", "re");
131 if (file) {
132 char name[64] = {0};
133 size_t name_len = 0;
134 char ver_id[64] = {0};
135 size_t ver_id_len = 0;
136 char line[LINE_MAX2048];
137 char *p;
138 char *s;
139
140 /* Read key-value pairs one line at a time */
141 while ((!name_len || !ver_id_len) &&
142 (p = fgets(line, sizeof(line), file)) != NULL((void*)0)) {
143 /* Clean up string by removing leading/trailing blanks
144 * and new line characters. Also eliminate trailing
145 * comments, if any.
146 */
147 p = shr_kv_strip(p);
148
149 /* Empty string? */
150 if (*p == '\0')
151 continue;
152
153 s = shr_kv_keymatch(p, "NAME");
154 if (s)
155 name_len = copy_value(name, sizeof(name), s);
156
157 s = shr_kv_keymatch(p, "VERSION_ID");
158 if (s)
159 ver_id_len = copy_value(ver_id, sizeof(ver_id), s);
160 }
161
162 if (name_len) {
163 /* Append a space */
164 if (bufsz) {
165 buffer[num_bytes++] = ' ';
166 bufsz--;
167 }
168 name_len = min(name_len, bufsz)({ typeof(name_len) _a = (name_len); typeof(bufsz) _b = (bufsz
); do { } while (0); _a < _b ? _a : _b; })
;
169 memcpy(&buffer[num_bytes], name, name_len);
170 bufsz -= name_len;
171 num_bytes += name_len;
172 }
173
174 if (ver_id_len) {
175 /* Append a space */
176 if (bufsz) {
177 buffer[num_bytes++] = ' ';
178 bufsz--;
179 }
180 ver_id_len = min(ver_id_len, bufsz)({ typeof(ver_id_len) _a = (ver_id_len); typeof(bufsz) _b = (
bufsz); do { } while (0); _a < _b ? _a : _b; })
;
181 memcpy(&buffer[num_bytes], ver_id, ver_id_len);
182 bufsz -= ver_id_len;
183 num_bytes += ver_id_len;
184 }
185 }
186
187 /* Fill the rest of buffer with zeros */
188 memset(&buffer[num_bytes], '\0', bufsz);
189
190 return num_bytes;
191}