Bug Summary

File:bin/lwan/main.c
Warning:line 294, 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/2022-10-12-052144-3323220-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 printf("Serve files through HTTP.\n\n");
112 printf("Options:\n");
113 printf(" -r, --root Path to serve files from (default: ./wwwroot).\n");
114 printf("\n");
115 printf(" -l, --listen Listener (default: %s).\n", config->listener);
116#ifdef LWAN_HAVE_MBEDTLS
117 printf(" -L, --tls-listen TLS Listener (default: %s).\n",
118 config->tls_listener ?
119 config->tls_listener : "not listening");
120#endif
121 printf("\n");
122 printf(" -c, --config Path to config file path.\n");
123 printf(" -u, --user Username to drop privileges to (root required).\n");
124 printf(" -C, --chroot Chroot to path passed to --root (root required).\n");
125#ifdef LWAN_HAVE_MBEDTLS
126 printf("\n");
127 printf(" -P, --cert-path Path to TLS certificate.\n");
128 printf(" -K, --cert-key Path to TLS key.\n");
129#endif
130 printf("\n");
131 printf(" -h, --help This.\n");
132 printf("\n");
133 printf("Examples:\n");
134 printf(" Serve system-wide documentation:\n");
135 printf(" %s -r /usr/share/doc\n", argv0);
136 printf(" Serve on a different port:\n");
137 printf(" %s -l '*:1337'\n", argv0);
138 printf(" Use %s from %s:\n", config_file, current_dir);
139 printf(" %s\n", argv0);
140 printf(" Use /etc/%s:\n", config_file);
141 printf(" %s -c /etc/%s\n", argv0, config_file);
142#ifdef LWAN_HAVE_MBEDTLS
143 printf(" Serve system docs with HTTP and HTTPS:\n");
144 printf(" %s -P /path/to/cert.pem -K /path/to/cert.key \\\n"
145 " -l '*:8080' -L '*:8081' -r /usr/share/doc\n", argv0);
146#endif
147 printf("\n");
148 print_build_time_configuration();
149 print_module_info();
150 print_handler_info();
151 printf("\n");
152 printf("Report bugs at <https://github.com/lpereira/lwan>.\n");
153
154 free(current_dir);
155}
156
157static enum args
158parse_args(int argc, char *argv[], struct lwan_config *config, char *root,
159 struct lwan_straitjacket *sj)
160{
161 static const struct option opts[] = {
162 { .name = "root", .has_arg = 1, .val = 'r' },
163 { .name = "listen", .has_arg = 1, .val = 'l' },
164 { .name = "help", .val = 'h' },
165 { .name = "config", .has_arg = 1, .val = 'c' },
166 { .name = "chroot", .val = 'C' },
167 { .name = "user", .val = 'u', .has_arg = 1 },
168#ifdef LWAN_HAVE_MBEDTLS
169 { .name = "tls-listen", .val = 'L', .has_arg = 1 },
170 { .name = "cert-path", .val = 'P', .has_arg = 1 },
171 { .name = "cert-key", .val = 'K', .has_arg = 1 },
172#endif
173 { }
174 };
175 int c, optidx = 0;
176 enum args result = ARGS_USE_CONFIG;
177
178 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 178
9
Assuming the condition is true
10
Loop condition is true. Entering loop body
179 switch (c) {
6
Control jumps to 'case 80:' at line 187
11
Control jumps to the 'default' case at line 235
180#ifdef LWAN_HAVE_MBEDTLS
181 case 'L':
182 free(config->tls_listener);
183 config->tls_listener = strdup(optarg);
184 result = ARGS_SERVE_FILES;
185 break;
186
187 case 'P':
188 free(config->ssl.cert);
189 config->ssl.cert = strdup(optarg);
7
Memory is allocated
190 break;
191
192 case 'K':
193 free(config->ssl.key);
194 config->ssl.key = strdup(optarg);
195 break;
196#endif
197 case 'u':
198 free((char *)sj->user_name);
199 sj->user_name = (const char *)strdup(optarg);
200 break;
201
202 case 'C':
203 sj->chroot_path = root;
204 break;
205
206 case 'c':
207 free(config->config_file_path);
208 config->config_file_path = strdup(optarg);
209 result = ARGS_USE_CONFIG;
210 break;
211
212 case 'l':
213 free(config->listener);
214 config->listener = strdup(optarg);
215 result = ARGS_SERVE_FILES;
216 break;
217
218 case 'r': {
219 size_t len = strlen(optarg);
220
221 if (len >= PATH_MAX4096) {
222 fprintf(stderrstderr, "Root path length exeeds %d characters\n", PATH_MAX4096);
223 return ARGS_FAILED;
224 }
225
226 memcpy(root, optarg, len + 1);
227 result = ARGS_SERVE_FILES;
228 break;
229 }
230
231 case 'h':
232 print_help(argv[0], config);
233 return ARGS_FAILED;
234
235 default:
236 printf("Run %s --help for usage information.\n", argv[0]);
237 return ARGS_FAILED;
238 }
239 }
240
241 return result;
242}
243
244int
245main(int argc, char *argv[])
246{
247 struct lwan l;
248 struct lwan_config c;
249 struct lwan_straitjacket sj = {};
250 char root_buf[PATH_MAX4096];
251 char *root = root_buf;
252 int ret = EXIT_SUCCESS0;
253
254 if (!getcwd(root, PATH_MAX4096))
1
Assuming the condition is false
2
Taking false branch
255 return 1;
256
257 c = *lwan_get_default_config();
258 c.listener = strdup("*:8080");
259
260 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 284
261 case ARGS_SERVE_FILES:
262 lwan_status_info("Serving files from %s", root)lwan_status_info_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/bin/lwan/main.c"
, 262, __FUNCTION__, "Serving files from %s", root)
;
263
264 if (sj.chroot_path) {
265 root = "/";
266 }
267 lwan_straitjacket_enforce(&sj);
268
269 lwan_init_with_config(&l, &c);
270
271 const struct lwan_url_map map[] = {
272 { .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
},
273 { }
274 };
275 lwan_set_url_map(&l, map);
276 break;
277 case ARGS_USE_CONFIG:
278 lwan_straitjacket_enforce(&sj);
279 if (c.config_file_path)
280 lwan_init_with_config(&l, &c);
281 else
282 lwan_init(&l);
283 break;
284 case ARGS_FAILED:
285 ret = EXIT_FAILURE1;
286 goto out;
14
Control jumps to line 293
287 }
288
289 lwan_main_loop(&l);
290 lwan_shutdown(&l);
291
292out:
293 free(c.listener);
294 free(c.config_file_path);
15
Potential leak of memory pointed to by 'c.ssl.cert'
295 free((char *)sj.user_name);
296
297 return ret;
298}