Bug Summary

File:build-scan/../src/libsystemd/sd-path/sd-path.c
Warning:line 624, column 28
Use of zero-allocated memory

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name sd-path.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 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -menable-no-infs -menable-no-nans -menable-unsafe-fp-math -fno-signed-zeros -mreassociate -freciprocal-math -fdenormal-fp-math=preserve-sign,preserve-sign -ffp-contract=fast -fno-rounding-math -ffast-math -ffinite-math-only -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/12.0.0 -include config.h -I src/libsystemd/libsystemd_static.a.p -I src/libsystemd -I ../src/libsystemd -I src/basic -I ../src/basic -I src/shared -I ../src/shared -I src/systemd -I ../src/systemd -I src/journal -I ../src/journal -I src/journal-remote -I ../src/journal-remote -I src/nspawn -I ../src/nspawn -I src/resolve -I ../src/resolve -I src/timesync -I ../src/timesync -I ../src/time-wait-sync -I src/login -I ../src/login -I src/udev -I ../src/udev -I src/libudev -I ../src/libudev -I src/core -I ../src/core -I ../src/libsystemd/sd-bus -I ../src/libsystemd/sd-device -I ../src/libsystemd/sd-hwdb -I ../src/libsystemd/sd-id128 -I ../src/libsystemd/sd-netlink -I ../src/libsystemd/sd-network -I src/libsystemd-network -I ../src/libsystemd-network -I . -I .. -D _FILE_OFFSET_BITS=64 -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/12.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wwrite-strings -Wno-unused-parameter -Wno-missing-field-initializers -Wno-unused-result -Wno-format-signedness -Wno-error=nonnull -std=gnu99 -fconst-strings -fdebug-compilation-dir /home/mrc0mmand/repos/@redhat-plumbers/systemd-rhel8/build-scan -ferror-limit 19 -fvisibility default -stack-protector 2 -fgnuc-version=4.2.1 -fcolor-diagnostics -analyzer-output=html -faddrsig -o /tmp/scan-build-2021-07-16-221226-1465241-1 -x c ../src/libsystemd/sd-path/sd-path.c

../src/libsystemd/sd-path/sd-path.c

1/* SPDX-License-Identifier: LGPL-2.1+ */
2/***
3***/
4
5#include "sd-path.h"
6
7#include "alloc-util.h"
8#include "architecture.h"
9#include "fd-util.h"
10#include "fileio.h"
11#include "fs-util.h"
12#include "missing.h"
13#include "path-util.h"
14#include "string-util.h"
15#include "strv.h"
16#include "user-util.h"
17#include "util.h"
18
19static int from_environment(const char *envname, const char *fallback, const char **ret) {
20 assert(ret)do { if ((__builtin_expect(!!(!(ret)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ret"), "../src/libsystemd/sd-path/sd-path.c"
, 20, __PRETTY_FUNCTION__); } while (0)
;
21
22 if (envname) {
23 const char *e;
24
25 e = secure_getenv(envname);
26 if (e && path_is_absolute(e)) {
27 *ret = e;
28 return 0;
29 }
30 }
31
32 if (fallback) {
33 *ret = fallback;
34 return 0;
35 }
36
37 return -ENXIO6;
38}
39
40static int from_home_dir(const char *envname, const char *suffix, char **buffer, const char **ret) {
41 _cleanup_free___attribute__((cleanup(freep))) char *h = NULL((void*)0);
42 char *cc = NULL((void*)0);
43 int r;
44
45 assert(suffix)do { if ((__builtin_expect(!!(!(suffix)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("suffix"), "../src/libsystemd/sd-path/sd-path.c"
, 45, __PRETTY_FUNCTION__); } while (0)
;
46 assert(buffer)do { if ((__builtin_expect(!!(!(buffer)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("buffer"), "../src/libsystemd/sd-path/sd-path.c"
, 46, __PRETTY_FUNCTION__); } while (0)
;
47 assert(ret)do { if ((__builtin_expect(!!(!(ret)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ret"), "../src/libsystemd/sd-path/sd-path.c"
, 47, __PRETTY_FUNCTION__); } while (0)
;
48
49 if (envname) {
50 const char *e = NULL((void*)0);
51
52 e = secure_getenv(envname);
53 if (e && path_is_absolute(e)) {
54 *ret = e;
55 return 0;
56 }
57 }
58
59 r = get_home_dir(&h);
60 if (r < 0)
61 return r;
62
63 if (endswith(h, "/"))
64 cc = strappend(h, suffix);
65 else
66 cc = strjoin(h, "/", suffix)strjoin_real((h), "/", suffix, ((void*)0));
67 if (!cc)
68 return -ENOMEM12;
69
70 *buffer = cc;
71 *ret = cc;
72 return 0;
73}
74
75static int from_user_dir(const char *field, char **buffer, const char **ret) {
76 _cleanup_fclose___attribute__((cleanup(fclosep))) FILE *f = NULL((void*)0);
77 _cleanup_free___attribute__((cleanup(freep))) char *b = NULL((void*)0);
78 _cleanup_free___attribute__((cleanup(freep))) const char *fn = NULL((void*)0);
79 const char *c = NULL((void*)0);
80 char line[LINE_MAX2048];
81 size_t n;
82 int r;
83
84 assert(field)do { if ((__builtin_expect(!!(!(field)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("field"), "../src/libsystemd/sd-path/sd-path.c"
, 84, __PRETTY_FUNCTION__); } while (0)
;
85 assert(buffer)do { if ((__builtin_expect(!!(!(buffer)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("buffer"), "../src/libsystemd/sd-path/sd-path.c"
, 85, __PRETTY_FUNCTION__); } while (0)
;
86 assert(ret)do { if ((__builtin_expect(!!(!(ret)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ret"), "../src/libsystemd/sd-path/sd-path.c"
, 86, __PRETTY_FUNCTION__); } while (0)
;
87
88 r = from_home_dir("XDG_CONFIG_HOME", ".config", &b, &c);
89 if (r < 0)
90 return r;
91
92 fn = strappend(c, "/user-dirs.dirs");
93 if (!fn)
94 return -ENOMEM12;
95
96 f = fopen(fn, "re");
97 if (!f) {
98 if (errno(*__errno_location ()) == ENOENT2)
99 goto fallback;
100
101 return -errno(*__errno_location ());
102 }
103
104 /* This is an awful parse, but it follows closely what
105 * xdg-user-dirs does upstream */
106
107 n = strlen(field);
108 FOREACH_LINE(line, f, return -errno)for (;;) if (!fgets(line, sizeof(line), f)) { if (ferror(f)) {
return -(*__errno_location ()); } break; } else
{
109 char *l, *p, *e;
110
111 l = strstrip(line);
112
113 if (!strneq(l, field, n)(strncmp((l), (field), (n)) == 0))
114 continue;
115
116 p = l + n;
117 p += strspn(p, WHITESPACE" \t\n\r");
118
119 if (*p != '=')
120 continue;
121 p++;
122
123 p += strspn(p, WHITESPACE" \t\n\r");
124
125 if (*p != '"')
126 continue;
127 p++;
128
129 e = strrchr(p, '"');
130 if (!e)
131 continue;
132 *e = 0;
133
134 /* Three syntaxes permitted: relative to $HOME, $HOME itself, and absolute path */
135 if (startswith(p, "$HOME/")) {
136 _cleanup_free___attribute__((cleanup(freep))) char *h = NULL((void*)0);
137 char *cc;
138
139 r = get_home_dir(&h);
140 if (r < 0)
141 return r;
142
143 cc = strappend(h, p+5);
144 if (!cc)
145 return -ENOMEM12;
146
147 *buffer = cc;
148 *ret = cc;
149 return 0;
150 } else if (streq(p, "$HOME")(strcmp((p),("$HOME")) == 0)) {
151
152 r = get_home_dir(buffer);
153 if (r < 0)
154 return r;
155
156 *ret = *buffer;
157 return 0;
158 } else if (path_is_absolute(p)) {
159 char *copy;
160
161 copy = strdup(p);
162 if (!copy)
163 return -ENOMEM12;
164
165 *buffer = copy;
166 *ret = copy;
167 return 0;
168 }
169 }
170
171fallback:
172 /* The desktop directory defaults to $HOME/Desktop, the others to $HOME */
173 if (streq(field, "XDG_DESKTOP_DIR")(strcmp((field),("XDG_DESKTOP_DIR")) == 0)) {
174 _cleanup_free___attribute__((cleanup(freep))) char *h = NULL((void*)0);
175 char *cc;
176
177 r = get_home_dir(&h);
178 if (r < 0)
179 return r;
180
181 cc = strappend(h, "/Desktop");
182 if (!cc)
183 return -ENOMEM12;
184
185 *buffer = cc;
186 *ret = cc;
187 } else {
188
189 r = get_home_dir(buffer);
190 if (r < 0)
191 return r;
192
193 *ret = *buffer;
194 }
195
196 return 0;
197}
198
199static int get_path(uint64_t type, char **buffer, const char **ret) {
200 int r;
201
202 assert(buffer)do { if ((__builtin_expect(!!(!(buffer)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("buffer"), "../src/libsystemd/sd-path/sd-path.c"
, 202, __PRETTY_FUNCTION__); } while (0)
;
203 assert(ret)do { if ((__builtin_expect(!!(!(ret)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ret"), "../src/libsystemd/sd-path/sd-path.c"
, 203, __PRETTY_FUNCTION__); } while (0)
;
204
205 switch (type) {
206
207 case SD_PATH_TEMPORARY:
208 return tmp_dir(ret);
209
210 case SD_PATH_TEMPORARY_LARGE:
211 return var_tmp_dir(ret);
212
213 case SD_PATH_SYSTEM_BINARIES:
214 *ret = "/usr/bin";
215 return 0;
216
217 case SD_PATH_SYSTEM_INCLUDE:
218 *ret = "/usr/include";
219 return 0;
220
221 case SD_PATH_SYSTEM_LIBRARY_PRIVATE:
222 *ret = "/usr/lib";
223 return 0;
224
225 case SD_PATH_SYSTEM_LIBRARY_ARCH:
226 *ret = LIBDIR"/usr/lib64";
227 return 0;
228
229 case SD_PATH_SYSTEM_SHARED:
230 *ret = "/usr/share";
231 return 0;
232
233 case SD_PATH_SYSTEM_CONFIGURATION_FACTORY:
234 *ret = "/usr/share/factory/etc";
235 return 0;
236
237 case SD_PATH_SYSTEM_STATE_FACTORY:
238 *ret = "/usr/share/factory/var";
239 return 0;
240
241 case SD_PATH_SYSTEM_CONFIGURATION:
242 *ret = "/etc";
243 return 0;
244
245 case SD_PATH_SYSTEM_RUNTIME:
246 *ret = "/run";
247 return 0;
248
249 case SD_PATH_SYSTEM_RUNTIME_LOGS:
250 *ret = "/run/log";
251 return 0;
252
253 case SD_PATH_SYSTEM_STATE_PRIVATE:
254 *ret = "/var/lib";
255 return 0;
256
257 case SD_PATH_SYSTEM_STATE_LOGS:
258 *ret = "/var/log";
259 return 0;
260
261 case SD_PATH_SYSTEM_STATE_CACHE:
262 *ret = "/var/cache";
263 return 0;
264
265 case SD_PATH_SYSTEM_STATE_SPOOL:
266 *ret = "/var/spool";
267 return 0;
268
269 case SD_PATH_USER_BINARIES:
270 return from_home_dir(NULL((void*)0), ".local/bin", buffer, ret);
271
272 case SD_PATH_USER_LIBRARY_PRIVATE:
273 return from_home_dir(NULL((void*)0), ".local/lib", buffer, ret);
274
275 case SD_PATH_USER_LIBRARY_ARCH:
276 return from_home_dir(NULL((void*)0), ".local/lib/" LIB_ARCH_TUPLE"x86_64-linux-gnu", buffer, ret);
277
278 case SD_PATH_USER_SHARED:
279 return from_home_dir("XDG_DATA_HOME", ".local/share", buffer, ret);
280
281 case SD_PATH_USER_CONFIGURATION:
282 return from_home_dir("XDG_CONFIG_HOME", ".config", buffer, ret);
283
284 case SD_PATH_USER_RUNTIME:
285 return from_environment("XDG_RUNTIME_DIR", NULL((void*)0), ret);
286
287 case SD_PATH_USER_STATE_CACHE:
288 return from_home_dir("XDG_CACHE_HOME", ".cache", buffer, ret);
289
290 case SD_PATH_USER:
291 r = get_home_dir(buffer);
292 if (r < 0)
293 return r;
294
295 *ret = *buffer;
296 return 0;
297
298 case SD_PATH_USER_DOCUMENTS:
299 return from_user_dir("XDG_DOCUMENTS_DIR", buffer, ret);
300
301 case SD_PATH_USER_MUSIC:
302 return from_user_dir("XDG_MUSIC_DIR", buffer, ret);
303
304 case SD_PATH_USER_PICTURES:
305 return from_user_dir("XDG_PICTURES_DIR", buffer, ret);
306
307 case SD_PATH_USER_VIDEOS:
308 return from_user_dir("XDG_VIDEOS_DIR", buffer, ret);
309
310 case SD_PATH_USER_DOWNLOAD:
311 return from_user_dir("XDG_DOWNLOAD_DIR", buffer, ret);
312
313 case SD_PATH_USER_PUBLIC:
314 return from_user_dir("XDG_PUBLICSHARE_DIR", buffer, ret);
315
316 case SD_PATH_USER_TEMPLATES:
317 return from_user_dir("XDG_TEMPLATES_DIR", buffer, ret);
318
319 case SD_PATH_USER_DESKTOP:
320 return from_user_dir("XDG_DESKTOP_DIR", buffer, ret);
321 }
322
323 return -EOPNOTSUPP95;
324}
325
326_public___attribute__ ((visibility("default"))) int sd_path_home(uint64_t type, const char *suffix, char **path) {
327 char *buffer = NULL((void*)0), *cc;
328 const char *ret;
329 int r;
330
331 assert_return(path, -EINVAL)do { if (!(((__builtin_expect(!!(path),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("path"), "../src/libsystemd/sd-path/sd-path.c"
, 331, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
1
Assuming 'path' is non-null
2
'?' condition is true
3
Taking false branch
4
Loop condition is false. Exiting loop
332
333 if (IN_SET(type,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){SD_PATH_SEARCH_BINARIES, SD_PATH_SEARCH_BINARIES_DEFAULT
, SD_PATH_SEARCH_LIBRARY_PRIVATE, SD_PATH_SEARCH_LIBRARY_ARCH
, SD_PATH_SEARCH_SHARED, SD_PATH_SEARCH_CONFIGURATION_FACTORY
, SD_PATH_SEARCH_STATE_FACTORY, SD_PATH_SEARCH_CONFIGURATION}
)/sizeof(int)]; switch(type) { case SD_PATH_SEARCH_BINARIES: case
SD_PATH_SEARCH_BINARIES_DEFAULT: case SD_PATH_SEARCH_LIBRARY_PRIVATE
: case SD_PATH_SEARCH_LIBRARY_ARCH: case SD_PATH_SEARCH_SHARED
: case SD_PATH_SEARCH_CONFIGURATION_FACTORY: case SD_PATH_SEARCH_STATE_FACTORY
: case SD_PATH_SEARCH_CONFIGURATION: _found = 1; break; default
: break; } _found; })
5
Control jumps to 'case SD_PATH_SEARCH_CONFIGURATION:' at line 333
6
Execution continues on line 333
7
Taking true branch
334 SD_PATH_SEARCH_BINARIES,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){SD_PATH_SEARCH_BINARIES, SD_PATH_SEARCH_BINARIES_DEFAULT
, SD_PATH_SEARCH_LIBRARY_PRIVATE, SD_PATH_SEARCH_LIBRARY_ARCH
, SD_PATH_SEARCH_SHARED, SD_PATH_SEARCH_CONFIGURATION_FACTORY
, SD_PATH_SEARCH_STATE_FACTORY, SD_PATH_SEARCH_CONFIGURATION}
)/sizeof(int)]; switch(type) { case SD_PATH_SEARCH_BINARIES: case
SD_PATH_SEARCH_BINARIES_DEFAULT: case SD_PATH_SEARCH_LIBRARY_PRIVATE
: case SD_PATH_SEARCH_LIBRARY_ARCH: case SD_PATH_SEARCH_SHARED
: case SD_PATH_SEARCH_CONFIGURATION_FACTORY: case SD_PATH_SEARCH_STATE_FACTORY
: case SD_PATH_SEARCH_CONFIGURATION: _found = 1; break; default
: break; } _found; })
335 SD_PATH_SEARCH_BINARIES_DEFAULT,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){SD_PATH_SEARCH_BINARIES, SD_PATH_SEARCH_BINARIES_DEFAULT
, SD_PATH_SEARCH_LIBRARY_PRIVATE, SD_PATH_SEARCH_LIBRARY_ARCH
, SD_PATH_SEARCH_SHARED, SD_PATH_SEARCH_CONFIGURATION_FACTORY
, SD_PATH_SEARCH_STATE_FACTORY, SD_PATH_SEARCH_CONFIGURATION}
)/sizeof(int)]; switch(type) { case SD_PATH_SEARCH_BINARIES: case
SD_PATH_SEARCH_BINARIES_DEFAULT: case SD_PATH_SEARCH_LIBRARY_PRIVATE
: case SD_PATH_SEARCH_LIBRARY_ARCH: case SD_PATH_SEARCH_SHARED
: case SD_PATH_SEARCH_CONFIGURATION_FACTORY: case SD_PATH_SEARCH_STATE_FACTORY
: case SD_PATH_SEARCH_CONFIGURATION: _found = 1; break; default
: break; } _found; })
336 SD_PATH_SEARCH_LIBRARY_PRIVATE,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){SD_PATH_SEARCH_BINARIES, SD_PATH_SEARCH_BINARIES_DEFAULT
, SD_PATH_SEARCH_LIBRARY_PRIVATE, SD_PATH_SEARCH_LIBRARY_ARCH
, SD_PATH_SEARCH_SHARED, SD_PATH_SEARCH_CONFIGURATION_FACTORY
, SD_PATH_SEARCH_STATE_FACTORY, SD_PATH_SEARCH_CONFIGURATION}
)/sizeof(int)]; switch(type) { case SD_PATH_SEARCH_BINARIES: case
SD_PATH_SEARCH_BINARIES_DEFAULT: case SD_PATH_SEARCH_LIBRARY_PRIVATE
: case SD_PATH_SEARCH_LIBRARY_ARCH: case SD_PATH_SEARCH_SHARED
: case SD_PATH_SEARCH_CONFIGURATION_FACTORY: case SD_PATH_SEARCH_STATE_FACTORY
: case SD_PATH_SEARCH_CONFIGURATION: _found = 1; break; default
: break; } _found; })
337 SD_PATH_SEARCH_LIBRARY_ARCH,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){SD_PATH_SEARCH_BINARIES, SD_PATH_SEARCH_BINARIES_DEFAULT
, SD_PATH_SEARCH_LIBRARY_PRIVATE, SD_PATH_SEARCH_LIBRARY_ARCH
, SD_PATH_SEARCH_SHARED, SD_PATH_SEARCH_CONFIGURATION_FACTORY
, SD_PATH_SEARCH_STATE_FACTORY, SD_PATH_SEARCH_CONFIGURATION}
)/sizeof(int)]; switch(type) { case SD_PATH_SEARCH_BINARIES: case
SD_PATH_SEARCH_BINARIES_DEFAULT: case SD_PATH_SEARCH_LIBRARY_PRIVATE
: case SD_PATH_SEARCH_LIBRARY_ARCH: case SD_PATH_SEARCH_SHARED
: case SD_PATH_SEARCH_CONFIGURATION_FACTORY: case SD_PATH_SEARCH_STATE_FACTORY
: case SD_PATH_SEARCH_CONFIGURATION: _found = 1; break; default
: break; } _found; })
338 SD_PATH_SEARCH_SHARED,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){SD_PATH_SEARCH_BINARIES, SD_PATH_SEARCH_BINARIES_DEFAULT
, SD_PATH_SEARCH_LIBRARY_PRIVATE, SD_PATH_SEARCH_LIBRARY_ARCH
, SD_PATH_SEARCH_SHARED, SD_PATH_SEARCH_CONFIGURATION_FACTORY
, SD_PATH_SEARCH_STATE_FACTORY, SD_PATH_SEARCH_CONFIGURATION}
)/sizeof(int)]; switch(type) { case SD_PATH_SEARCH_BINARIES: case
SD_PATH_SEARCH_BINARIES_DEFAULT: case SD_PATH_SEARCH_LIBRARY_PRIVATE
: case SD_PATH_SEARCH_LIBRARY_ARCH: case SD_PATH_SEARCH_SHARED
: case SD_PATH_SEARCH_CONFIGURATION_FACTORY: case SD_PATH_SEARCH_STATE_FACTORY
: case SD_PATH_SEARCH_CONFIGURATION: _found = 1; break; default
: break; } _found; })
339 SD_PATH_SEARCH_CONFIGURATION_FACTORY,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){SD_PATH_SEARCH_BINARIES, SD_PATH_SEARCH_BINARIES_DEFAULT
, SD_PATH_SEARCH_LIBRARY_PRIVATE, SD_PATH_SEARCH_LIBRARY_ARCH
, SD_PATH_SEARCH_SHARED, SD_PATH_SEARCH_CONFIGURATION_FACTORY
, SD_PATH_SEARCH_STATE_FACTORY, SD_PATH_SEARCH_CONFIGURATION}
)/sizeof(int)]; switch(type) { case SD_PATH_SEARCH_BINARIES: case
SD_PATH_SEARCH_BINARIES_DEFAULT: case SD_PATH_SEARCH_LIBRARY_PRIVATE
: case SD_PATH_SEARCH_LIBRARY_ARCH: case SD_PATH_SEARCH_SHARED
: case SD_PATH_SEARCH_CONFIGURATION_FACTORY: case SD_PATH_SEARCH_STATE_FACTORY
: case SD_PATH_SEARCH_CONFIGURATION: _found = 1; break; default
: break; } _found; })
340 SD_PATH_SEARCH_STATE_FACTORY,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){SD_PATH_SEARCH_BINARIES, SD_PATH_SEARCH_BINARIES_DEFAULT
, SD_PATH_SEARCH_LIBRARY_PRIVATE, SD_PATH_SEARCH_LIBRARY_ARCH
, SD_PATH_SEARCH_SHARED, SD_PATH_SEARCH_CONFIGURATION_FACTORY
, SD_PATH_SEARCH_STATE_FACTORY, SD_PATH_SEARCH_CONFIGURATION}
)/sizeof(int)]; switch(type) { case SD_PATH_SEARCH_BINARIES: case
SD_PATH_SEARCH_BINARIES_DEFAULT: case SD_PATH_SEARCH_LIBRARY_PRIVATE
: case SD_PATH_SEARCH_LIBRARY_ARCH: case SD_PATH_SEARCH_SHARED
: case SD_PATH_SEARCH_CONFIGURATION_FACTORY: case SD_PATH_SEARCH_STATE_FACTORY
: case SD_PATH_SEARCH_CONFIGURATION: _found = 1; break; default
: break; } _found; })
341 SD_PATH_SEARCH_CONFIGURATION)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){SD_PATH_SEARCH_BINARIES, SD_PATH_SEARCH_BINARIES_DEFAULT
, SD_PATH_SEARCH_LIBRARY_PRIVATE, SD_PATH_SEARCH_LIBRARY_ARCH
, SD_PATH_SEARCH_SHARED, SD_PATH_SEARCH_CONFIGURATION_FACTORY
, SD_PATH_SEARCH_STATE_FACTORY, SD_PATH_SEARCH_CONFIGURATION}
)/sizeof(int)]; switch(type) { case SD_PATH_SEARCH_BINARIES: case
SD_PATH_SEARCH_BINARIES_DEFAULT: case SD_PATH_SEARCH_LIBRARY_PRIVATE
: case SD_PATH_SEARCH_LIBRARY_ARCH: case SD_PATH_SEARCH_SHARED
: case SD_PATH_SEARCH_CONFIGURATION_FACTORY: case SD_PATH_SEARCH_STATE_FACTORY
: case SD_PATH_SEARCH_CONFIGURATION: _found = 1; break; default
: break; } _found; })
) {
342
343 _cleanup_strv_free___attribute__((cleanup(strv_freep))) char **l = NULL((void*)0);
344
345 r = sd_path_search(type, suffix, &l);
8
Calling 'sd_path_search'
346 if (r < 0)
347 return r;
348
349 buffer = strv_join(l, ":");
350 if (!buffer)
351 return -ENOMEM12;
352
353 *path = buffer;
354 return 0;
355 }
356
357 r = get_path(type, &buffer, &ret);
358 if (r < 0)
359 return r;
360
361 if (!suffix) {
362 if (!buffer) {
363 buffer = strdup(ret);
364 if (!buffer)
365 return -ENOMEM12;
366 }
367
368 *path = buffer;
369 return 0;
370 }
371
372 suffix += strspn(suffix, "/");
373
374 if (endswith(ret, "/"))
375 cc = strappend(ret, suffix);
376 else
377 cc = strjoin(ret, "/", suffix)strjoin_real((ret), "/", suffix, ((void*)0));
378
379 free(buffer);
380
381 if (!cc)
382 return -ENOMEM12;
383
384 *path = cc;
385 return 0;
386}
387
388static int search_from_environment(
389 char ***list,
390 const char *env_home,
391 const char *home_suffix,
392 const char *env_search,
393 bool_Bool env_search_sufficient,
394 const char *first, ...) {
395
396 const char *e;
397 char *h = NULL((void*)0);
398 char **l = NULL((void*)0);
399 int r;
400
401 assert(list)do { if ((__builtin_expect(!!(!(list)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("list"), "../src/libsystemd/sd-path/sd-path.c"
, 401, __PRETTY_FUNCTION__); } while (0)
;
402
403 if (env_search) {
404 e = secure_getenv(env_search);
405 if (e) {
406 l = strv_split(e, ":");
407 if (!l)
408 return -ENOMEM12;
409
410 if (env_search_sufficient) {
411 *list = l;
412 return 0;
413 }
414 }
415 }
416
417 if (!l && first) {
418 va_list ap;
419
420 va_start(ap, first)__builtin_va_start(ap, first);
421 l = strv_new_ap(first, ap);
422 va_end(ap)__builtin_va_end(ap);
423
424 if (!l)
425 return -ENOMEM12;
426 }
427
428 if (env_home) {
429 e = secure_getenv(env_home);
430 if (e && path_is_absolute(e)) {
431 h = strdup(e);
432 if (!h) {
433 strv_free(l);
434 return -ENOMEM12;
435 }
436 }
437 }
438
439 if (!h && home_suffix) {
440 e = secure_getenv("HOME");
441 if (e && path_is_absolute(e)) {
442 if (endswith(e, "/"))
443 h = strappend(e, home_suffix);
444 else
445 h = strjoin(e, "/", home_suffix)strjoin_real((e), "/", home_suffix, ((void*)0));
446
447 if (!h) {
448 strv_free(l);
449 return -ENOMEM12;
450 }
451 }
452 }
453
454 if (h) {
455 r = strv_consume_prepend(&l, h);
456 if (r < 0) {
457 strv_free(l);
458 return -ENOMEM12;
459 }
460 }
461
462 *list = l;
463 return 0;
464}
465
466#if HAVE_SPLIT_BIN1
467# define ARRAY_SBIN_BIN(x)x "sbin", x "bin" x "sbin", x "bin"
468#else
469# define ARRAY_SBIN_BIN(x)x "sbin", x "bin" x "bin"
470#endif
471
472static int get_search(uint64_t type, char ***list) {
473
474 assert(list)do { if ((__builtin_expect(!!(!(list)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("list"), "../src/libsystemd/sd-path/sd-path.c"
, 474, __PRETTY_FUNCTION__); } while (0)
;
475
476 switch(type) {
477
478 case SD_PATH_SEARCH_BINARIES:
479 return search_from_environment(list,
480 NULL((void*)0),
481 ".local/bin",
482 "PATH",
483 true1,
484 ARRAY_SBIN_BIN("/usr/local/")"/usr/local/" "sbin", "/usr/local/" "bin",
485 ARRAY_SBIN_BIN("/usr/")"/usr/" "sbin", "/usr/" "bin",
486#if HAVE_SPLIT_USR0
487 ARRAY_SBIN_BIN("/")"/" "sbin", "/" "bin",
488#endif
489 NULL((void*)0));
490
491 case SD_PATH_SEARCH_LIBRARY_PRIVATE:
492 return search_from_environment(list,
493 NULL((void*)0),
494 ".local/lib",
495 NULL((void*)0),
496 false0,
497 "/usr/local/lib",
498 "/usr/lib",
499#if HAVE_SPLIT_USR0
500 "/lib",
501#endif
502 NULL((void*)0));
503
504 case SD_PATH_SEARCH_LIBRARY_ARCH:
505 return search_from_environment(list,
506 NULL((void*)0),
507 ".local/lib/" LIB_ARCH_TUPLE"x86_64-linux-gnu",
508 "LD_LIBRARY_PATH",
509 true1,
510 LIBDIR"/usr/lib64",
511#if HAVE_SPLIT_USR0
512 ROOTLIBDIR"/usr/lib64",
513#endif
514 NULL((void*)0));
515
516 case SD_PATH_SEARCH_SHARED:
517 return search_from_environment(list,
518 "XDG_DATA_HOME",
519 ".local/share",
520 "XDG_DATA_DIRS",
521 false0,
522 "/usr/local/share",
523 "/usr/share",
524 NULL((void*)0));
525
526 case SD_PATH_SEARCH_CONFIGURATION_FACTORY:
527 return search_from_environment(list,
528 NULL((void*)0),
529 NULL((void*)0),
530 NULL((void*)0),
531 false0,
532 "/usr/local/share/factory/etc",
533 "/usr/share/factory/etc",
534 NULL((void*)0));
535
536 case SD_PATH_SEARCH_STATE_FACTORY:
537 return search_from_environment(list,
538 NULL((void*)0),
539 NULL((void*)0),
540 NULL((void*)0),
541 false0,
542 "/usr/local/share/factory/var",
543 "/usr/share/factory/var",
544 NULL((void*)0));
545
546 case SD_PATH_SEARCH_CONFIGURATION:
547 return search_from_environment(list,
548 "XDG_CONFIG_HOME",
549 ".config",
550 "XDG_CONFIG_DIRS",
551 false0,
552 "/etc",
553 NULL((void*)0));
554
555 case SD_PATH_SEARCH_BINARIES_DEFAULT: {
556 char **t;
557
558 t = strv_split_nulstr(DEFAULT_PATH_NULSTR"/usr/local/" "sbin\0" "/usr/local/" "bin\0" "/usr/" "sbin\0"
"/usr/" "bin\0"
);
559 if (!t)
560 return -ENOMEM12;
561
562 *list = t;
563 return 0;
564 }}
565
566 return -EOPNOTSUPP95;
567}
568
569_public___attribute__ ((visibility("default"))) int sd_path_search(uint64_t type, const char *suffix, char ***paths) {
570 char **i, **j;
571 _cleanup_strv_free___attribute__((cleanup(strv_freep))) char **l = NULL((void*)0), **n = NULL((void*)0);
572 int r;
573
574 assert_return(paths, -EINVAL)do { if (!(((__builtin_expect(!!(paths),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("paths"), "../src/libsystemd/sd-path/sd-path.c"
, 574, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
9
'?' condition is true
10
Taking false branch
11
Loop condition is false. Exiting loop
575
576 if (!IN_SET(type,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){SD_PATH_SEARCH_BINARIES, SD_PATH_SEARCH_BINARIES_DEFAULT
, SD_PATH_SEARCH_LIBRARY_PRIVATE, SD_PATH_SEARCH_LIBRARY_ARCH
, SD_PATH_SEARCH_SHARED, SD_PATH_SEARCH_CONFIGURATION_FACTORY
, SD_PATH_SEARCH_STATE_FACTORY, SD_PATH_SEARCH_CONFIGURATION}
)/sizeof(int)]; switch(type) { case SD_PATH_SEARCH_BINARIES: case
SD_PATH_SEARCH_BINARIES_DEFAULT: case SD_PATH_SEARCH_LIBRARY_PRIVATE
: case SD_PATH_SEARCH_LIBRARY_ARCH: case SD_PATH_SEARCH_SHARED
: case SD_PATH_SEARCH_CONFIGURATION_FACTORY: case SD_PATH_SEARCH_STATE_FACTORY
: case SD_PATH_SEARCH_CONFIGURATION: _found = 1; break; default
: break; } _found; })
12
Control jumps to 'case SD_PATH_SEARCH_CONFIGURATION:' at line 576
13
Execution continues on line 576
14
Taking false branch
577 SD_PATH_SEARCH_BINARIES,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){SD_PATH_SEARCH_BINARIES, SD_PATH_SEARCH_BINARIES_DEFAULT
, SD_PATH_SEARCH_LIBRARY_PRIVATE, SD_PATH_SEARCH_LIBRARY_ARCH
, SD_PATH_SEARCH_SHARED, SD_PATH_SEARCH_CONFIGURATION_FACTORY
, SD_PATH_SEARCH_STATE_FACTORY, SD_PATH_SEARCH_CONFIGURATION}
)/sizeof(int)]; switch(type) { case SD_PATH_SEARCH_BINARIES: case
SD_PATH_SEARCH_BINARIES_DEFAULT: case SD_PATH_SEARCH_LIBRARY_PRIVATE
: case SD_PATH_SEARCH_LIBRARY_ARCH: case SD_PATH_SEARCH_SHARED
: case SD_PATH_SEARCH_CONFIGURATION_FACTORY: case SD_PATH_SEARCH_STATE_FACTORY
: case SD_PATH_SEARCH_CONFIGURATION: _found = 1; break; default
: break; } _found; })
578 SD_PATH_SEARCH_BINARIES_DEFAULT,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){SD_PATH_SEARCH_BINARIES, SD_PATH_SEARCH_BINARIES_DEFAULT
, SD_PATH_SEARCH_LIBRARY_PRIVATE, SD_PATH_SEARCH_LIBRARY_ARCH
, SD_PATH_SEARCH_SHARED, SD_PATH_SEARCH_CONFIGURATION_FACTORY
, SD_PATH_SEARCH_STATE_FACTORY, SD_PATH_SEARCH_CONFIGURATION}
)/sizeof(int)]; switch(type) { case SD_PATH_SEARCH_BINARIES: case
SD_PATH_SEARCH_BINARIES_DEFAULT: case SD_PATH_SEARCH_LIBRARY_PRIVATE
: case SD_PATH_SEARCH_LIBRARY_ARCH: case SD_PATH_SEARCH_SHARED
: case SD_PATH_SEARCH_CONFIGURATION_FACTORY: case SD_PATH_SEARCH_STATE_FACTORY
: case SD_PATH_SEARCH_CONFIGURATION: _found = 1; break; default
: break; } _found; })
579 SD_PATH_SEARCH_LIBRARY_PRIVATE,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){SD_PATH_SEARCH_BINARIES, SD_PATH_SEARCH_BINARIES_DEFAULT
, SD_PATH_SEARCH_LIBRARY_PRIVATE, SD_PATH_SEARCH_LIBRARY_ARCH
, SD_PATH_SEARCH_SHARED, SD_PATH_SEARCH_CONFIGURATION_FACTORY
, SD_PATH_SEARCH_STATE_FACTORY, SD_PATH_SEARCH_CONFIGURATION}
)/sizeof(int)]; switch(type) { case SD_PATH_SEARCH_BINARIES: case
SD_PATH_SEARCH_BINARIES_DEFAULT: case SD_PATH_SEARCH_LIBRARY_PRIVATE
: case SD_PATH_SEARCH_LIBRARY_ARCH: case SD_PATH_SEARCH_SHARED
: case SD_PATH_SEARCH_CONFIGURATION_FACTORY: case SD_PATH_SEARCH_STATE_FACTORY
: case SD_PATH_SEARCH_CONFIGURATION: _found = 1; break; default
: break; } _found; })
580 SD_PATH_SEARCH_LIBRARY_ARCH,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){SD_PATH_SEARCH_BINARIES, SD_PATH_SEARCH_BINARIES_DEFAULT
, SD_PATH_SEARCH_LIBRARY_PRIVATE, SD_PATH_SEARCH_LIBRARY_ARCH
, SD_PATH_SEARCH_SHARED, SD_PATH_SEARCH_CONFIGURATION_FACTORY
, SD_PATH_SEARCH_STATE_FACTORY, SD_PATH_SEARCH_CONFIGURATION}
)/sizeof(int)]; switch(type) { case SD_PATH_SEARCH_BINARIES: case
SD_PATH_SEARCH_BINARIES_DEFAULT: case SD_PATH_SEARCH_LIBRARY_PRIVATE
: case SD_PATH_SEARCH_LIBRARY_ARCH: case SD_PATH_SEARCH_SHARED
: case SD_PATH_SEARCH_CONFIGURATION_FACTORY: case SD_PATH_SEARCH_STATE_FACTORY
: case SD_PATH_SEARCH_CONFIGURATION: _found = 1; break; default
: break; } _found; })
581 SD_PATH_SEARCH_SHARED,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){SD_PATH_SEARCH_BINARIES, SD_PATH_SEARCH_BINARIES_DEFAULT
, SD_PATH_SEARCH_LIBRARY_PRIVATE, SD_PATH_SEARCH_LIBRARY_ARCH
, SD_PATH_SEARCH_SHARED, SD_PATH_SEARCH_CONFIGURATION_FACTORY
, SD_PATH_SEARCH_STATE_FACTORY, SD_PATH_SEARCH_CONFIGURATION}
)/sizeof(int)]; switch(type) { case SD_PATH_SEARCH_BINARIES: case
SD_PATH_SEARCH_BINARIES_DEFAULT: case SD_PATH_SEARCH_LIBRARY_PRIVATE
: case SD_PATH_SEARCH_LIBRARY_ARCH: case SD_PATH_SEARCH_SHARED
: case SD_PATH_SEARCH_CONFIGURATION_FACTORY: case SD_PATH_SEARCH_STATE_FACTORY
: case SD_PATH_SEARCH_CONFIGURATION: _found = 1; break; default
: break; } _found; })
582 SD_PATH_SEARCH_CONFIGURATION_FACTORY,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){SD_PATH_SEARCH_BINARIES, SD_PATH_SEARCH_BINARIES_DEFAULT
, SD_PATH_SEARCH_LIBRARY_PRIVATE, SD_PATH_SEARCH_LIBRARY_ARCH
, SD_PATH_SEARCH_SHARED, SD_PATH_SEARCH_CONFIGURATION_FACTORY
, SD_PATH_SEARCH_STATE_FACTORY, SD_PATH_SEARCH_CONFIGURATION}
)/sizeof(int)]; switch(type) { case SD_PATH_SEARCH_BINARIES: case
SD_PATH_SEARCH_BINARIES_DEFAULT: case SD_PATH_SEARCH_LIBRARY_PRIVATE
: case SD_PATH_SEARCH_LIBRARY_ARCH: case SD_PATH_SEARCH_SHARED
: case SD_PATH_SEARCH_CONFIGURATION_FACTORY: case SD_PATH_SEARCH_STATE_FACTORY
: case SD_PATH_SEARCH_CONFIGURATION: _found = 1; break; default
: break; } _found; })
583 SD_PATH_SEARCH_STATE_FACTORY,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){SD_PATH_SEARCH_BINARIES, SD_PATH_SEARCH_BINARIES_DEFAULT
, SD_PATH_SEARCH_LIBRARY_PRIVATE, SD_PATH_SEARCH_LIBRARY_ARCH
, SD_PATH_SEARCH_SHARED, SD_PATH_SEARCH_CONFIGURATION_FACTORY
, SD_PATH_SEARCH_STATE_FACTORY, SD_PATH_SEARCH_CONFIGURATION}
)/sizeof(int)]; switch(type) { case SD_PATH_SEARCH_BINARIES: case
SD_PATH_SEARCH_BINARIES_DEFAULT: case SD_PATH_SEARCH_LIBRARY_PRIVATE
: case SD_PATH_SEARCH_LIBRARY_ARCH: case SD_PATH_SEARCH_SHARED
: case SD_PATH_SEARCH_CONFIGURATION_FACTORY: case SD_PATH_SEARCH_STATE_FACTORY
: case SD_PATH_SEARCH_CONFIGURATION: _found = 1; break; default
: break; } _found; })
584 SD_PATH_SEARCH_CONFIGURATION)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){SD_PATH_SEARCH_BINARIES, SD_PATH_SEARCH_BINARIES_DEFAULT
, SD_PATH_SEARCH_LIBRARY_PRIVATE, SD_PATH_SEARCH_LIBRARY_ARCH
, SD_PATH_SEARCH_SHARED, SD_PATH_SEARCH_CONFIGURATION_FACTORY
, SD_PATH_SEARCH_STATE_FACTORY, SD_PATH_SEARCH_CONFIGURATION}
)/sizeof(int)]; switch(type) { case SD_PATH_SEARCH_BINARIES: case
SD_PATH_SEARCH_BINARIES_DEFAULT: case SD_PATH_SEARCH_LIBRARY_PRIVATE
: case SD_PATH_SEARCH_LIBRARY_ARCH: case SD_PATH_SEARCH_SHARED
: case SD_PATH_SEARCH_CONFIGURATION_FACTORY: case SD_PATH_SEARCH_STATE_FACTORY
: case SD_PATH_SEARCH_CONFIGURATION: _found = 1; break; default
: break; } _found; })
) {
585
586 char *p;
587
588 r = sd_path_home(type, suffix, &p);
589 if (r < 0)
590 return r;
591
592 l = new(char*, 2)((char**) malloc_multiply(sizeof(char*), (2)));
593 if (!l) {
594 free(p);
595 return -ENOMEM12;
596 }
597
598 l[0] = p;
599 l[1] = NULL((void*)0);
600
601 *paths = TAKE_PTR(l)({ typeof(l) _ptr_ = (l); (l) = ((void*)0); _ptr_; });
602 return 0;
603 }
604
605 r = get_search(type, &l);
606 if (r < 0)
15
Assuming 'r' is >= 0
16
Taking false branch
607 return r;
608
609 if (!suffix) {
17
Assuming 'suffix' is non-null
18
Taking false branch
610 *paths = TAKE_PTR(l)({ typeof(l) _ptr_ = (l); (l) = ((void*)0); _ptr_; });
611 return 0;
612 }
613
614 n = new(char*, strv_length(l)+1)((char**) malloc_multiply(sizeof(char*), (strv_length(l)+1)));
19
Calling 'malloc_multiply'
22
Returned allocated memory
615 if (!n)
23
Assuming 'n' is non-null
24
Taking false branch
616 return -ENOMEM12;
617
618 j = n;
619 STRV_FOREACH(i, l)for ((i) = (l); (i) && *(i); (i)++) {
25
Assuming 'i' is non-null
26
Loop condition is true. Entering loop body
620
621 if (endswith(*i, "/"))
27
Assuming the condition is false
28
Taking false branch
622 *j = strappend(*i, suffix);
623 else
624 *j = strjoin(*i, "/", suffix)strjoin_real((*i), "/", suffix, ((void*)0));
29
Use of zero-allocated memory
625
626 if (!*j)
627 return -ENOMEM12;
628
629 j++;
630 }
631
632 *j = NULL((void*)0);
633 *paths = TAKE_PTR(n)({ typeof(n) _ptr_ = (n); (n) = ((void*)0); _ptr_; });
634 return 0;
635}

../src/basic/alloc-util.h

1/* SPDX-License-Identifier: LGPL-2.1+ */
2#pragma once
3
4#include <alloca.h>
5#include <stddef.h>
6#include <stdlib.h>
7#include <string.h>
8
9#include "macro.h"
10
11#define new(t, n)((t*) malloc_multiply(sizeof(t), (n))) ((t*) malloc_multiply(sizeof(t), (n)))
12
13#define new0(t, n)((t*) calloc((n), sizeof(t))) ((t*) calloc((n), sizeof(t)))
14
15#define newa(t, n)({ do { if ((__builtin_expect(!!(!(!size_multiply_overflow(sizeof
(t), n))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("!size_multiply_overflow(sizeof(t), n)"
), "../src/basic/alloc-util.h", 15, __PRETTY_FUNCTION__); } while
(0); (t*) __builtin_alloca (sizeof(t)*(n)); })
\
16 ({ \
17 assert(!size_multiply_overflow(sizeof(t), n))do { if ((__builtin_expect(!!(!(!size_multiply_overflow(sizeof
(t), n))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("!size_multiply_overflow(sizeof(t), n)"
), "../src/basic/alloc-util.h", 17, __PRETTY_FUNCTION__); } while
(0)
; \
18 (t*) alloca(sizeof(t)*(n))__builtin_alloca (sizeof(t)*(n)); \
19 })
20
21#define newa0(t, n)({ do { if ((__builtin_expect(!!(!(!size_multiply_overflow(sizeof
(t), n))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("!size_multiply_overflow(sizeof(t), n)"
), "../src/basic/alloc-util.h", 21, __PRETTY_FUNCTION__); } while
(0); (t*) ({ char *_new_; size_t _len_ = sizeof(t)*(n); _new_
= __builtin_alloca (_len_); (void *) memset(_new_, 0, _len_)
; }); })
\
22 ({ \
23 assert(!size_multiply_overflow(sizeof(t), n))do { if ((__builtin_expect(!!(!(!size_multiply_overflow(sizeof
(t), n))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("!size_multiply_overflow(sizeof(t), n)"
), "../src/basic/alloc-util.h", 23, __PRETTY_FUNCTION__); } while
(0)
; \
24 (t*) alloca0(sizeof(t)*(n))({ char *_new_; size_t _len_ = sizeof(t)*(n); _new_ = __builtin_alloca
(_len_); (void *) memset(_new_, 0, _len_); })
; \
25 })
26
27#define newdup(t, p, n)((t*) memdup_multiply(p, sizeof(t), (n))) ((t*) memdup_multiply(p, sizeof(t), (n)))
28
29#define newdup_suffix0(t, p, n)((t*) memdup_suffix0_multiply(p, sizeof(t), (n))) ((t*) memdup_suffix0_multiply(p, sizeof(t), (n)))
30
31#define malloc0(n)(calloc(1, (n))) (calloc(1, (n)))
32
33static inline void *mfree(void *memory) {
34 free(memory);
35 return NULL((void*)0);
36}
37
38#define free_and_replace(a, b)({ free(a); (a) = (b); (b) = ((void*)0); 0; }) \
39 ({ \
40 free(a); \
41 (a) = (b); \
42 (b) = NULL((void*)0); \
43 0; \
44 })
45
46void* memdup(const void *p, size_t l) _alloc_(2);
47void* memdup_suffix0(const void *p, size_t l) _alloc_(2);
48
49static inline void freep(void *p) {
50 free(*(void**) p);
51}
52
53#define _cleanup_free___attribute__((cleanup(freep))) _cleanup_(freep)__attribute__((cleanup(freep)))
54
55static inline bool_Bool size_multiply_overflow(size_t size, size_t need) {
56 return _unlikely_(need != 0 && size > (SIZE_MAX / need))(__builtin_expect(!!(need != 0 && size > ((18446744073709551615UL
) / need)),0))
;
57}
58
59_malloc___attribute__ ((malloc)) _alloc_(1, 2) static inline void *malloc_multiply(size_t size, size_t need) {
60 if (size_multiply_overflow(size, need))
20
Taking false branch
61 return NULL((void*)0);
62
63 return malloc(size * need);
21
Memory is allocated
64}
65
66#if !HAVE_REALLOCARRAY1
67_alloc_(2, 3) static inline void *reallocarray(void *p, size_t need, size_t size) {
68 if (size_multiply_overflow(size, need))
69 return NULL((void*)0);
70
71 return realloc(p, size * need);
72}
73#endif
74
75_alloc_(2, 3) static inline void *memdup_multiply(const void *p, size_t size, size_t need) {
76 if (size_multiply_overflow(size, need))
77 return NULL((void*)0);
78
79 return memdup(p, size * need);
80}
81
82_alloc_(2, 3) static inline void *memdup_suffix0_multiply(const void *p, size_t size, size_t need) {
83 if (size_multiply_overflow(size, need))
84 return NULL((void*)0);
85
86 return memdup_suffix0(p, size * need);
87}
88
89void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size);
90void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size);
91
92#define GREEDY_REALLOC(array, allocated, need)greedy_realloc((void**) &(array), &(allocated), (need
), sizeof((array)[0]))
\
93 greedy_realloc((void**) &(array), &(allocated), (need), sizeof((array)[0]))
94
95#define GREEDY_REALLOC0(array, allocated, need)greedy_realloc0((void**) &(array), &(allocated), (need
), sizeof((array)[0]))
\
96 greedy_realloc0((void**) &(array), &(allocated), (need), sizeof((array)[0]))
97
98#define alloca0(n)({ char *_new_; size_t _len_ = n; _new_ = __builtin_alloca (_len_
); (void *) memset(_new_, 0, _len_); })
\
99 ({ \
100 char *_new_; \
101 size_t _len_ = n; \
102 _new_ = alloca(_len_)__builtin_alloca (_len_); \
103 (void *) memset(_new_, 0, _len_); \
104 })
105
106/* It's not clear what alignment glibc/gcc alloca() guarantee, hence provide a guaranteed safe version */
107#define alloca_align(size, align)({ void *_ptr_; size_t _mask_ = (align) - 1; _ptr_ = __builtin_alloca
((size) + _mask_); (void*)(((uintptr_t)_ptr_ + _mask_) &
~_mask_); })
\
108 ({ \
109 void *_ptr_; \
110 size_t _mask_ = (align) - 1; \
111 _ptr_ = alloca((size) + _mask_)__builtin_alloca ((size) + _mask_); \
112 (void*)(((uintptr_t)_ptr_ + _mask_) & ~_mask_); \
113 })
114
115#define alloca0_align(size, align)({ void *_new_; size_t _size_ = (size); _new_ = ({ void *_ptr_
; size_t _mask_ = ((align)) - 1; _ptr_ = __builtin_alloca ((_size_
) + _mask_); (void*)(((uintptr_t)_ptr_ + _mask_) & ~_mask_
); }); (void*)memset(_new_, 0, _size_); })
\
116 ({ \
117 void *_new_; \
118 size_t _size_ = (size); \
119 _new_ = alloca_align(_size_, (align))({ void *_ptr_; size_t _mask_ = ((align)) - 1; _ptr_ = __builtin_alloca
((_size_) + _mask_); (void*)(((uintptr_t)_ptr_ + _mask_) &
~_mask_); })
; \
120 (void*)memset(_new_, 0, _size_); \
121 })
122
123/* Takes inspiration from Rusts's Option::take() method: reads and returns a pointer, but at the same time resets it to
124 * NULL. See: https://doc.rust-lang.org/std/option/enum.Option.html#method.take */
125#define TAKE_PTR(ptr)({ typeof(ptr) _ptr_ = (ptr); (ptr) = ((void*)0); _ptr_; }) \
126 ({ \
127 typeof(ptr) _ptr_ = (ptr); \
128 (ptr) = NULL((void*)0); \
129 _ptr_; \
130 })