I was looking for something different when I stumbled upon this. - in server_file_index `escapedpath' is leaked if evbuffer_add_printf fails, similarly the directory entries in the loop. `escapeduri' is also leaked if escape_html fails.
- read_errdoc leaks a file descriptor if fstat fails or if the file is empty. both very unlikely but worth fixing IMHO. For server_file_index I decided to just drop the `skip' variable and just goto fail on errors. There shouldn't be any visible change from it, except that we don't try to serve half page if we somehow exhaust memory halfway through. ok? Index: server_file.c =================================================================== RCS file: /home/cvs/src/usr.sbin/httpd/server_file.c,v retrieving revision 1.74 diff -u -p -r1.74 server_file.c --- server_file.c 4 Mar 2022 01:46:07 -0000 1.74 +++ server_file.c 14 Aug 2022 21:09:25 -0000 @@ -474,7 +474,7 @@ server_file_index(struct httpd *env, str struct http_descriptor *desc = clt->clt_descreq; struct server_config *srv_conf = clt->clt_srv_conf; struct dirent **namelist, *dp; - int namesize, i, ret, fd = -1, namewidth, skip; + int namesize = 0, i = 0, ret, fd = -1, namewidth; int code = 500; struct evbuffer *evb = NULL; struct media_type *media; @@ -510,9 +510,6 @@ server_file_index(struct httpd *env, str if ((namesize = scandir(path, &namelist, NULL, alphasort)) == -1) goto abort; - /* Indicate failure but continue going through the list */ - skip = 0; - if ((escapedpath = escape_html(desc->http_path)) == NULL) goto fail; @@ -535,8 +532,10 @@ server_file_index(struct httpd *env, str "<body>\n" "<h1>Index of %s</h1>\n" "<hr>\n<pre>\n", - escapedpath, style, escapedpath) == -1) - skip = 1; + escapedpath, style, escapedpath) == -1) { + free(escapedpath); + goto fail; + } free(escapedpath); @@ -545,8 +544,7 @@ server_file_index(struct httpd *env, str dp = namelist[i]; - if (skip || - fstatat(fd, dp->d_name, &subst, 0) == -1) { + if (fstatat(fd, dp->d_name, &subst, 0) == -1) { free(dp); continue; } @@ -558,8 +556,10 @@ server_file_index(struct httpd *env, str if ((escapeduri = url_encode(dp->d_name)) == NULL) goto fail; - if ((escapedhtml = escape_html(dp->d_name)) == NULL) + if ((escapedhtml = escape_html(dp->d_name)) == NULL) { + free(escapeduri); goto fail; + } if (dp->d_name[0] == '.' && !(dp->d_name[1] == '.' && dp->d_name[2] == '\0')) { @@ -571,7 +571,7 @@ server_file_index(struct httpd *env, str strchr(escapeduri, ':') != NULL ? "./" : "", escapeduri, escapedhtml, MAXIMUM(namewidth, 0), " ", tmstr, "-") == -1) - skip = 1; + goto fail; } else if (S_ISREG(subst.st_mode)) { if (evbuffer_add_printf(evb, "<a href=\"%s%s\">%s</a>%*s%s%20llu\n", @@ -579,16 +579,16 @@ server_file_index(struct httpd *env, str escapeduri, escapedhtml, MAXIMUM(namewidth, 0), " ", tmstr, subst.st_size) == -1) - skip = 1; + goto fail; } free(escapeduri); free(escapedhtml); free(dp); } free(namelist); + namelist = NULL; - if (skip || - evbuffer_add_printf(evb, + if (evbuffer_add_printf(evb, "</pre>\n<hr>\n</body>\n</html>\n") == -1) goto abort; @@ -629,6 +629,9 @@ server_file_index(struct httpd *env, str bufferevent_free(clt->clt_bev); clt->clt_bev = NULL; abort: + for (; i < namesize; i++) + free(namelist[i]); + free(namelist); if (fd != -1) close(fd); if (evb != NULL) Index: server_http.c =================================================================== RCS file: /home/cvs/src/usr.sbin/httpd/server_http.c,v retrieving revision 1.150 diff -u -p -r1.150 server_http.c --- server_http.c 2 Mar 2022 11:10:43 -0000 1.150 +++ server_http.c 14 Aug 2022 18:42:33 -0000 @@ -1777,14 +1777,13 @@ read_errdoc(const char *root, const char free(path); if (fstat(fd, &sb) < 0) { log_warn("%s: stat", __func__); + close(fd); return (NULL); } if ((ret = calloc(1, sb.st_size + 1)) == NULL) fatal("calloc"); - if (sb.st_size == 0) - return (ret); - if (read(fd, ret, sb.st_size) != sb.st_size) { + if (sb.st_size != 0 && read(fd, ret, sb.st_size) != sb.st_size) { log_warn("%s: read", __func__); close(fd); free(ret);