Bug Summary

File:lwan.c
Warning:line 334, column 17
Potential memory leak

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name lwan.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 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -fno-plt -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib/clang/11.1.0 -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/src/lib/missing -I /usr/include/luajit-2.0 -I /usr/include/valgrind -I /home/buildbot/lwan-worker/clang-analyze/build/src/lib -I /home/buildbot/lwan-worker/clang-analyze/build -internal-isystem /usr/local/include -internal-isystem /usr/lib/clang/11.1.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-unused-parameter -Wno-free-nonheap-object -std=gnu99 -fdebug-compilation-dir /home/buildbot/lwan-worker/clang-analyze/build/src/lib -ferror-limit 19 -stack-protector 2 -fgnuc-version=4.2.1 -analyzer-output=html -faddrsig -o /home/buildbot/lwan-worker/clang-analyze/CLANG/2021-05-16-151938-405757-1 -x c /home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c
1/*
2 * lwan - simple web server
3 * Copyright (c) 2012, 2013 Leandro A. F. Pereira <leandro@hardinfo.org>
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,
18 * USA.
19 */
20
21#define _GNU_SOURCE
22#include <assert.h>
23#include <ctype.h>
24#include <dlfcn.h>
25#include <errno(*__errno_location ()).h>
26#include <fcntl.h>
27#include <libproc.h>
28#include <limits.h>
29#include <signal.h>
30#include <stdlib.h>
31#include <string.h>
32#include <sys/resource.h>
33#include <sys/socket.h>
34#include <sys/types.h>
35#include <unistd.h>
36
37#include "lwan-private.h"
38
39#include "lwan-config.h"
40#include "lwan-http-authorize.h"
41
42#if defined(HAVE_LUA)
43#include "lwan-lua.h"
44#endif
45
46/* Ideally, this would check if all items in enum lwan_request_flags,
47 * when bitwise-or'd together, would not have have any bit set that
48 * is also set in REQUEST_METHOD_MASK. */
49static_assert(REQUEST_ACCEPT_DEFLATE > REQUEST_METHOD_MASK,extern int (*__Static_assert_function (void)) [!!sizeof (struct
{ int __error_if_negative: (REQUEST_ACCEPT_DEFLATE > REQUEST_METHOD_MASK
) ? 2 : -1; })]
50 "enough bits to store request methods")extern int (*__Static_assert_function (void)) [!!sizeof (struct
{ int __error_if_negative: (REQUEST_ACCEPT_DEFLATE > REQUEST_METHOD_MASK
) ? 2 : -1; })]
;
51
52/* See detect_fastest_monotonic_clock() */
53clockid_t monotonic_clock_id = CLOCK_MONOTONIC1;
54
55static const struct lwan_config default_config = {
56 .listener = "localhost:8080",
57 .keep_alive_timeout = 15,
58 .quiet = false0,
59 .proxy_protocol = false0,
60 .allow_cors = false0,
61 .expires = 1 * ONE_WEEK(((60 * 60) * 24) * 7),
62 .n_threads = 0,
63 .max_post_data_size = 10 * DEFAULT_BUFFER_SIZE4096,
64 .allow_post_temp_file = false0,
65 .max_put_data_size = 10 * DEFAULT_BUFFER_SIZE4096,
66 .allow_put_temp_file = false0,
67};
68
69LWAN_HANDLER(brew_coffee)static enum lwan_http_status lwan_handler_brew_coffee( struct
lwan_request *, struct lwan_response *, void *); static const
struct lwan_handler_info __attribute__((used, section("lwan_handler"
))) lwan_handler_info_brew_coffee = {.name = "brew_coffee", .
handler = lwan_handler_brew_coffee}; static enum lwan_http_status
lwan_handler_brew_coffee( struct lwan_request *request __attribute__
((unused)), struct lwan_response *response __attribute__((unused
)), void *data __attribute__((unused)))
70{
71 /* Placeholder handler so that __start_lwan_handler and __stop_lwan_handler
72 * symbols will get defined.
73 */
74 return HTTP_I_AM_A_TEAPOT;
75}
76
77__attribute__((no_sanitize_address))
78static void *find_handler(const char *name)
79{
80 const struct lwan_handler_info *handler;
81
82 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
)++)
{
83 if (streq(handler->name, name))
84 return handler->handler;
85 }
86
87 return NULL((void*)0);
88}
89
90__attribute__((no_sanitize_address))
91static const struct lwan_module *find_module(const char *name)
92{
93 const struct lwan_module_info *module;
94
95 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
)++)
{
96 if (streq(module->name, name))
97 return module->module;
98 }
99
100 return NULL((void*)0);
101}
102
103static void destroy_urlmap(void *data)
104{
105 struct lwan_url_map *url_map = data;
106
107 if (url_map->module) {
108 const struct lwan_module *module = url_map->module;
109
110 if (module->destroy)
111 module->destroy(url_map->data);
112 } else if (url_map->data && url_map->flags & HANDLER_DATA_IS_HASH_TABLE) {
113 hash_free(url_map->data);
114 }
115
116 free(url_map->authorization.realm);
117 free(url_map->authorization.password_file);
118 free((char *)url_map->prefix);
119 free(url_map);
120}
121
122static struct lwan_url_map *add_url_map(struct lwan_trie *t, const char *prefix,
123 const struct lwan_url_map *map)
124{
125 struct lwan_url_map *copy = malloc(sizeof(*copy));
126
127 if (!copy)
128 lwan_status_critical_perror("Could not copy URL map")lwan_status_critical_perror_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 128, __FUNCTION__, "Could not copy URL map")
;
129
130 memcpy(copy, map, sizeof(*copy));
131
132 copy->prefix = strdup(prefix ? prefix : copy->prefix);
133 if (!copy->prefix)
134 lwan_status_critical_perror("Could not copy URL prefix")lwan_status_critical_perror_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 134, __FUNCTION__, "Could not copy URL prefix")
;
135
136 copy->prefix_len = strlen(copy->prefix);
137 lwan_trie_add(t, copy->prefix, copy);
138
139 return copy;
140}
141
142static bool_Bool can_override_header(const char *name)
143{
144 /* NOTE: Update lwan_prepare_response_header_full() in lwan-response.c
145 * if new headers are added here. */
146
147 if (!strcasecmp(name, "Date"))
148 return false0;
149 if (!strcasecmp(name, "Expires"))
150 return false0;
151 if (!strcasecmp(name, "WWW-Authenticate"))
152 return false0;
153 if (!strcasecmp(name, "Connection"))
154 return false0;
155 if (!strcasecmp(name, "Content-Type"))
156 return false0;
157 if (!strcasecmp(name, "Transfer-Encoding"))
158 return false0;
159 if (!strncasecmp(name, "Access-Control-Allow-",
160 sizeof("Access-Control-Allow-") - 1))
161 return false0;
162
163 return true1;
164}
165
166static void build_response_headers(struct lwan *l,
167 const struct lwan_key_value *kv)
168{
169 bool_Bool set_server = false0;
170
171 assert(l)((void) sizeof ((l) ? 1 : 0), __extension__ ({ if (l) ; else __assert_fail
("l", "/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 171, __extension__ __PRETTY_FUNCTION__); }))
;
172
173 lwan_strbuf_init(&l->headers);
174
175 for (; kv && kv->key; kv++) {
176 if (!can_override_header(kv->key)) {
177 lwan_status_warning("Cannot override header '%s'", kv->key)lwan_status_warning_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 177, __FUNCTION__, "Cannot override header '%s'", kv->key
)
;
178 } else {
179 if (!strcasecmp(kv->key, "Server"))
180 set_server = true1;
181
182 lwan_strbuf_append_printf(&l->headers, "\r\n%s: %s", kv->key,
183 kv->value);
184 }
185 }
186
187 if (!set_server)
188 lwan_strbuf_append_strz(&l->headers, "\r\nServer: lwan");
189
190 lwan_strbuf_append_strz(&l->headers, "\r\n\r\n");
191}
192
193static void parse_global_headers(struct config *c,
194 struct lwan *lwan)
195{
196 struct lwan_key_value_array hdrs;
197 const struct config_line *l;
198 struct lwan_key_value *kv;
199
200 lwan_key_value_array_init(&hdrs);
201
202 while ((l = config_read_line(c))) {
203 switch (l->type) {
204 case CONFIG_LINE_TYPE_SECTION:
205 config_error(
206 c, "No sections are supported under the 'headers' section");
207 goto cleanup;
208
209 case CONFIG_LINE_TYPE_LINE:
210 kv = lwan_key_value_array_append(&hdrs);
211 if (!kv) {
212 lwan_status_critical_perror(lwan_status_critical_perror_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 213, __FUNCTION__, "Could not allocate memory for custom response header"
)
213 "Could not allocate memory for custom response header")lwan_status_critical_perror_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 213, __FUNCTION__, "Could not allocate memory for custom response header"
)
;
214 }
215
216 kv->key = strdup(l->key);
217 if (!kv->key) {
218 lwan_status_critical_perror(lwan_status_critical_perror_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 219, __FUNCTION__, "Could not allocate memory for custom response header"
)
219 "Could not allocate memory for custom response header")lwan_status_critical_perror_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 219, __FUNCTION__, "Could not allocate memory for custom response header"
)
;
220 }
221
222 kv->value = strdup(l->value);
223 if (!kv->value) {
224 lwan_status_critical_perror(lwan_status_critical_perror_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 225, __FUNCTION__, "Could not allocate memory for custom response header"
)
225 "Could not allocate memory for custom response header")lwan_status_critical_perror_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 225, __FUNCTION__, "Could not allocate memory for custom response header"
)
;
226 }
227 break;
228
229 case CONFIG_LINE_TYPE_SECTION_END:
230 kv = lwan_key_value_array_append(&hdrs);
231 if (!kv) {
232 lwan_status_critical_perror(lwan_status_critical_perror_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 233, __FUNCTION__, "Could not allocate memory for custom response header"
)
233 "Could not allocate memory for custom response header")lwan_status_critical_perror_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 233, __FUNCTION__, "Could not allocate memory for custom response header"
)
;
234 }
235
236 kv->key = NULL((void*)0);
237 kv->value = NULL((void*)0);
238
239 build_response_headers(lwan, lwan_key_value_array_get_array(&hdrs));
240 goto cleanup;
241 }
242 }
243
244 config_error(c, "EOF while looking for end of 'headers' section");
245
246cleanup:
247 LWAN_ARRAY_FOREACH (&hdrs, kv)for (kv = (&hdrs)->base.base; kv < ((typeof(kv))(&
hdrs)->base.base + (&hdrs)->base.elements); kv++)
{
248 free(kv->key);
249 free(kv->value);
250 }
251 lwan_key_value_array_reset(&hdrs);
252}
253
254static void parse_listener_prefix_authorization(struct config *c,
255 const struct config_line *l,
256 struct lwan_url_map *url_map)
257{
258 if (!streq(l->value, "basic")) {
259 config_error(c, "Only basic authorization supported");
260 return;
261 }
262
263 memset(&url_map->authorization, 0, sizeof(url_map->authorization));
264
265 while ((l = config_read_line(c))) {
266 switch (l->type) {
267 case CONFIG_LINE_TYPE_LINE:
268 if (streq(l->key, "realm")) {
269 free(url_map->authorization.realm);
270 url_map->authorization.realm = strdup(l->value);
271 } else if (streq(l->key, "password_file")) {
272 free(url_map->authorization.password_file);
273 url_map->authorization.password_file = realpath(l->value, NULL((void*)0));
274 if (!url_map->authorization.password_file)
275 config_error(c, "Could not determine full path for password file: %s", l->value);
276 }
277 break;
278
279 case CONFIG_LINE_TYPE_SECTION:
280 config_error(c, "Unexpected section: %s", l->key);
281 goto error;
282
283 case CONFIG_LINE_TYPE_SECTION_END:
284 if (!url_map->authorization.realm)
285 url_map->authorization.realm = strdup("Lwan");
286 if (!url_map->authorization.password_file)
287 url_map->authorization.password_file = strdup("htpasswd");
288
289 url_map->flags |= HANDLER_MUST_AUTHORIZE;
290 return;
291 }
292 }
293
294 config_error(c, "Could not find end of authorization section");
295
296error:
297 free(url_map->authorization.realm);
298 free(url_map->authorization.password_file);
299}
300
301__attribute__((no_sanitize_address))
302static const char *get_module_name(const struct lwan_module *module)
303{
304 const struct lwan_module_info *iter;
305
306 LWAN_SECTION_FOREACH(lwan_module, iter)for (iter = ({ extern const typeof(*iter) __start_lwan_module
[]; __start_lwan_module; }); iter < ({ extern const typeof
(*iter) __stop_lwan_module[]; __stop_lwan_module; }); (iter)++
)
{
307 if (iter->module == module)
308 return iter->name;
309 }
310
311 return "<unknown>";
312}
313
314static void parse_listener_prefix(struct config *c,
315 const struct config_line *l,
316 struct lwan *lwan,
317 const struct lwan_module *module,
318 void *handler)
319{
320 struct lwan_url_map url_map = {};
321 struct hash *hash = hash_str_new(free, free);
322 char *prefix = strdupa(l->value)(__extension__ ({ const char *__old = (l->value); size_t __len
= strlen (__old) + 1; char *__new = (char *) __builtin_alloca
(__len); (char *) memcpy (__new, __old, __len); }))
;
323 struct config *isolated;
324
325 if (!hash)
21
Assuming 'hash' is non-null
22
Taking false branch
326 lwan_status_critical("Could not allocate hash table")lwan_status_critical_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 326, __FUNCTION__, "Could not allocate hash table")
;
327
328 isolated = config_isolate_section(c, l);
329 if (!isolated) {
23
Assuming 'isolated' is non-null
24
Taking false branch
330 config_error(c, "Could not isolate configuration file");
331 goto out;
332 }
333
334 while ((l = config_read_line(c))) {
25
Loop condition is true. Entering loop body
29
Potential memory leak
335 switch (l->type) {
26
Control jumps to 'case CONFIG_LINE_TYPE_LINE:' at line 336
336 case CONFIG_LINE_TYPE_LINE:
337 hash_add(hash, strdup(l->key), strdup(l->value));
27
Memory is allocated
338 break;
28
Execution continues on line 334
339
340 case CONFIG_LINE_TYPE_SECTION:
341 if (streq(l->key, "authorization")) {
342 parse_listener_prefix_authorization(c, l, &url_map);
343 } else if (!config_skip_section(c, l)) {
344 config_error(c, "Could not skip section");
345 goto out;
346 }
347 break;
348
349 case CONFIG_LINE_TYPE_SECTION_END:
350 goto add_map;
351 }
352 }
353
354 config_error(c, "Expecting section end while parsing prefix");
355 goto out;
356
357add_map:
358 assert((handler && !module) || (!handler && module))((void) sizeof (((handler && !module) || (!handler &&
module)) ? 1 : 0), __extension__ ({ if ((handler && !
module) || (!handler && module)) ; else __assert_fail
("(handler && !module) || (!handler && module)"
, "/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 358, __extension__ __PRETTY_FUNCTION__); }))
;
359
360 if (handler) {
361 url_map.handler = handler;
362 url_map.flags |= HANDLER_PARSE_MASK | HANDLER_DATA_IS_HASH_TABLE;
363 url_map.data = hash;
364 url_map.module = NULL((void*)0);
365
366 hash = NULL((void*)0);
367 } else if (module->create_from_hash && module->handle_request) {
368 lwan_status_debug("Initializing module %s from config",lwan_status_debug_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 369, __FUNCTION__, "Initializing module %s from config", get_module_name
(module))
369 get_module_name(module))lwan_status_debug_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 369, __FUNCTION__, "Initializing module %s from config", get_module_name
(module))
;
370
371 url_map.data = module->create_from_hash(prefix, hash);
372 if (!url_map.data) {
373 config_error(c, "Could not create module instance");
374 goto out;
375 }
376
377 if (module->parse_conf && !module->parse_conf(url_map.data, isolated)) {
378 const char *msg = config_last_error(isolated);
379
380 config_error(c, "Error from module: %s", msg ? msg : "Unknown");
381 goto out;
382 }
383
384 url_map.handler = module->handle_request;
385 url_map.flags |= module->flags;
386 url_map.module = module;
387 } else if (UNLIKELY(!module->create_from_hash)__builtin_expect(((!module->create_from_hash)), (0))) {
388 config_error(c, "Module isn't prepared to load settings from a file; "
389 "create_from_hash() method isn't present");
390 goto out;
391 } else if (UNLIKELY(!module->handle_request)__builtin_expect(((!module->handle_request)), (0))) {
392 config_error(c, "Module does not have handle_request() method");
393 goto out;
394 }
395
396 add_url_map(&lwan->url_map_trie, prefix, &url_map);
397
398out:
399 hash_free(hash);
400 config_close(isolated);
401}
402
403void lwan_set_url_map(struct lwan *l, const struct lwan_url_map *map)
404{
405 lwan_trie_destroy(&l->url_map_trie);
406 if (UNLIKELY(!lwan_trie_init(&l->url_map_trie, destroy_urlmap))__builtin_expect(((!lwan_trie_init(&l->url_map_trie, destroy_urlmap
))), (0))
)
407 lwan_status_critical_perror("Could not initialize trie")lwan_status_critical_perror_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 407, __FUNCTION__, "Could not initialize trie")
;
408
409 for (; map->prefix; map++) {
410 struct lwan_url_map *copy = add_url_map(&l->url_map_trie, NULL((void*)0), map);
411
412 if (copy->module && copy->module->create) {
413 lwan_status_debug("Initializing module %s from struct",lwan_status_debug_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 414, __FUNCTION__, "Initializing module %s from struct", get_module_name
(copy->module))
414 get_module_name(copy->module))lwan_status_debug_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 414, __FUNCTION__, "Initializing module %s from struct", get_module_name
(copy->module))
;
415
416 copy->data = copy->module->create(map->prefix, copy->args);
417 if (!copy->data) {
418 lwan_status_critical("Could not initialize module %s",lwan_status_critical_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 419, __FUNCTION__, "Could not initialize module %s", get_module_name
(copy->module))
419 get_module_name(copy->module))lwan_status_critical_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 419, __FUNCTION__, "Could not initialize module %s", get_module_name
(copy->module))
;
420 }
421
422 copy->flags = copy->module->flags;
423 copy->handler = copy->module->handle_request;
424 } else {
425 copy->flags = HANDLER_PARSE_MASK;
426 }
427 }
428}
429
430static void parse_listener(struct config *c,
431 const struct config_line *l,
432 struct lwan *lwan)
433{
434 free(lwan->config.listener);
435 lwan->config.listener = strdup(l->value);
436
437 while ((l = config_read_line(c))) {
14
Loop condition is true. Entering loop body
438 switch (l->type) {
15
Control jumps to 'case CONFIG_LINE_TYPE_SECTION:' at line 442
439 case CONFIG_LINE_TYPE_LINE:
440 config_error(c, "Expecting prefix section");
441 return;
442 case CONFIG_LINE_TYPE_SECTION:
443 if (l->key[0] == '&') {
16
Assuming the condition is false
17
Taking false branch
444 void *handler = find_handler(l->key + 1);
445 if (handler) {
446 parse_listener_prefix(c, l, lwan, NULL((void*)0), handler);
447 continue;
448 }
449
450 config_error(c, "Could not find handler name: %s", l->key + 1);
451 return;
452 }
453
454 const struct lwan_module *module = find_module(l->key);
455 if (module) {
18
Assuming 'module' is non-null
19
Taking true branch
456 parse_listener_prefix(c, l, lwan, module, NULL((void*)0));
20
Calling 'parse_listener_prefix'
457 continue;
458 }
459
460 config_error(c, "Invalid section or module not found: %s", l->key);
461 return;
462 case CONFIG_LINE_TYPE_SECTION_END:
463 return;
464 }
465 }
466
467 config_error(c, "Expecting section end while parsing listener");
468}
469
470const char *lwan_get_config_path(char *path_buf, size_t path_buf_len)
471{
472 char buffer[PATH_MAX4096];
473
474 if (proc_pidpath(getpid(), buffer, sizeof(buffer)) < 0)
475 goto out;
476
477 char *path = strrchr(buffer, '/');
478 if (!path)
479 goto out;
480 int ret = snprintf(path_buf, path_buf_len, "%s.conf", path + 1);
481 if (ret < 0 || ret >= (int)path_buf_len)
482 goto out;
483
484 return path_buf;
485
486out:
487 return "lwan.conf";
488}
489
490static bool_Bool setup_from_config(struct lwan *lwan, const char *path)
491{
492 const struct config_line *line;
493 struct config *conf;
494 bool_Bool has_listener = false0;
495 char path_buf[PATH_MAX4096];
496
497 if (!path
3.1
'path' is null
)
4
Taking true branch
498 path = lwan_get_config_path(path_buf, sizeof(path_buf));
499 lwan_status_info("Loading configuration file: %s", path)lwan_status_info_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 499, __FUNCTION__, "Loading configuration file: %s", path)
;
500
501 conf = config_open(path);
502 if (!conf)
5
Assuming 'conf' is non-null
6
Taking false branch
503 return false0;
504
505 if (!lwan_trie_init(&lwan->url_map_trie, destroy_urlmap))
7
Assuming the condition is false
8
Taking false branch
506 return false0;
507
508 while ((line = config_read_line(conf))) {
9
Loop condition is true. Entering loop body