Summary
On the receive path in libutil (libs/network/src/MessageHandler.cpp, MessageHandler::recv), the message length taken from the wire is only checked for being negative — there is no upper bound. The 64 KB cap that exists on the send side is not mirrored on receive. (Filing here since libutil has issues disabled.)
external/libutil/libs/network/src/MessageHandler.cpp, around lines 135 / 143 / 152 / 174:
- L135:
if(header.msgLen < 0) throw ...; — only rejects negative, nothing caps the maximum.
- L174:
sock.Recv(ser.GetDataWritable(header.msgLen), header.msgLen); — allocates up to ~2 GB from a 4-byte field before any data arrives.
- L143 / L152:
static_cast<int>(header.msgLen + sizeof(header)) — msgLen is summed with a size_t then narrowed to int, so a large msgLen truncates/overflows and corrupts the "enough bytes waiting" guard.
Trigger
A peer (or anything speaking the protocol) sends a valid 6-byte header claiming a very large msgLen. The receiver then attempts a huge allocation (memory-exhaustion / bad_alloc), and the truncating cast makes the length bookkeeping unreliable. This is reachable before any authentication of the payload.
Suggested fix
Reject msgLen > 64*1024 on receive, mirroring the existing send-side cap, before calling GetDataWritable. Also compute the "bytes waiting" comparison in a width that can't truncate (compare as size_t / against msgLen directly) rather than casting the sum to int.
This is a defensive-hardening report (denial-of-service / robustness on malformed input), not a demonstrated remote code execution. Happy to send a PR.
Summary
On the receive path in
libutil(libs/network/src/MessageHandler.cpp,MessageHandler::recv), the message length taken from the wire is only checked for being negative — there is no upper bound. The 64 KB cap that exists on the send side is not mirrored on receive. (Filing here since libutil has issues disabled.)external/libutil/libs/network/src/MessageHandler.cpp, around lines 135 / 143 / 152 / 174:if(header.msgLen < 0) throw ...;— only rejects negative, nothing caps the maximum.sock.Recv(ser.GetDataWritable(header.msgLen), header.msgLen);— allocates up to ~2 GB from a 4-byte field before any data arrives.static_cast<int>(header.msgLen + sizeof(header))—msgLenis summed with asize_tthen narrowed toint, so a largemsgLentruncates/overflows and corrupts the "enough bytes waiting" guard.Trigger
A peer (or anything speaking the protocol) sends a valid 6-byte header claiming a very large
msgLen. The receiver then attempts a huge allocation (memory-exhaustion /bad_alloc), and the truncating cast makes the length bookkeeping unreliable. This is reachable before any authentication of the payload.Suggested fix
Reject
msgLen > 64*1024on receive, mirroring the existing send-side cap, before callingGetDataWritable. Also compute the "bytes waiting" comparison in a width that can't truncate (compare assize_t/ againstmsgLendirectly) rather than casting the sum toint.This is a defensive-hardening report (denial-of-service / robustness on malformed input), not a demonstrated remote code execution. Happy to send a PR.