On Thu, Oct 30, 2025 at 10:51:42PM +0100, Claudio Jeker wrote:
> 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.
Better diff that stops the bufferevent read callback when switching back
to HTTP header mode.
--
: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 22:04:45 -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,15 +627,14 @@ 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;
+ bufferevent_disable(bev, EV_READ);
bev->readcb = server_read_http;
+ free(line);
+ return;
}
free(line);
break;
@@ -649,8 +642,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;
}