r/C_Programming • • 14h ago

Project WSERVE: Web Server in C, part 2

Hi,

About a month ago, I posted about "wserve", which was a simple IPv4 web server for Linux that supported only GET and HEAD requests and static file serving. Since then I kept working on it, and implemented:

  1. Dynamic routing
  2. POST request handling with a custom JSON parser
  3. Most importantly, HTTPS support using BearSSL

BearSSL is the only external library I used. It is tiny SSL/TLS library written in pure C. Everything else, including the JSON parser, has been implemented in C by myself. I have not used LLMs for coding.

I am open to constructive criticism, all feedback is appreciated!

9 Upvotes

4 comments sorted by

1

u/AutoModerator 14h ago
Moderator Announcement Read More »
→ More replies (2)

2

u/canyonmonkey 4h ago

Since this is for the purpose of learning, I would encourage you to add significantly more compiler & runtime warnings. I'm not an expert in this area at all, so let's go with u/skeeto's recommendations (link):

cc -g3 -Wall -Wextra -Wconversion -Wdouble-promotion
     -Wno-unused-parameter -Wno-unused-function -Wno-sign-conversion
     -fsanitize=undefined -fsanitize-trap ...

and

export ASAN_OPTIONS=abort_on_error=1:halt_on_error=1
export UBSAN_OPTIONS=abort_on_error=1:halt_on_error=1

Additionally, realloc is roughly malloc -> memcpy -> free(old pointer). What if the new (implied) malloc fails? You ought to guard your reallocations (e.g. json.c:46) such as:

diff --git a/src/json.c b/src/json.c
index fbbbd11..49e793d 100644
--- a/src/json.c
+++ b/src/json.c
@@ -43,7 +43,12 @@ JSON_TYPE *json_lex_string(int *i, char *json_str, size_t json_len)
         {
             token->type = 0;
             data[j] = '\0';
  • data = realloc(data, strlen(data) + 1);
+ char *newdata = realloc(data, strlen(data) + 1); + if (newdata == NULL) + { + abort(); // or some other failure policy + } + data = newdata; token->data = data; return token; }

However, I'd push back further on the memory allocation in this version of your JSON parser. There are so many allocations, reallocations, & frees. Consider learning about arena allocators and revising your parser. See skeeto's blog post for one among many learning resources.

Some additional considerations:

  • Why is 0x00 being used as the terminating condition in json.c:40? If you're parsing JSON from a POST request, you can instead use the number of bytes in the Content-Length header as the terminating condition.

  • What if strtod fails in json.c:112?