diff options
| author | Hauke Mehrtens | 2026-05-03 21:53:37 +0000 |
|---|---|---|
| committer | Hauke Mehrtens | 2026-05-15 00:13:28 +0000 |
| commit | 05317bf30a9432aaeac1a20300f605d9cf43c64f (patch) | |
| tree | 8babca3165b093e259af60a48ee3808dac1a8d0b | |
| parent | 0df62571f158f26cda43865df00ef59253a9a8fd (diff) | |
| download | uhttpd-05317bf30a9432aaeac1a20300f605d9cf43c64f.tar.gz | |
proc: store CGI Status message per-client instead of in a shared buffer
proc_handle_header parsed the CGI \"Status:\" header into a function-
static char status_buf[64] and pointed cl->dispatch.proc.status_msg at
it. dispatch_proc.status_msg was a plain char *, so every client's
status_msg ended up aliasing the same static buffer.
Header parsing for one CGI is split across multiple relay_read_cb
invocations whenever the child sends headers in chunks. Between two
reads of the same client, uloop can dispatch another client's CGI,
whose proc_handle_header overwrites the shared status_buf. When the
first client's empty-line read finally arrives and proc_handle_header_end
fires, status_msg points at the second client's text, so the
\"HTTP/1.1 <code> <msg>\" status line emitted to the first client
mixes its own status_code with another client's reason phrase.
Replace the char * with a fixed-size char status_msg[64] embedded in
dispatch_proc and snprintf into it directly. Each client now owns its
own buffer, so concurrent CGI responses can no longer trample each
other's status line.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
| -rw-r--r-- | proc.c | 7 | ||||
| -rw-r--r-- | uhttpd.h | 2 |
2 files changed, 4 insertions, 5 deletions
@@ -202,7 +202,6 @@ static void proc_handle_close(struct relay *r, int ret) static void proc_handle_header(struct relay *r, const char *name, const char *val) { - static char status_buf[64]; struct client *cl = r->cl; char *sep; char buf[4]; @@ -214,8 +213,8 @@ static void proc_handle_header(struct relay *r, const char *name, const char *va memcpy(buf, val, 3); buf[3] = 0; - snprintf(status_buf, sizeof(status_buf), "%s", sep + 1); - cl->dispatch.proc.status_msg = status_buf; + snprintf(cl->dispatch.proc.status_msg, + sizeof(cl->dispatch.proc.status_msg), "%s", sep + 1); cl->dispatch.proc.status_code = atoi(buf); return; } @@ -338,7 +337,7 @@ bool uh_create_process(struct client *cl, struct path_info *pi, char *url, blob_buf_init(&proc->hdr, 0); proc->status_code = 200; - proc->status_msg = "OK"; + strcpy(proc->status_msg, "OK"); if (pipe(rfd)) return false; @@ -206,7 +206,7 @@ struct dispatch_proc { struct uloop_fd wrfd; struct relay r; int status_code; - char *status_msg; + char status_msg[64]; }; struct dispatch_handler { |