Bug Summary

File:build-scan/../src/binfmt/binfmt.c
Warning:line 39, column 12
Potential leak of memory pointed to by 'x'

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 binfmt.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 static -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 systemd-binfmt.p -I . -I .. -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 -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 hidden -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/binfmt/binfmt.c
1/* SPDX-License-Identifier: LGPL-2.1+ */
2
3#include <errno(*__errno_location ()).h>
4#include <getopt.h>
5#include <limits.h>
6#include <stdbool.h>
7#include <stdio.h>
8#include <stdlib.h>
9#include <string.h>
10
11#include "alloc-util.h"
12#include "conf-files.h"
13#include "def.h"
14#include "fd-util.h"
15#include "fileio.h"
16#include "log.h"
17#include "pager.h"
18#include "string-util.h"
19#include "strv.h"
20#include "terminal-util.h"
21#include "util.h"
22
23static bool_Bool arg_cat_config = false0;
24static bool_Bool arg_no_pager = false0;
25
26static int delete_rule(const char *rule) {
27 _cleanup_free___attribute__((cleanup(freep))) char *x = NULL((void*)0), *fn = NULL((void*)0);
28 char *e;
29
30 assert(rule[0])do { if ((__builtin_expect(!!(!(rule[0])),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("rule[0]"), "../src/binfmt/binfmt.c", 30
, __PRETTY_FUNCTION__); } while (0)
;
26
Taking false branch
27
Loop condition is false. Exiting loop
31
32 x = strdup(rule);
28
Memory is allocated
33 if (!x)
29
Assuming 'x' is non-null
30
Taking false branch
34 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/binfmt/binfmt.c",
34, __func__)
;
35
36 e = strchrnul(x+1, x[0]);
37 *e = 0;
38
39 fn = strappend("/proc/sys/fs/binfmt_misc/", x+1);
31
Potential leak of memory pointed to by 'x'
40 if (!fn)
41 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/binfmt/binfmt.c",
41, __func__)
;
42
43 return write_string_file(fn, "-1", 0);
44}
45
46static int apply_rule(const char *rule) {
47 int r;
48
49 delete_rule(rule);
25
Calling 'delete_rule'
50
51 r = write_string_file("/proc/sys/fs/binfmt_misc/register", rule, 0);
52 if (r < 0)
53 return log_error_errno(r, "Failed to add binary format: %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/binfmt/binfmt.c", 53, __func__, "Failed to add binary format: %m"
) : -abs(_e); })
;
54
55 return 0;
56}
57
58static int apply_file(const char *path, bool_Bool ignore_enoent) {
59 _cleanup_fclose___attribute__((cleanup(fclosep))) FILE *f = NULL((void*)0);
60 int r;
61
62 assert(path)do { if ((__builtin_expect(!!(!(path)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("path"), "../src/binfmt/binfmt.c", 62, __PRETTY_FUNCTION__
); } while (0)
;
11
Taking false branch
12
Loop condition is false. Exiting loop
63
64 r = search_and_fopen(path, "re", NULL((void*)0), (const char**) CONF_PATHS_STRV("binfmt.d")((char**) ((const char*[]) { "/etc/" "binfmt.d", "/run/" "binfmt.d"
, "/usr/local/lib/" "binfmt.d", "/usr/lib/" "binfmt.d", ((void
*)0) }))
, &f);
65 if (r < 0) {
13
Assuming 'r' is >= 0
14
Taking false branch
66 if (ignore_enoent && r == -ENOENT2)
67 return 0;
68
69 return log_error_errno(r, "Failed to open file '%s', ignoring: %m", path)({ 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/binfmt/binfmt.c", 69, __func__, "Failed to open file '%s', ignoring: %m"
, path) : -abs(_e); })
;
70 }
71
72 log_debug("apply: %s", path)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/binfmt/binfmt.c", 72, __func__, "apply: %s", path) :
-abs(_e); })
;
15
Assuming the condition is false
16
'?' condition is false
73 for (;;) {
17
Loop condition is true. Entering loop body
74 char l[LINE_MAX2048], *p;
75 int k;
76
77 if (!fgets(l, sizeof(l), f)) {
18
Assuming the condition is false
19
Taking false branch
78 if (feof(f))
79 break;
80
81 return log_error_errno(errno, "Failed to read file '%s', ignoring: %m", path)({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/binfmt/binfmt.c", 81, __func__, "Failed to read file '%s', ignoring: %m"
, path) : -abs(_e); })
;
82 }
83
84 p = strstrip(l);
85 if (!*p)
20
Assuming the condition is false
21
Taking false branch
86 continue;
87 if (strchr(COMMENTS"#;" "\n", *p))
22
Assuming the condition is false
23
Taking false branch
88 continue;
89
90 k = apply_rule(p);
24
Calling 'apply_rule'
91 if (k < 0 && r == 0)
92 r = k;
93 }
94
95 return r;
96}
97
98static void help(void) {
99 printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
100 "Registers binary formats.\n\n"
101 " -h --help Show this help\n"
102 " --version Show package version\n"
103 " --cat-config Show configuration files\n"
104 " --no-pager Do not pipe output into a pager\n"
105 , program_invocation_short_name);
106}
107
108static int parse_argv(int argc, char *argv[]) {
109
110 enum {
111 ARG_VERSION = 0x100,
112 ARG_CAT_CONFIG,
113 ARG_NO_PAGER,
114 };
115
116 static const struct option options[] = {
117 { "help", no_argument0, NULL((void*)0), 'h' },
118 { "version", no_argument0, NULL((void*)0), ARG_VERSION },
119 { "cat-config", no_argument0, NULL((void*)0), ARG_CAT_CONFIG },
120 { "no-pager", no_argument0, NULL((void*)0), ARG_NO_PAGER },
121 {}
122 };
123
124 int c;
125
126 assert(argc >= 0)do { if ((__builtin_expect(!!(!(argc >= 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("argc >= 0"), "../src/binfmt/binfmt.c"
, 126, __PRETTY_FUNCTION__); } while (0)
;
127 assert(argv)do { if ((__builtin_expect(!!(!(argv)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("argv"), "../src/binfmt/binfmt.c", 127, __PRETTY_FUNCTION__
); } while (0)
;
128
129 while ((c = getopt_long(argc, argv, "h", options, NULL((void*)0))) >= 0)
130
131 switch (c) {
132
133 case 'h':
134 help();
135 return 0;
136
137 case ARG_VERSION:
138 return version();
139
140 case ARG_CAT_CONFIG:
141 arg_cat_config = true1;
142 break;
143
144 case ARG_NO_PAGER:
145 arg_no_pager = true1;
146 break;
147
148 case '?':
149 return -EINVAL22;
150
151 default:
152 assert_not_reached("Unhandled option")do { log_assert_failed_unreachable_realm(LOG_REALM_SYSTEMD, (
"Unhandled option"), "../src/binfmt/binfmt.c", 152, __PRETTY_FUNCTION__
); } while (0)
;
153 }
154
155 if (arg_cat_config && argc > optind) {
156 log_error("Positional arguments are not allowed with --cat-config")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/binfmt/binfmt.c", 156, __func__, "Positional arguments are not allowed with --cat-config"
) : -abs(_e); })
;
157 return -EINVAL22;
158 }
159
160 return 1;
161}
162
163int main(int argc, char *argv[]) {
164 int r, k;
165
166 r = parse_argv(argc, argv);
167 if (r <= 0)
1
Assuming 'r' is > 0
2
Taking false branch
168 return r < 0 ? EXIT_FAILURE1 : EXIT_SUCCESS0;
169
170 log_set_target(LOG_TARGET_AUTO);
171 log_parse_environment()log_parse_environment_realm(LOG_REALM_SYSTEMD);
172 log_open();
173
174 umask(0022);
175
176 r = 0;
177
178 if (argc > optind) {
3
Assuming 'argc' is <= 'optind'
4
Taking false branch
179 int i;
180
181 for (i = optind; i < argc; i++) {
182 k = apply_file(argv[i], false0);
183 if (k < 0 && r == 0)
184 r = k;
185 }
186 } else {
187 _cleanup_strv_free___attribute__((cleanup(strv_freep))) char **files = NULL((void*)0);
188 char **f;
189
190 r = conf_files_list_strv(&files, ".conf", NULL((void*)0), 0, (const char**) CONF_PATHS_STRV("binfmt.d")((char**) ((const char*[]) { "/etc/" "binfmt.d", "/run/" "binfmt.d"
, "/usr/local/lib/" "binfmt.d", "/usr/lib/" "binfmt.d", ((void
*)0) }))
);
191 if (r < 0) {
5
Assuming 'r' is >= 0
6
Taking false branch
192 log_error_errno(r, "Failed to enumerate binfmt.d files: %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/binfmt/binfmt.c", 192, __func__, "Failed to enumerate binfmt.d files: %m"
) : -abs(_e); })
;
193 goto finish;
194 }
195
196 if (arg_cat_config
6.1
'arg_cat_config' is false
) {
7
Taking false branch
197 (void) pager_open(arg_no_pager, false0);
198
199 r = cat_files(NULL((void*)0), files, 0);
200 goto finish;
201 }
202
203 /* Flush out all rules */
204 write_string_file("/proc/sys/fs/binfmt_misc/status", "-1", 0);
205
206 STRV_FOREACH(f, files)for ((f) = (files); (f) && *(f); (f)++) {
8
Assuming 'f' is non-null
9
Loop condition is true. Entering loop body
207 k = apply_file(*f, true1);
10
Calling 'apply_file'
208 if (k < 0 && r == 0)
209 r = k;
210 }
211 }
212
213finish:
214 pager_close();
215
216 return r < 0 ? EXIT_FAILURE1 : EXIT_SUCCESS0;
217}