Bug Summary

File:bin/lwan/main.c
Warning:line 301, column 5
Potential leak of memory pointed to by 'c.ssl.cert'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name main.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 -pic-is-pie -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -fno-plt -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/home/buildbot/lwan-worker/clang-analyze/build/src/bin/lwan -resource-dir /usr/lib/clang/14.0.6 -include /home/buildbot/lwan-worker/clang-analyze/build/lwan-build-config.h -D _FILE_OFFSET_BITS=64 -D _TIME_BITS=64 -I /home/buildbot/lwan-worker/clang-analyze/build -I /home/buildbot/lwan-worker/clang-analyze/build/src/lib/missing -I /usr/include/luajit-2.1 -I /usr/include/valgrind -I /home/buildbot/lwan-worker/clang-analyze/build/src/lib -internal-isystem /usr/lib/clang/14.0.6/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/12.2.0/../../../../x86_64-pc-linux-gnu/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-unused-parameter -Wno-free-nonheap-object -std=gnu11 -fdebug-compilation-dir=/home/buildbot/lwan-worker/clang-analyze/build/src/bin/lwan -ferror-limit 19 -stack-protector 2 -fgnuc-version=4.2.1 -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/buildbot/lwan-worker/clang-analyze/CLANG/2023-01-03-043944-1058096-1 -x c /home/buildbot/lwan-worker/clang-analyze/build/src/bin/lwan/main.c
1/*
2 * lwan - web server
3 * Copyright (c) 2012 L. A. F. Pereira <l@tia.mat.br>
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 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 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */
19
20#define _GNU_SOURCE
21#include <getopt.h>
22#include <stdlib.h>
23#include <unistd.h>
24#include <limits.h>
25
26#include "lwan-private.h"
27#include "lwan-mod-serve-files.h"
28
29enum args {
30 ARGS_FAILED,
31 ARGS_USE_CONFIG,
32 ARGS_SERVE_FILES
33};
34
35static void print_module_info(void)
36{
37 const struct lwan_module_info *module;
38
39 printf("Built-in modules:");
40 LWAN_SECTION_FOREACH(lwan_module, module)for (module = ({ extern const typeof(*module) __start_lwan_module
[]; __start_lwan_module; }); module < ({ extern const typeof
(*module) __stop_lwan_module[]; __stop_lwan_module; }); (module
)++)
{
41 printf(" %s", module->name);
42 }
43 printf(".\n");
44}
45
46static void
47print_handler_info(void)
48{
49 const struct lwan_handler_info *handler;
50
51 printf("Built-in handlers:");
52 LWAN_SECTION_FOREACH(lwan_handler, handler)for (handler = ({ extern const typeof(*handler) __start_lwan_handler
[]; __start_lwan_handler; }); handler < ({ extern const typeof
(*handler) __stop_lwan_handler[]; __stop_lwan_handler; }); (handler
)++)
{
53 printf(" %s", handler->name);
54 }
55 printf(".\n");
56}
57
58static void
59print_build_time_configuration(void)
60{
61 printf("Build-time configuration:");
62#ifdef LWAN_HAVE_LUA
63 printf(" Lua");
64#endif
65#ifdef LWAN_HAVE_BROTLI
66 printf(" Brotli");
67#endif
68#ifdef LWAN_HAVE_ZSTD
69 printf(" zstd");
70#endif
71#ifdef LWAN_HAVE_MBEDTLS
72 printf(" mbedTLS");
73#endif
74#ifdef LWAN_HAVE_LIBUCONTEXT
75 printf(" libucontext");
76#endif
77#ifdef LWAN_HAVE_EPOLL
78 printf(" epoll");
79#endif
80#ifdef LWAN_HAVE_KQUEUE
81 printf(" kqueue");
82#endif
83#ifdef LWAN_HAVE_SO_ATTACH_REUSEPORT_CBPF
84 printf(" sockopt-reuseport-CBPF");
85#endif
86#ifdef LWAN_HAVE_SO_INCOMING_CPU
87 printf(" sockopt-reuseport-incoming-cpu");
88#endif
89#ifdef LWAN_HAVE_VALGRIND
90 printf(" valgrind");
91#endif
92#ifdef LWAN_HAVE_SYSLOG
93 printf(" syslog");
94#endif
95#ifdef HAVE_PYTHON
96 printf(" python");
97#endif
98 printf(".\n");
99}
100
101static void
102print_help(const char *argv0, const struct lwan_config *config)
103{
104 char path_buf[PATH_MAX4096];
105 char *current_dir = get_current_dir_name();
106 const char *config_file = lwan_get_config_path(path_buf, sizeof(path_buf));
107
108 printf("Usage: %s [--root /path/to/root/dir] [--listen addr:port]\n", argv0);
109 printf(" [--config] [--user username] [--chroot] [--modules|--handlers]\n");
110 printf("\n");
111#ifdef LWAN_HAVE_MBEDTLS
112 printf("Serve files through HTTP or HTTPS.\n\n");
113#else
114 printf("Serve files through HTTP.\n\n");
115#endif
116 printf("Options:\n");
117 printf(" -r, --root Path to serve files from (default: ./wwwroot).\n");
118 printf("\n");
119 printf(" -l, --listen Listener (default: %s).\n", config->listener);
120#ifdef LWAN_HAVE_MBEDTLS
121 printf(" -L, --tls-listen TLS Listener (default: %s).\n",
122 config->tls_listener ?
123 config->tls_listener : "not listening");
124#endif
125 printf("\n");
126 printf(" -c, --config Path to config file path.\n");
127 printf(" -u, --user Username to drop privileges to (root required).\n");
128 printf(" -C, --chroot Chroot to path passed to --root (root required).\n");
129#ifdef LWAN_HAVE_MBEDTLS
130 printf("\n");
131 printf(" -P, --cert-path Path to TLS certificate.\n");
132 printf(" -K, --cert-key Path to TLS key.\n");
133#endif
134 printf("\n");
135 printf(" -h, --help This.\n");
136 printf("\n");
137 printf("Examples:\n");
138 if (!access("/usr/share/doc", R_OK4)) {
139 printf(" Serve system-wide documentation:\n");
140 printf(" %s -r /usr/share/doc\n", argv0);
141 }
142 printf(" Serve on a different port:\n");
143 printf(" %s -l '*:1337'\n", argv0);
144 printf(" Use %s from %s:\n", config_file, current_dir);
145 printf(" %s\n", argv0);
146 printf(" Use /etc/%s:\n", config_file);
147 printf(" %s -c /etc/%s\n", argv0, config_file);
148#ifdef LWAN_HAVE_MBEDTLS
149 printf(" Serve system docs with HTTP and HTTPS:\n");
150 printf(" %s -P /path/to/cert.pem -K /path/to/cert.key \\\n"
151 " -l '*:8080' -L '*:8081' -r /usr/share/doc\n", argv0);
152#endif
153 printf("\n");
154 print_build_time_configuration();
155 print_module_info();
156 print_handler_info();
157 printf("\n");
158 printf("Report bugs at <https://github.com/lpereira/lwan>.\n");
159 printf("For security-related reports, mail them to <security@tia.mat.br>.\n");
160
161 free(current_dir);
162}
163
164static enum args
165parse_args(int argc, char *argv[], struct lwan_config *config, char *root,
166 struct lwan_straitjacket *sj)
167{
168 static const struct option opts[] = {
169 { .name = "root", .has_arg = 1, .val = 'r' },
170 { .name = "listen", .has_arg = 1, .val = 'l' },
171 { .name = "help", .val = 'h' },
172 { .name = "config", .has_arg = 1, .val = 'c' },
173 { .name = "chroot", .val = 'C' },
174 { .name = "user", .val = 'u', .has_arg = 1 },
175#ifdef LWAN_HAVE_MBEDTLS
176 { .name = "tls-listen", .val = 'L', .has_arg = 1 },
177 { .name = "cert-path", .val = 'P', .has_arg = 1 },
178 { .name = "cert-key", .val = 'K', .has_arg = 1 },
179#endif
180 { }
181 };
182 int c, optidx = 0;
183 enum args result = ARGS_USE_CONFIG;
184
185 while ((c = getopt_long(argc, argv, "L:P:K:hr:l:c:u:C", opts, &optidx)) != -1) {
4
Assuming the condition is true
5
Loop condition is true. Entering loop body
8
Execution continues on line 185
9
Assuming the condition is true
10
Loop condition is true. Entering loop body
186 switch (c) {
6
Control jumps to 'case 80:' at line 194
11
Control jumps to the 'default' case at line 242
187#ifdef LWAN_HAVE_MBEDTLS
188 case 'L':
189 free(config->tls_listener);
190 config->tls_listener = strdup(optarg);
191 result = ARGS_SERVE_FILES;
192 break;
193
194 case 'P':
195 free(config->ssl.cert);
196 config->ssl.cert = strdup(optarg);
7
Memory is allocated
197 break;
198
199 case 'K':
200 free(config->ssl.key);
201 config->ssl.key = strdup(optarg);
202 break;
203#endif
204 case 'u':
205 free((char *)sj->user_name);
206 sj->user_name = (const char *)strdup(optarg);
207 break;
208
209 case 'C':
210 sj->chroot_path = root;
211 break;
212
213 case 'c':
214 free(config->config_file_path);
215 config->config_file_path = strdup(optarg);
216 result = ARGS_USE_CONFIG;
217 break;
218
219 case 'l':
220 free(config->listener);
221 config->listener = strdup(optarg);
222 result = ARGS_SERVE_FILES;
223 break;
224
225 case 'r': {
226 size_t len = strlen(optarg);
227
228 if (len >= PATH_MAX4096) {
229 fprintf(stderrstderr, "Root path length exeeds %d characters\n", PATH_MAX4096);
230 return ARGS_FAILED;
231 }
232
233 memcpy(root, optarg, len + 1);
234 result = ARGS_SERVE_FILES;
235 break;
236 }
237
238 case 'h':
239 print_help(argv[0], config);
240 return ARGS_FAILED;
241
242 default:
243 printf("Run %s --help for usage information.\n", argv[0]);
244 return ARGS_FAILED;
245 }
246 }
247
248 return result;
249}
250
251int
252main(int argc, char *argv[])
253{
254 struct lwan l;
255 struct lwan_config c;
256 struct lwan_straitjacket sj = {};
257 char root_buf[PATH_MAX4096];
258 char *root = root_buf;
259 int ret = EXIT_SUCCESS0;
260
261 if (!getcwd(root, PATH_MAX4096))
1
Assuming the condition is false
2
Taking false branch
262 return 1;
263
264 c = *lwan_get_default_config();
265 c.listener = strdup("*:8080");
266
267 switch (parse_args(argc, argv, &c, root, &sj)) {
3
Calling 'parse_args'
12
Returned allocated memory
13
Control jumps to 'case ARGS_FAILED:' at line 291
268 case ARGS_SERVE_FILES:
269 lwan_status_info("Serving files from %s", root)lwan_status_info_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/bin/lwan/main.c"
, 269, __FUNCTION__, "Serving files from %s", root)
;
270
271 if (sj.chroot_path) {
272 root = "/";
273 }
274 lwan_straitjacket_enforce(&sj);
275
276 lwan_init_with_config(&l, &c);
277
278 const struct lwan_url_map map[] = {
279 { .prefix = "/", SERVE_FILES_SETTINGS(root, "index.html", true).module = lwan_module_info_serve_files.module, .args = ((struct
lwan_serve_files_settings[]) {{ .read_ahead = (128 * 1024), .
root_path = root, .index_html = "index.html", .serve_precompressed_files
= 1, .directory_list_template = ((void*)0), .auto_index = 1,
.auto_index_readme = 1, .cache_for = 5, }}), .flags = (enum lwan_handler_flags
)0
},
280 { }
281 };
282 lwan_set_url_map(&l, map);
283 break;
284 case ARGS_USE_CONFIG:
285 lwan_straitjacket_enforce(&sj);
286 if (c.config_file_path)
287 lwan_init_with_config(&l, &c);
288 else
289 lwan_init(&l);
290 break;
291 case ARGS_FAILED:
292 ret = EXIT_FAILURE1;
293 goto out;
14
Control jumps to line 300
294 }
295
296 lwan_main_loop(&l);
297 lwan_shutdown(&l);
298
299out:
300 free(c.listener);
301 free(c.config_file_path);
15
Potential leak of memory pointed to by 'c.ssl.cert'
302 free((char *)sj.user_name);
303
304 return ret;
305}