implement recv_buffer size limit and input validation

* Implement recv_buffer size limit and input validation

* Add readLengthPrefixedData helper and refactor some read flows

* Change error to be more accurate

* Add newline to error message

* fix long chat messages kicking clients

* style nitpicks

---------

Co-authored-by: p2r3 <p2r3@p2r3.com>
Co-authored-by: p2r3 <41925384+p2r3@users.noreply.github.com>
This commit is contained in:
Tyler Zars
2025-09-18 19:00:02 -04:00
committed by GitHub
parent b23e19ecd4
commit 3bde692976
5 changed files with 47 additions and 18 deletions

View File

@@ -217,12 +217,45 @@ double readDouble (int client_fd) {
return output;
}
// Receive length prefixed data with bounds checking
ssize_t readLengthPrefixedData (int client_fd) {
uint32_t length = readVarInt(client_fd);
if (length >= MAX_RECV_BUF_LEN) {
printf("ERROR: Received length (%u) exceeds maximum (%u)\n", length, MAX_RECV_BUF_LEN);
disconnectClient(&client_fd, -1);
recv_count = 0;
return 0;
}
return recv_all(client_fd, recv_buffer, length, false);
}
// Reads a networked string into recv_buffer
void readString (int client_fd) {
uint32_t length = readVarInt(client_fd);
recv_count = recv_all(client_fd, recv_buffer, length, false);
recv_count = readLengthPrefixedData(client_fd);
recv_buffer[recv_count] = '\0';
}
// Reads a networked string of up to N bytes into recv_buffer
void readStringN (int client_fd, uint32_t max_length) {
// Forward to readString if max length is invalid
if (max_length >= MAX_RECV_BUF_LEN) {
readString(client_fd);
return;
}
// Attempt to read full string within maximum
uint32_t length = readVarInt(client_fd);
if (max_length > length) {
recv_count = recv_all(client_fd, recv_buffer, length, false);
recv_buffer[recv_count] = '\0';
return;
}
// Read string up to maximum, dump the rest
recv_count = recv_all(client_fd, recv_buffer, max_length, false);
recv_buffer[recv_count] = '\0';
uint8_t dummy;
for (uint32_t i = max_length; i < length; i ++) {
recv_all(client_fd, &dummy, 1, false);
}
}
uint32_t fast_rand () {
rng_seed ^= rng_seed << 13;