mime: fix reader stall on small read lengths

The base64 mime encoder stalls when it cannot encode a full 3 byte input
set into the read buffer. The workaround for this limitation was
incomplete and could lead to stalled transfers when the last chunk to
upload was smaller than 4 bytes.

Use a tmp buffer on small reads to allow mime encoders more space to put
their things.

Add test case reproducing the issue and fix.

Reported-by: Alexis Savin
Fixes #15688
Closes #15691
This commit is contained in:
Stefan Eissing 2024-12-05 12:37:38 +01:00 committed by Daniel Stenberg
parent 4bba14c35d
commit ce949ba1dc
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2
2 changed files with 69 additions and 12 deletions

View file

@ -669,6 +669,25 @@ class TestUpload:
])
r.check_stats(count=1, http_status=200, exitcode=0)
# issue #15688 when posting a form and cr_mime_read() is called with
# length < 4, we did not progress
@pytest.mark.parametrize("proto", ['http/1.1'])
def test_07_62_upload_issue_15688(self, env: Env, httpd, proto):
# this length leads to (including multipart formatting) to a
# client reader invocation with length 1.
upload_len = 196169
fname = f'data-{upload_len}'
env.make_data_file(indir=env.gen_dir, fname=fname, fsize=upload_len)
fdata = os.path.join(env.gen_dir, fname)
curl = CurlClient(env=env)
url = f'https://{env.authority_for(env.domain1, proto)}/curltest/echo?id=[0-0]'
r = curl.http_form(urls=[url], form={
'file': f'@{fdata}',
}, alpn_proto=proto, extra_args=[
'--max-time', '10'
])
r.check_stats(count=1, http_status=200, exitcode=0)
# nghttpx is the only server we have that supports TLS early data and
# has a limit of 16k it announces
@pytest.mark.skipif(condition=not Env.have_nghttpx(), reason="no nghttpx")