Naturally when I write C I’m reasonably careful about a number of things. Because at runtime it’s a free-for-all, I take care to notice buffer overruns, uninitialized memory, and in particular the possible values assigned to a pointer.
I’ll back up a second, because unfortunately I recently managed to make a bit of a bollocks of the last point, which I only noticed when I came back to change the code. This is something I know inside-out, so the point of this post is to shame me into never making the same mistake again.
--- a/src/resource_handler.c
+++ b/src/resource_handler.c
@@ -27,16 +27,18 @@ uint16_t
service_request(struct request *req, char *rtrv_buf, const size_t len)
{
- if (req->method == MGET) {
- if (cache_rtrv(req->uri, rtrv_buf, len) == 0) {
- return ROK;
- } else {
- log_ln(DEBUG, "'%s' not found in cache\n", req->uri);
- return RNOTFOUND;
+ if (req != NULL) {
+ if (req->method == MGET) {
+ if (cache_rtrv(req->uri, rtrv_buf, len) == 0) {
+ return ROK;
+ } else {
+ log_ln(DEBUG, "'%s' not found in cache\n", req->uri);
+ return RNOTFOUND;
+ }
+ } else if (req->method == MUNKNOWN || req->method == MPOST) {
+ log_ln(ERROR, "request method not implemented: 0x%x\n", req->method
+ return RNOTIMPLEMENTED;
}
- } else if (req->method == MUNKNOWN) {
- log_ln(ERROR, "request method not implemented: 0x%x\n", req->method);
- return RNOTIMPLEMENTED;
}
return RINTERNAL;
In the original code I’m deferencing a field in a struct (req->method
)
without first finding out whether the struct had been assigned.
To fix this I added a check for a NULL
before trying to dereference
the field (and as this is an HTTP server, prepare to send an HTTP 500
response to the client if there’s a problem).