Bug Summary

File:build-scan/../src/shared/cgroup-show.c
Warning:line 247, column 32
Potential leak of memory pointed to by 'copy'

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 cgroup-show.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/shared/libsystemd-shared-239.a.p -I src/shared -I ../src/shared -I src/basic -I ../src/basic -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 .. -I /usr/include/blkid -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/shared/cgroup-show.c

../src/shared/cgroup-show.c

1/* SPDX-License-Identifier: LGPL-2.1+ */
2
3#include <dirent.h>
4#include <errno(*__errno_location ()).h>
5#include <stddef.h>
6#include <stdio.h>
7#include <stdlib.h>
8#include <string.h>
9
10#include "alloc-util.h"
11#include "bus-error.h"
12#include "bus-util.h"
13#include "cgroup-show.h"
14#include "cgroup-util.h"
15#include "fd-util.h"
16#include "fileio.h"
17#include "format-util.h"
18#include "locale-util.h"
19#include "macro.h"
20#include "output-mode.h"
21#include "path-util.h"
22#include "process-util.h"
23#include "string-util.h"
24#include "terminal-util.h"
25#include "unit-name.h"
26
27static void show_pid_array(
28 pid_t pids[],
29 unsigned n_pids,
30 const char *prefix,
31 unsigned n_columns,
32 bool_Bool extra,
33 bool_Bool more,
34 OutputFlags flags) {
35
36 unsigned i, j, pid_width;
37
38 if (n_pids == 0)
39 return;
40
41 qsort(pids, n_pids, sizeof(pid_t), pid_compare_func);
42
43 /* Filter duplicates */
44 for (j = 0, i = 1; i < n_pids; i++) {
45 if (pids[i] == pids[j])
46 continue;
47 pids[++j] = pids[i];
48 }
49 n_pids = j + 1;
50 pid_width = DECIMAL_STR_WIDTH(pids[j])({ typeof(pids[j]) _x_ = (pids[j]); unsigned ans = 1; while (
(_x_ /= 10) != 0) ans++; ans; })
;
51
52 if (flags & OUTPUT_FULL_WIDTH)
53 n_columns = 0;
54 else {
55 if (n_columns > pid_width+2)
56 n_columns -= pid_width+2;
57 else
58 n_columns = 20;
59 }
60 for (i = 0; i < n_pids; i++) {
61 _cleanup_free___attribute__((cleanup(freep))) char *t = NULL((void*)0);
62
63 (void) get_process_cmdline(pids[i], n_columns, true1, &t);
64
65 if (extra)
66 printf("%s%s ", prefix, special_glyph(TRIANGULAR_BULLET));
67 else
68 printf("%s%s", prefix, special_glyph(((more || i < n_pids-1) ? TREE_BRANCH : TREE_RIGHT)));
69
70 printf("%*"PID_PRI"i"" %s\n", pid_width, pids[i], strna(t));
71 }
72}
73
74static int show_cgroup_one_by_path(
75 const char *path,
76 const char *prefix,
77 unsigned n_columns,
78 bool_Bool more,
79 OutputFlags flags) {
80
81 char *fn;
82 _cleanup_fclose___attribute__((cleanup(fclosep))) FILE *f = NULL((void*)0);
83 size_t n = 0, n_allocated = 0;
84 _cleanup_free___attribute__((cleanup(freep))) pid_t *pids = NULL((void*)0);
85 _cleanup_free___attribute__((cleanup(freep))) char *p = NULL((void*)0);
86 pid_t pid;
87 int r;
88
89 r = cg_mangle_path(path, &p);
90 if (r < 0)
91 return r;
92
93 fn = strjoina(p, "/cgroup.procs")({ const char *_appendees_[] = { p, "/cgroup.procs" }; char *
_d_, *_p_; size_t _len_ = 0; size_t _i_; for (_i_ = 0; _i_ <
__extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_
)/sizeof((_appendees_)[0]), ((void)0))) && _appendees_
[_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca
(_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(_appendees_), typeof(&
*(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0]
), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy
(_p_, _appendees_[_i_]); *_p_ = 0; _d_; })
;
94 f = fopen(fn, "re");
95 if (!f)
96 return -errno(*__errno_location ());
97
98 while ((r = cg_read_pid(f, &pid)) > 0) {
99
100 if (!(flags & OUTPUT_KERNEL_THREADS) && is_kernel_thread(pid) > 0)
101 continue;
102
103 if (!GREEDY_REALLOC(pids, n_allocated, n + 1)greedy_realloc((void**) &(pids), &(n_allocated), (n +
1), sizeof((pids)[0]))
)
104 return -ENOMEM12;
105
106 assert(n < n_allocated)do { if ((__builtin_expect(!!(!(n < n_allocated)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("n < n_allocated"), "../src/shared/cgroup-show.c"
, 106, __PRETTY_FUNCTION__); } while (0)
;
107 pids[n++] = pid;
108 }
109
110 if (r < 0)
111 return r;
112
113 show_pid_array(pids, n, prefix, n_columns, false0, more, flags);
114
115 return 0;
116}
117
118int show_cgroup_by_path(
119 const char *path,
120 const char *prefix,
121 unsigned n_columns,
122 OutputFlags flags) {
123
124 _cleanup_free___attribute__((cleanup(freep))) char *fn = NULL((void*)0), *p1 = NULL((void*)0), *last = NULL((void*)0), *p2 = NULL((void*)0);
125 _cleanup_closedir___attribute__((cleanup(closedirp))) DIR *d = NULL((void*)0);
126 char *gn = NULL((void*)0);
127 bool_Bool shown_pids = false0;
128 int r;
129
130 assert(path)do { if ((__builtin_expect(!!(!(path)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("path"), "../src/shared/cgroup-show.c", 130
, __PRETTY_FUNCTION__); } while (0)
;
131
132 if (n_columns <= 0)
133 n_columns = columns();
134
135 prefix = strempty(prefix);
136
137 r = cg_mangle_path(path, &fn);
138 if (r < 0)
139 return r;
140
141 d = opendir(fn);
142 if (!d)
143 return -errno(*__errno_location ());
144
145 while ((r = cg_read_subgroup(d, &gn)) > 0) {
146 _cleanup_free___attribute__((cleanup(freep))) char *k = NULL((void*)0);
147
148 k = strjoin(fn, "/", gn)strjoin_real((fn), "/", gn, ((void*)0));
149 free(gn);
150 if (!k)
151 return -ENOMEM12;
152
153 if (!(flags & OUTPUT_SHOW_ALL) && cg_is_empty_recursive(NULL((void*)0), k) > 0)
154 continue;
155
156 if (!shown_pids) {
157 show_cgroup_one_by_path(path, prefix, n_columns, true1, flags);
158 shown_pids = true1;
159 }
160
161 if (last) {
162 printf("%s%s%s\n", prefix, special_glyph(TREE_BRANCH), cg_unescape(basename(last)));
163
164 if (!p1) {
165 p1 = strappend(prefix, special_glyph(TREE_VERTICAL));
166 if (!p1)
167 return -ENOMEM12;
168 }
169
170 show_cgroup_by_path(last, p1, n_columns-2, flags);
171 free(last);
172 }
173
174 last = TAKE_PTR(k)({ typeof(k) _ptr_ = (k); (k) = ((void*)0); _ptr_; });
175 }
176
177 if (r < 0)
178 return r;
179
180 if (!shown_pids)
181 show_cgroup_one_by_path(path, prefix, n_columns, !!last, flags);
182
183 if (last) {
184 printf("%s%s%s\n", prefix, special_glyph(TREE_RIGHT), cg_unescape(basename(last)));
185
186 if (!p2) {
187 p2 = strappend(prefix, " ");
188 if (!p2)
189 return -ENOMEM12;
190 }
191
192 show_cgroup_by_path(last, p2, n_columns-2, flags);
193 }
194
195 return 0;
196}
197
198int show_cgroup(const char *controller,
199 const char *path,
200 const char *prefix,
201 unsigned n_columns,
202 OutputFlags flags) {
203 _cleanup_free___attribute__((cleanup(freep))) char *p = NULL((void*)0);
204 int r;
205
206 assert(path)do { if ((__builtin_expect(!!(!(path)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("path"), "../src/shared/cgroup-show.c", 206
, __PRETTY_FUNCTION__); } while (0)
;
207
208 r = cg_get_path(controller, path, NULL((void*)0), &p);
209 if (r < 0)
210 return r;
211
212 return show_cgroup_by_path(p, prefix, n_columns, flags);
213}
214
215static int show_extra_pids(
216 const char *controller,
217 const char *path,
218 const char *prefix,
219 unsigned n_columns,
220 const pid_t pids[],
221 unsigned n_pids,
222 OutputFlags flags) {
223
224 _cleanup_free___attribute__((cleanup(freep))) pid_t *copy = NULL((void*)0);
225 unsigned i, j;
226 int r;
227
228 assert(path)do { if ((__builtin_expect(!!(!(path)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("path"), "../src/shared/cgroup-show.c", 228
, __PRETTY_FUNCTION__); } while (0)
;
13
Taking false branch
14
Loop condition is false. Exiting loop
229
230 if (n_pids <= 0)
15
Assuming 'n_pids' is > 0
16
Taking false branch
231 return 0;
232
233 if (n_columns
16.1
'n_columns' is > 0
16.1
'n_columns' is > 0
<= 0)
17
Taking false branch
234 n_columns = columns();
235
236 prefix = strempty(prefix);
237
238 copy = new(pid_t, n_pids)((pid_t*) malloc_multiply(sizeof(pid_t), (n_pids)));
18
Calling 'malloc_multiply'
21
Returned allocated memory
239 if (!copy)
22
Assuming 'copy' is non-null
23
Taking false branch
240 return -ENOMEM12;
241
242 for (i = 0, j = 0; i
23.1
'i' is < 'n_pids'
23.1
'i' is < 'n_pids'
< n_pids; i++) {
24
Loop condition is true. Entering loop body
243 _cleanup_free___attribute__((cleanup(freep))) char *k = NULL((void*)0);
244
245 r = cg_pid_get_path(controller, pids[i], &k);
246 if (r < 0)
25
Assuming 'r' is < 0
26
Taking true branch
247 return r;
27
Potential leak of memory pointed to by 'copy'
248
249 if (path_startswith(k, path))
250 continue;
251
252 copy[j++] = pids[i];
253 }
254
255 show_pid_array(copy, j, prefix, n_columns, true1, false0, flags);
256
257 return 0;
258}
259
260int show_cgroup_and_extra(
261 const char *controller,
262 const char *path,
263 const char *prefix,
264 unsigned n_columns,
265 const pid_t extra_pids[],
266 unsigned n_extra_pids,
267 OutputFlags flags) {
268
269 int r;
270
271 assert(path)do { if ((__builtin_expect(!!(!(path)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("path"), "../src/shared/cgroup-show.c", 271
, __PRETTY_FUNCTION__); } while (0)
;
7
Assuming 'path' is non-null
8
Taking false branch
9
Loop condition is false. Exiting loop
272
273 r = show_cgroup(controller, path, prefix, n_columns, flags);
274 if (r < 0)
10
Assuming 'r' is >= 0
11
Taking false branch
275 return r;
276
277 return show_extra_pids(controller, path, prefix, n_columns, extra_pids, n_extra_pids, flags);
12
Calling 'show_extra_pids'
278}
279
280int show_cgroup_and_extra_by_spec(
281 const char *spec,
282 const char *prefix,
283 unsigned n_columns,
284 const pid_t extra_pids[],
285 unsigned n_extra_pids,
286 OutputFlags flags) {
287
288 _cleanup_free___attribute__((cleanup(freep))) char *controller = NULL((void*)0), *path = NULL((void*)0);
289 int r;
290
291 assert(spec)do { if ((__builtin_expect(!!(!(spec)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("spec"), "../src/shared/cgroup-show.c", 291
, __PRETTY_FUNCTION__); } while (0)
;
1
Assuming 'spec' is non-null
2
Taking false branch
3
Loop condition is false. Exiting loop
292
293 r = cg_split_spec(spec, &controller, &path);
294 if (r < 0)
4
Assuming 'r' is >= 0
5
Taking false branch
295 return r;
296
297 return show_cgroup_and_extra(controller, path, prefix, n_columns, extra_pids, n_extra_pids, flags);
6
Calling 'show_cgroup_and_extra'
298}
299
300int show_cgroup_get_unit_path_and_warn(
301 sd_bus *bus,
302 const char *unit,
303 char **ret) {
304
305 _cleanup_(sd_bus_error_free)__attribute__((cleanup(sd_bus_error_free))) sd_bus_error error = SD_BUS_ERROR_NULL((const sd_bus_error) {(((void*)0)), (((void*)0)), 0});
306 _cleanup_free___attribute__((cleanup(freep))) char *path = NULL((void*)0);
307 int r;
308
309 path = unit_dbus_path_from_name(unit);
310 if (!path)
311 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/shared/cgroup-show.c"
, 311, __func__)
;
312
313 r = sd_bus_get_property_string(
314 bus,
315 "org.freedesktop.systemd1",
316 path,
317 unit_dbus_interface_from_name(unit),
318 "ControlGroup",
319 &error,
320 ret);
321 if (r < 0)
322 return log_error_errno(r, "Failed to query unit control group path: %s",({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/shared/cgroup-show.c", 323, __func__, "Failed to query unit control group path: %s"
, bus_error_message(&error, r)) : -abs(_e); })
323 bus_error_message(&error, r))({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/shared/cgroup-show.c", 323, __func__, "Failed to query unit control group path: %s"
, bus_error_message(&error, r)) : -abs(_e); })
;
324
325 return 0;
326}
327
328int show_cgroup_get_path_and_warn(
329 const char *machine,
330 const char *prefix,
331 char **ret) {
332
333 int r;
334 _cleanup_free___attribute__((cleanup(freep))) char *root = NULL((void*)0);
335
336 if (machine) {
337 _cleanup_(sd_bus_flush_close_unrefp)__attribute__((cleanup(sd_bus_flush_close_unrefp))) sd_bus *bus = NULL((void*)0);
338 _cleanup_free___attribute__((cleanup(freep))) char *unit = NULL((void*)0);
339 const char *m;
340
341 m = strjoina("/run/systemd/machines/", machine)({ const char *_appendees_[] = { "/run/systemd/machines/", machine
}; char *_d_, *_p_; size_t _len_ = 0; size_t _i_; for (_i_ =
0; _i_ < __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_
)/sizeof((_appendees_)[0]), ((void)0))) && _appendees_
[_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca
(_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(_appendees_), typeof(&
*(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0]
), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy
(_p_, _appendees_[_i_]); *_p_ = 0; _d_; })
;
342 r = parse_env_file(NULL((void*)0), m, NEWLINE"\n\r", "SCOPE", &unit, NULL((void*)0));
343 if (r < 0)
344 return log_error_errno(r, "Failed to load machine data: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/shared/cgroup-show.c", 344, __func__, "Failed to load machine data: %m"
) : -abs(_e); })
;
345
346 r = bus_connect_transport_systemd(BUS_TRANSPORT_LOCAL, NULL((void*)0), false0, &bus);
347 if (r < 0)
348 return log_error_errno(r, "Failed to create bus connection: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/shared/cgroup-show.c", 348, __func__, "Failed to create bus connection: %m"
) : -abs(_e); })
;
349
350 r = show_cgroup_get_unit_path_and_warn(bus, unit, &root);
351 if (r < 0)
352 return r;
353 } else {
354 r = cg_get_root_path(&root);
355 if (r == -ENOMEDIUM123)
356 return log_error_errno(r, "Failed to get root control group path.\n"({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/shared/cgroup-show.c", 357, __func__, "Failed to get root control group path.\n"
"No cgroup filesystem mounted on /sys/fs/cgroup") : -abs(_e)
; })
357 "No cgroup filesystem mounted on /sys/fs/cgroup")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/shared/cgroup-show.c", 357, __func__, "Failed to get root control group path.\n"
"No cgroup filesystem mounted on /sys/fs/cgroup") : -abs(_e)
; })
;
358 else if (r < 0)
359 return log_error_errno(r, "Failed to get root control group path: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/shared/cgroup-show.c", 359, __func__, "Failed to get root control group path: %m"
) : -abs(_e); })
;
360 }
361
362 if (prefix) {
363 char *t;
364
365 t = strjoin(root, prefix)strjoin_real((root), prefix, ((void*)0));
366 if (!t)
367 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/shared/cgroup-show.c"
, 367, __func__)
;
368
369 *ret = t;
370 } else
371 *ret = TAKE_PTR(root)({ typeof(root) _ptr_ = (root); (root) = ((void*)0); _ptr_; }
)
;
372
373 return 0;
374}

../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))
19
Taking false branch
61 return NULL((void*)0);
62
63 return malloc(size * need);
20
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 })