Reputation: 348
For learning purposes, I'm writing a basic network protocol over TcpStream
s. In order to delimit individual messages, I was using read_until
, but because the data sent can contain any bytes, this can't work.
So the next best option seems to be to prepend every message with the length and then read that many bytes from the stream.
Naively, this could be implemented as such:
fn read(stream: &mut TcpStream) -> Vec<u8> {
let mut length_buffer = [0_u8; 8];
stream.read_exact(&mut length_buffer); // Ignoring errors for the example
let length = u64::from_le_bytes(length_buffer);
let mut result = vec![0_u8; length as usize];
stream.read_exact(&mut result); // Ignoring errors for the example
result
}
However, let's imagine a server is using this read
function. A malicious user could send a packet: [255, 255, 255, 255, 255, 255, 255, 255]
, causing the server to attempt to allocate 18446744073709551615 bytes of memory, which will obviously fail and crash the program.
How could you deal with this? Options I can think of are:
But neither of these seem right. What is done in practice for public-facing server protocols?
Upvotes: 0
Views: 94