Hi Dmytro,
Thank you for the structured report with detailed minimal example and
for testing of our pre-release version.
Please share also the following data:
* The size of your test file used for uploads
* Your OS and kernel version
* gcc --version
* curl --version
* Any extra options used for MHD2 configure
You may get additional data by testing with MHD2 built with "./configure
--enable-build-type=debug" or "./configure
--enable-build-type=debugger". I would appreciate if you try with MHD2
with such settings.
Thank you!
--
Best,
Evgeny
On 28/02/2026 15:30, Dmytro Zhukov wrote:
Hi,
I found a bug in the MHD2 multipart POST parser where |size| passed to
|MHD_PostDataReader| occasionally wraps to a huge value (e.g.
|18446744073709551518|, which is |-98| as a signed value), and the
|off| parameter simultaneously regresses by the same amount.
*Tested on:* commit |afe8b43| (current master)
*Minimal reproducer:
*#include <microhttpd2.h>
#include <stdio.h>
static const struct MHD_UploadAction *post_data_reader(
struct MHD_Request *req, void *cls, const struct MHD_String *name,
const struct MHD_StringNullable *filename,
const struct MHD_StringNullable *content_type,
const struct MHD_StringNullable *encoding, size_t size, const void
*data,
uint_fast64_t off, enum MHD_Bool final_data) {
if (filename && filename->cstr)
printf("f=%s off=%llu size=%zu final=%d\n", filename->cstr,
(unsigned long long)off, size, (int)final_data);
return MHD_upload_action_continue(req);
}
static const struct MHD_UploadAction *
post_done(struct MHD_Request *req, void *cls, enum MHD_PostParseResult
result) {
return (const struct MHD_UploadAction *)MHD_action_from_response(
req, MHD_response_from_buffer_static(MHD_HTTP_STATUS_OK, 2,
"OK"));
}
static const struct MHD_Action *handle_request(void *cls,
struct MHD_Request *req,
const struct MHD_String
*path,
enum MHD_HTTP_Method
method,
uint_fast64_t
upload_size) {
if (method == MHD_HTTP_METHOD_POST)
return MHD_action_parse_post(
req,
4 * 1024, // small buffer for regular fields
0, // stream everything including files
MHD_HTTP_POST_ENCODING_OTHER, &post_data_reader, NULL,
&post_done,
NULL);
return MHD_action_from_response(
req,
MHD_response_from_buffer_static(MHD_HTTP_STATUS_METHOD_NOT_ALLOWED,
0, ""));
}
int main(void) {
struct MHD_Daemon *d;
static const struct MHD_DaemonOptionAndValue bind_opt =
MHD_D_OPTION_BIND_PORT(MHD_AF_AUTO, 8080);
d = MHD_daemon_create(&handle_request, NULL);
if (MHD_SC_OK != MHD_DAEMON_SET_OPTIONS(
d, MHD_D_OPTION_BIND_PORT(MHD_AF_AUTO, 8080),
MHD_D_OPTION_WM_WORKER_THREADS(4),
MHD_D_OPTION_LARGE_POOL_SIZE(16 * 1024 *
1024))) {
fprintf(stderr, "Failed to set options\n");
MHD_daemon_destroy(d);
return 1;
}
MHD_daemon_start(d);
printf("Listening on :8080\n");
(void)getchar();
MHD_daemon_destroy(d);
return 0;
}
*Buil**d:
*gcc -o mhd_test mhd_test.c \
-I.../libmicrohttpd2/src/include \
.../libmicrohttpd2/src/mhd2/.libs/libmicrohttpd2.a
*Reproduce:*
curl -X POST http://localhost:8080/ -F "file=@any_large_file.png"
*Output showing the bug:*
f=IMG_7717.PNG off=616227 size=18446744073709551518 final=0
f=IMG_7717.PNG off=616129 size=3999 final=0 ← offset regressed by 98 bytes
The offset regression equals exactly |2^64 - size|, suggesting a
signed underflow in the chunk size calculation at certain multipart
boundary alignments. The bug is deterministic and reproducible across
multiple uploads of the same file.
------------------------------------------------------------------------