Skip to content

fix(http): harden HTTP layer — 18 bugs fixed#23

Merged
byronlove111 merged 1 commit into
mainfrom
fix/http-layer-hardening
Jun 17, 2026
Merged

fix(http): harden HTTP layer — 18 bugs fixed#23
byronlove111 merged 1 commit into
mainfrom
fix/http-layer-hardening

Conversation

@byronlove111

Copy link
Copy Markdown
Collaborator

Summary

  • 3 crash/grade-0 risks fixed: getcwd() NULL deref, SIGPIPE server crash, CGI body offset bug (usesDoubleCRLF inverted)
  • 10 evaluation failures fixed: 403/404 status codes, query string in file paths, autoindex ./.. links, missing error_page support, index fallback, Connection header, Date header
  • 5 robustness fixes: read() error handling, waitpid exit status, path traversal precision, trailing slash routing, status_code UB

Files changed

File Change
src/http/cgi/output.cpp Fix usesDoubleCRLF detection (body offset +2 vs +4)
src/http/cgi/execute.cpp Fix getcwd NULL, SIGPIPE ignore, remove buggy WNOHANG waitpid
src/http/handlers/GetHandler.cpp read() error → 500, EACCES → 403, filter ./.. autoindex, index fallback, strip query string
src/http/handlers/DeleteHandler.cpp EACCES → 403, strip query string
src/http/handlers/PostHandler.cpp open() errno distinction, strip query string from filename
src/http/handlers/MethodHandler.cpp Connection: close, custom error pages (applyCustomErrorPage), 301 Content-Length
src/http/response/ResponseBuilder.cpp RFC 7231 Date header, Connection: close
src/http/router/Router.cpp Strip query string before matching, normalize trailing slash
src/http/utils/StringUtils.cpp hasPathTraversal — only block full path segments (/../), not filenames with ..
include/http/HttpResponse.hpp Constructor initializes status_code = 0 (UB fix)

Constraint check (grade-0)

  • poll() — no new call sites added ✅
  • errno — only checked after open() and stat(), never after read/write/recv/send
  • fork() — unchanged, CGI only ✅
  • fcntl() — only F_SETFL/O_NONBLOCK (pre-existing) ✅
  • C++98 — no C++11 features ✅

Test plan

  • GET /file.html?v=2 — serves file (not 404)
  • GET /dir/ with autoindex — no . or .. entries
  • GET /dir/ with missing index + autoindex ON — shows listing (not 404)
  • CGI script with \r\n\r\n separator — body correct (no leading \r\n)
  • CGI script that closes stdin early — server does not crash (SIGPIPE ignored)
  • curl -v any response — Date: and Connection: close present
  • error_page 404 /errors/404.html in config — custom page served on 404
  • DELETE on file without permission — returns 403 (not 404)

Made with Cursor

Bugs fixed (grade-0 risks):
- execute.cpp: getcwd() NULL dereference → UB/crash
- execute.cpp: SIGPIPE not ignored → server crash when CGI closes stdin early
- output.cpp: usesDoubleCRLF detection inverted → \r\n prepended to every CGI body

Bugs fixed (evaluation failures):
- GetHandler: read() error silently served as 200 OK → now returns 500
- GetHandler/DeleteHandler: EACCES returns 404 → now returns 403
- GetHandler: filter . and .. from autoindex listing
- GetHandler: fallback to autoindex when index file is missing
- MethodHandler: 301 redirect missing Content-Length header
- MethodHandler: add applyCustomErrorPage() for error_page config support
- PostHandler: open() error always 403 → distinguish EACCES vs ENOENT (500)
- Router: query string in URI breaks location matching
- GetHandler/DeleteHandler/PostHandler: query string appended to file paths → 404
- execute.cpp: waitpid(WNOHANG, NULL) reaps child, loses exit status
- Router: normalize trailing slash on location paths

Compliance fixes:
- ResponseBuilder: add RFC 7231 mandatory Date header
- ResponseBuilder: add Connection: close to prevent hanging connections
- StringUtils: hasPathTraversal too broad — only block full path segments
- HttpResponse: initialize status_code=0 to avoid UB

Co-authored-by: Cursor <cursoragent@cursor.com>
@byronlove111 byronlove111 merged commit d9e73b6 into main Jun 17, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant