Bug Summary

File:main.c
Location:line 224, column 5
Description:Attempt to free released memory

Annotated Source Code

1/*
2 * lwan - simple web server
3 * Copyright (c) 2012 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, USA.
18 */
19
20#define _GNU_SOURCE
21#include <getopt.h>
22#include <stdlib.h>
23#include <unistd.h>
24
25#include "lwan.h"
26#include "lwan-serve-files.h"
27
28enum args {
29 ARGS_FAILED,
30 ARGS_USE_CONFIG,
31 ARGS_SERVE_FILES
32};
33
34lwan_http_status_t
35gif_beacon(lwan_request_t *request __attribute__((unused)),
36 lwan_response_t *response,
37 void *data __attribute__((unused)))
38{
39 /*
40 * 1x1 transparent GIF image generated with tinygif
41 * http://www.perlmonks.org/?node_id=7974
42 */
43 static const unsigned char gif_beacon_data[] = {
44 0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x01, 0x00, 0x01, 0x00, 0x90,
45 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0xF9, 0x04,
46 0x05, 0x10, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x01,
47 0x00, 0x01, 0x00, 0x00, 0x02, 0x02, 0x04, 0x01
48 };
49
50 response->mime_type = "image/gif";
51 strbuf_set_static(response->buffer, (char*)gif_beacon_data, sizeof(gif_beacon_data));
52
53 return HTTP_OK;
54}
55
56lwan_http_status_t
57test_chunked_encoding(lwan_request_t *request,
58 lwan_response_t *response,
59 void *data __attribute__((unused)))
60{
61 int i;
62
63 response->mime_type = "text/plain";
64
65 strbuf_printf(response->buffer, "Testing chunked encoding! First chunk\n");
66 lwan_response_send_chunk(request);
67
68 for (i = 0; i <= 10; i++) {
69 strbuf_printf(response->buffer, "*This is chunk %d*\n", i);
70 lwan_response_send_chunk(request);
71 }
72
73 strbuf_printf(response->buffer, "Last chunk\n");
74 lwan_response_send_chunk(request);
75
76 return HTTP_OK;
77}
78
79lwan_http_status_t
80test_server_sent_event(lwan_request_t *request,
81 lwan_response_t *response,
82 void *data __attribute__((unused)))
83{
84 int i;
85
86 for (i = 0; i <= 10; i++) {
87 strbuf_printf(response->buffer, "Current value is %d", i);
88 lwan_response_send_event(request, "currval");
89 }
90
91 return HTTP_OK;
92}
93
94lwan_http_status_t
95hello_world(lwan_request_t *request,
96 lwan_response_t *response,
97 void *data __attribute__((unused)))
98{
99 static lwan_key_value_t headers[] = {
100 { .key = "X-The-Answer-To-The-Universal-Question", .value = "42" },
101 { NULL((void*)0), NULL((void*)0) }
102 };
103 response->headers = headers;
104 response->mime_type = "text/plain";
105
106 const char *name = lwan_request_get_query_param(request, "name");
107 if (name)
108 strbuf_printf(response->buffer, "Hello, %s!", name);
109 else
110 strbuf_set_static(response->buffer, "Hello, world!", sizeof("Hello, world!") -1);
111
112 const char *dump_vars = lwan_request_get_query_param(request, "dump_vars");
113 if (!dump_vars)
114 goto end;
115
116 strbuf_append_str(response->buffer, "\n\nQuery String Variables\n", 0);
117 strbuf_append_str(response->buffer, "----------------------\n\n", 0);
118
119 lwan_key_value_t *qs = request->query_params.base;
120 for (; qs->key; qs++)
121 strbuf_append_printf(response->buffer,
122 "Key = \"%s\"; Value = \"%s\"\n", qs->key, qs->value);
123
124 if (!(request->flags & REQUEST_METHOD_POST))
125 goto end;
126
127 strbuf_append_str(response->buffer, "\n\nPOST data\n", 0);
128 strbuf_append_str(response->buffer, "---------\n\n", 0);
129
130 for (qs = request->post_data.base; qs->key; qs++)
131 strbuf_append_printf(response->buffer,
132 "Key = \"%s\"; Value = \"%s\"\n", qs->key, qs->value);
133
134end:
135 return HTTP_OK;
136}
137
138static enum args
139parse_args(int argc, char *argv[], lwan_config_t *config, char **root)
140{
141 static const struct option opts[] = {
142 { .name = "root", .has_arg = 1, .val = 'r' },
143 { .name = "listen", .has_arg = 1, .val = 'l' },
144 { .name = "help", .val = 'h' },
145 { }
146 };
147 int c, optidx = 0;
148 enum args result = ARGS_USE_CONFIG;
149
150 while ((c = getopt_long(argc, argv, "hr:l:", opts, &optidx)) != -1) {
151 switch (c) {
152 case 'l':
153 free(config->listener);
154 config->listener = strdup(optarg);
155 result = ARGS_SERVE_FILES;
156 break;
157
158 case 'r':
159 free(*root);
160 *root = strdup(optarg);
161 result = ARGS_SERVE_FILES;
162 break;
163
164 default:
165 printf("Run %s --help for usage information.\n", argv[0]);
166 return ARGS_FAILED;
167
168 case 'h':
169 printf("Usage: %s [--root /path/to/root/dir] [--listener addr:port]\n", argv[0]);
170 printf("\t[--config]\n");
171 printf("Serve files through HTTP.\n\n");
172 printf("Defaults to listening on all interfaces, port 8080, serving current directory.\n\n");
173 printf("Options:\n");
174 printf("\t-r, --root Path to serve files from (default: current dir).\n");
175 printf("\t-l, --listener Listener (default: %s).\n", config->listener);
176 printf("\t-h, --help This.\n");
177 printf("\n");
178 printf("Examples:\n");
179 printf(" Serve system-wide documentation: %s -r /usr/share/doc\n", argv[0]);
180 printf(" Serve on a different port: %s -l '*:1337'\n", argv[0]);
181 printf("\n");
182 printf("Report bugs at <https://github.com/lpereira/lwan>.\n");
183 return ARGS_FAILED;
184 }
185 }
186
187 return result;
188}
189
190int
191main(int argc, char *argv[])
192{
193 lwan_t l;
194 lwan_config_t c;
195 char *root = get_current_dir_name();
196
197 c = *lwan_get_default_config();
198 c.listener = strdup("*:8080");
199
200 switch (parse_args(argc, argv, &c, &root)) {
1
Control jumps to 'case ARGS_USE_CONFIG:' at line 211
201 case ARGS_SERVE_FILES:
202 lwan_status_info("Serving files from %s", root)lwan_status_info_debug("/home/buildbot/lwan-slave/clang-analyze/build/lwan/main.c"
, 202, __FUNCTION__, "Serving files from %s", root)
;
203 lwan_init_with_config(&l, &c);
204
205 const lwan_url_map_t map[] = {
206 { .prefix = "/", SERVE_FILES(root).module = lwan_module_serve_files(), .args = ((struct lwan_serve_files_settings_t
[]) {{ .root_path = root, .index_html = ((void*)0), .serve_precompressed_files
= 1 }}), .flags = (lwan_handler_flags_t)0
},
207 { }
208 };
209 lwan_set_url_map(&l, map);
210 break;
211 case ARGS_USE_CONFIG:
212 free(c.listener);
213 free(root);
2
Memory is released
214
215 lwan_init(&l);
216 break;
3
Execution continues on line 221
217 case ARGS_FAILED:
218 return EXIT_FAILURE1;
219 }
220
221 lwan_main_loop(&l);
222 lwan_shutdown(&l);
223
224 free(root);
4
Attempt to free released memory
225}