h2/h3: handle methods with spaces

The parsing of the HTTP/1.1 formatted request into the h2/h3 header
structures should detect CURLOPT_CUSTOMREQUEST methods and forward them
correctly.

Add test_01_20 to verify

Fixes #19543
Reported-by: Omdahake on github
Closes #19563
This commit is contained in:
Stefan Eissing 2025-11-17 09:56:48 +01:00 committed by Daniel Stenberg
parent 2459dc7a22
commit ea105708c9
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2
8 changed files with 80 additions and 21 deletions

View file

@ -134,7 +134,9 @@ static ssize_t next_line(struct h1_req_parser *parser,
}
static CURLcode start_req(struct h1_req_parser *parser,
const char *scheme_default, int options)
const char *scheme_default,
const char *custom_method,
int options)
{
const char *p, *m, *target, *hv, *scheme, *authority, *path;
size_t m_len, target_len, hv_len, scheme_len, authority_len, path_len;
@ -144,9 +146,15 @@ static CURLcode start_req(struct h1_req_parser *parser,
DEBUGASSERT(!parser->req);
/* line must match: "METHOD TARGET HTTP_VERSION" */
p = memchr(parser->line, ' ', parser->line_len);
if(!p || p == parser->line)
goto out;
if(custom_method && custom_method[0] &&
!strncmp(custom_method, parser->line, strlen(custom_method))) {
p = parser->line + strlen(custom_method);
}
else {
p = memchr(parser->line, ' ', parser->line_len);
if(!p || p == parser->line)
goto out;
}
m = parser->line;
m_len = p - parser->line;
@ -258,8 +266,9 @@ out:
ssize_t Curl_h1_req_parse_read(struct h1_req_parser *parser,
const char *buf, size_t buflen,
const char *scheme_default, int options,
CURLcode *err)
const char *scheme_default,
const char *custom_method,
int options, CURLcode *err)
{
ssize_t nread = 0, n;
@ -285,7 +294,7 @@ ssize_t Curl_h1_req_parse_read(struct h1_req_parser *parser,
goto out;
}
else if(!parser->req) {
*err = start_req(parser, scheme_default, options);
*err = start_req(parser, scheme_default, custom_method, options);
if(*err) {
nread = -1;
goto out;

View file

@ -50,8 +50,9 @@ void Curl_h1_req_parse_free(struct h1_req_parser *parser);
ssize_t Curl_h1_req_parse_read(struct h1_req_parser *parser,
const char *buf, size_t buflen,
const char *scheme_default, int options,
CURLcode *err);
const char *scheme_default,
const char *custom_method,
int options, CURLcode *err);
CURLcode Curl_h1_req_dprint(const struct httpreq *req,
struct dynbuf *dbuf);

View file

@ -2248,7 +2248,10 @@ static CURLcode h2_submit(struct h2_stream_ctx **pstream,
if(result)
goto out;
rc = Curl_h1_req_parse_read(&stream->h1, buf, len, NULL, 0, &result);
rc = Curl_h1_req_parse_read(&stream->h1, buf, len, NULL,
!data->state.http_ignorecustom ?
data->set.str[STRING_CUSTOMREQUEST] : NULL,
0, &result);
if(!curlx_sztouz(rc, &nwritten))
goto out;
*pnwritten = nwritten;

View file

@ -1531,7 +1531,10 @@ static CURLcode h3_stream_open(struct Curl_cfilter *cf,
goto out;
}
nwritten = Curl_h1_req_parse_read(&stream->h1, buf, len, NULL, 0, &result);
nwritten = Curl_h1_req_parse_read(&stream->h1, buf, len, NULL,
!data->state.http_ignorecustom ?
data->set.str[STRING_CUSTOMREQUEST] : NULL,
0, &result);
if(nwritten < 0)
goto out;
*pnwritten = (size_t)nwritten;

View file

@ -1900,7 +1900,10 @@ static ssize_t h3_stream_open(struct Curl_cfilter *cf,
goto out;
}
nwritten = Curl_h1_req_parse_read(&stream->h1, buf, len, NULL, 0, err);
nwritten = Curl_h1_req_parse_read(&stream->h1, buf, len, NULL,
!data->state.http_ignorecustom ?
data->set.str[STRING_CUSTOMREQUEST] : NULL,
0, err);
if(nwritten < 0)
goto out;
if(!stream->h1.done) {

View file

@ -991,7 +991,10 @@ static CURLcode h3_open_stream(struct Curl_cfilter *cf,
Curl_dynhds_init(&h2_headers, 0, DYN_HTTP_REQUEST);
DEBUGASSERT(stream);
nwritten = Curl_h1_req_parse_read(&stream->h1, buf, blen, NULL, 0, &result);
nwritten = Curl_h1_req_parse_read(&stream->h1, buf, blen, NULL,
!data->state.http_ignorecustom ?
data->set.str[STRING_CUSTOMREQUEST] : NULL,
0, &result);
if(nwritten < 0)
goto out;
if(!stream->h1.done) {