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.
------------------------------