On Wed, Oct 29, 2025 at 06:06:36PM +0100, Claudio Jeker wrote:
> On Thu, Sep 25, 2025 at 01:31:07PM +0200, Claudio Jeker wrote:
> > On Thu, Sep 25, 2025 at 01:14:16PM +0200, Florian Obser wrote:
> > > Nobody stepped up to fix chunked encoding in fastcgi. I think we should
> > > disable it.
> > > OK?
> >
> > No.
>
> Just to be clear, this turns off chunked encoding for output but the
> problem is when data is sent with chunked encoding in a POST. I doubt that
> forcing clt->clt_fcgi.chunked = 0 will fix chunked encoding handling
> during input processing. My fear is that httpd has no code to handle
> chunked encoding in POST request (as in sent by the client) and all of
> that needs to be written first.
The problem is in server_read_httpchunks() which is the rev 1.1 copy of
code from relayd and is not doing the right thing. When florian@ added
POST support he only did it for server_read_httpcontent() but did not
adjust server_read_httpchunks(). All of this was done 11 years ago so this
bug has been in httpd since the beginning.
I think the following diff below is what is needed. It seems to work with
the provided test case. It is too late to do further tests, so I hope
someone else will do that.
--
:wq Claudio
Index: server_http.c
===================================================================
RCS file: /cvs/src/usr.sbin/httpd/server_http.c,v
diff -u -p -r1.155 server_http.c
--- server_http.c 22 Dec 2024 13:51:42 -0000 1.155
+++ server_http.c 30 Oct 2025 21:46:48 -0000
@@ -578,12 +578,11 @@ server_read_httpchunks(struct buffereven
/* Read chunk data */
if ((off_t)size > clt->clt_toread) {
size = clt->clt_toread;
- if (server_bufferevent_write_chunk(clt, src, size)
- == -1)
+ if (fcgi_add_stdin(clt, src) == -1)
goto fail;
clt->clt_toread = 0;
} else {
- if (server_bufferevent_write_buffer(clt, src) == -1)
+ if (fcgi_add_stdin(clt, src) == -1)
goto fail;
clt->clt_toread -= size;
}
@@ -613,11 +612,6 @@ server_read_httpchunks(struct buffereven
return;
}
- if (server_bufferevent_print(clt, line) == -1 ||
- server_bufferevent_print(clt, "\r\n") == -1) {
- free(line);
- goto fail;
- }
free(line);
if ((clt->clt_toread = llval) == 0) {
@@ -633,13 +627,9 @@ server_read_httpchunks(struct buffereven
bufferevent_enable(bev, EV_READ);
return;
}
- if (server_bufferevent_print(clt, line) == -1 ||
- server_bufferevent_print(clt, "\r\n") == -1) {
- free(line);
- goto fail;
- }
if (strlen(line) == 0) {
/* Switch to HTTP header mode */
+ fcgi_add_stdin(clt, NULL);
clt->clt_toread = TOREAD_HTTP_HEADER;
bev->readcb = server_read_http;
}
@@ -649,8 +639,6 @@ server_read_httpchunks(struct buffereven
/* Chunk is terminated by an empty newline */
line = evbuffer_readln(src, NULL, EVBUFFER_EOL_CRLF_STRICT);
free(line);
- if (server_bufferevent_print(clt, "\r\n") == -1)
- goto fail;
clt->clt_toread = TOREAD_HTTP_CHUNK_LENGTH;
break;
}