commit - b23e19ecd4f7a33e6cd03ab53103b65ccf4f8f1d
commit + 3bde6929768adf802fbe57b27d1ef99204bad8cc
blob - 4f07a3ef3f1b6dfc6da80ebc11996b99bbe90669
blob + b8c555ceffae58e8e93eb6eecad45354d127f0c7
--- include/globals.h
+++ include/globals.h
// clients from Keep Alive packets.
#define NETWORK_TIMEOUT_TIME 15000000
+// Size of the receive buffer for incoming string data
+#define MAX_RECV_BUF_LEN 256
+
// If defined, sends the server brand to clients. Doesn't do much, but will
// show up in the top-left of the F3/debug menu, in the Minecraft client.
// You can change the brand string in the "brand" variable in src/globals.c
blob - f83ba09748d486b9bef7b6f325e6a8b9c39155ff
blob + 9eb796dbb8671892346b640e07410a2d819e3102
--- include/tools.h
+++ include/tools.h
float readFloat (int client_fd);
double readDouble (int client_fd);
+ssize_t readLengthPrefixedData (int client_fd);
void readString (int client_fd);
+void readStringN (int client_fd, uint32_t max_length);
uint32_t fast_rand ();
uint64_t splitmix64 (uint64_t state);
blob - 731e7fad9e48b6855e54acb2603331ca3c42380b
blob + 1b5b462f7b7d434bac0b4c0b00ede8cd0b12501c
--- src/globals.c
+++ src/globals.c
#endif
ssize_t recv_count;
-uint8_t recv_buffer[256] = {0};
+uint8_t recv_buffer[MAX_RECV_BUF_LEN] = {0};
uint32_t world_seed = INITIAL_WORLD_SEED;
uint32_t rng_seed = INITIAL_RNG_SEED;
blob - cbb110903212a3c5afd085aa3c8cdc688d50d4cc
blob + 97c26f1ebd721ff802b643e96bfea1e6a7254433
--- src/packets.c
+++ src/packets.c
count = (uint8_t)readVarInt(client_fd);
// ignore components
- tmp = readVarInt(client_fd);
- recv_all(client_fd, recv_buffer, tmp, false);
- tmp = readVarInt(client_fd);
- recv_all(client_fd, recv_buffer, tmp, false);
+ readLengthPrefixedData(client_fd);
+ readLengthPrefixedData(client_fd);
if (count > 0 && apply_changes) {
*p_item = item;
player->flagval_16 = readVarInt(client_fd);
player->flagval_8 = readVarInt(client_fd);
// ignore components
- tmp = readVarInt(client_fd);
- recv_all(client_fd, recv_buffer, tmp, false);
- tmp = readVarInt(client_fd);
- recv_all(client_fd, recv_buffer, tmp, false);
+ readLengthPrefixedData(client_fd);
+ readLengthPrefixedData(client_fd);
} else {
player->flagval_16 = 0;
player->flagval_8 = 0;
// C->S Chat Message
int cs_chat (int client_fd) {
- readString(client_fd);
+ // To be safe, cap messages to 32 bytes before the buffer length
+ readStringN(client_fd, 224);
PlayerData *player;
if (getPlayerData(client_fd, &player)) return 1;
size_t message_len = strlen((char *)recv_buffer);
uint8_t name_len = strlen(player->name);
- // To be safe, cap messages to 32 bytes before the buffer length
- if (message_len > 224) {
- recv_buffer[224] = '\0';
- message_len = 224;
- }
-
if (recv_buffer[0] != '!') { // Standard chat message
// Shift message contents forward to make space for player name tag
blob - 0b7050f9785d2d07f62890ca08ae09b4c24b3ecc
blob + a84ffd1d0d554d906f5000834af086c8bbeed8a5
--- src/tools.c
+++ src/tools.c
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) {
+ 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);
- recv_count = recv_all(client_fd, recv_buffer, length, false);
+ 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 () {