bunkum

an old and silly c99 web server with some fun features
Log | Files | Refs | README

commit 67a8b26aba9217eb68ec5c1e04765b85c7b33a5c
parent 3f8a18907d21e9e1a91799243d0ec86d5f948bd0
Author: quantumish <freifeld.david@gmail.com>
Date:   Sun, 16 Apr 2023 00:34:35 -0700

Fix double free() bug

Diffstat:
Mhttp.c | 29+++++++++++++----------------
Mhttp/request.c | 3+++
Mutils/hashmap.c | 4+---
3 files changed, 17 insertions(+), 19 deletions(-)

diff --git a/http.c b/http.c @@ -47,9 +47,9 @@ char* get_file_ext(char* filename) { return ext; } -response_t serve_file(request_t req) { +response_t serve_file(request_t* req) { char path[128+8] = "./public"; - strcat(path, req.path); + strcat(path, req->path); int fd = open(path, O_RDONLY); // TODO handle response_t r = resp_new(OK); @@ -59,14 +59,14 @@ response_t serve_file(request_t req) { for (size_t i = 0; read(fd, fbuf+(i*4096), 4096) > 0; i++); - char* ext = get_file_ext(req.path); + char* ext = get_file_ext(req->path); resp_set_ctype(&r, ext); bool ok = true; char* mtype = (char*)ext_to_mtype(ext); char* hdr; - if ((hdr = hashmap_get(&req.headers, "Accept"))) { + if ((hdr = hashmap_get(&req->headers, "Accept"))) { ok = false; shitvec_t mtypes = hdr_parse_accept(hdr); for (int j = 0; j < mtypes.vec_sz; j++) { @@ -82,7 +82,7 @@ response_t serve_file(request_t req) { char* buf = fbuf; // buffer to be written size_t bufsize = st.st_size; - if (ok && (hdr = hashmap_get(&req.headers, "Accept-Encoding"))) { + if (ok && (hdr = hashmap_get(&req->headers, "Accept-Encoding"))) { ok = false; shitvec_t mtypes = hdr_parse_accept(hdr); // abuse of this func for (int j = 0; j < mtypes.vec_sz; j++) { @@ -119,26 +119,25 @@ response_t serve_file(request_t req) { // TODO actually respect requests // TODO list dirs -response_t make_response (request_t req) { - if (req_parse(&req) < 0) { +response_t make_response (request_t* req) { + if (req_parse(req) < 0) { log_error("Failed to parse incoming request."); return serve_error(BadRequest); } /* hashmap_dump(&req.headers); */ - log_info("Got request %s %s", method_name(req.method), req.path); + log_info("Got request %s %s", method_name(req->method), req->path); - char* mapped_path = hashmap_get(&path_redirs, req.path); + char* mapped_path = hashmap_get(&path_redirs, req->path); if (mapped_path != NULL) { - log_debug("test"); - strcpy(req.path, mapped_path); + strcpy(req->path, mapped_path); } - if (!shitvec_check(&paths, req.path, (sv_cmp_t)strcmp)) { + if (!shitvec_check(&paths, req->path, (sv_cmp_t)strcmp)) { return serve_error(NotFound); } - switch (req.method) { + switch (req->method) { case GET: return serve_file(req); break; default: return serve_error(MethodNotAllowed); } @@ -158,9 +157,8 @@ void* handle_conn(void* ctxt) { gettimeofday(&before, NULL); if (msgbuf[0] != 0) { request_t req = req_new(msgbuf, 1024); - log_debug("after init %p %p", req.headers.keys, req.headers.vals); - response_t r = make_response(req); + response_t r = make_response(&req); send(ns, r.content, r.sz, 0); free(r.content); @@ -240,7 +238,6 @@ int main() { pthread_create(&lthread, NULL, listen_for_conns, &s); while (true) { int ns = *(int*)channel_recv(&listen_chan); - log_debug("%d", ns); pthread_t thread; pthread_create(&thread, NULL, handle_conn, &ns); diff --git a/http/request.c b/http/request.c @@ -17,6 +17,9 @@ enum http_method method_enum(char* p) { return method_codes[((*(uint64_t*)p*0x1b8b6e6d) % 0x100000000) >> 28]; } +// Be careful about passing by value! if the internal hashmap resizes +// a req_free() call on the original (the one copied *from*) will be a +// double free() error request_t req_new(char* reqbuf, size_t bufsize) { request_t req; req.buf = reqbuf; diff --git a/utils/hashmap.c b/utils/hashmap.c @@ -41,7 +41,6 @@ hashmap_t hashmap_new(size_t ksize, size_t vsize) { // Keys and vals are in different arrays so unnecessary things aren't in cache h.keys = calloc(HASHMAP_INIT_SIZE, ksize); h.vals = malloc(vsize * HASHMAP_INIT_SIZE); - log_debug("in init %p %p", h.keys, h.vals); h.k_sz = ksize; h.v_sz = vsize; h.len = HASHMAP_INIT_SIZE; @@ -66,7 +65,7 @@ void hashmap_resize(hashmap_t* h) { h->len *= 2; // Simple to use calloc here because keys need to be initialized to zero. h->keys = calloc(h->len, h->k_sz); - h->vals = malloc(h->len * h->v_sz); + h->vals = malloc(h->len * h->v_sz); // Copy all keys and values for (size_t off = 0; off < (h->len / 2); off++) { // Don't bother copying entries with empty keys @@ -89,7 +88,6 @@ void hashmap_dump(hashmap_t* h) { int hashmap_set(hashmap_t* h, void* k, void* v) { // Check if load factor too high - if ((float)h->filled / h->len > (float)2/3) hashmap_resize(h); size_t index = hash(k, h->vark ? strlen(k) : h->k_sz) % h->len; int looped_once = 0;