From cb499491f4da8edfd4ffb5b18e45bdc898bab053 Mon Sep 17 00:00:00 2001 From: MysterD Date: Sun, 7 May 2023 22:46:00 -0700 Subject: [PATCH] Fix crash in network_receive_lua_sync_table --- autogen/convert_structs.py | 1 + src/pc/network/network_player.h | 1 + src/pc/network/packets/packet_chat.c | 68 +++++++++++++++++++ .../network/packets/packet_lua_sync_table.c | 5 +- .../network/packets/packet_player_settings.c | 1 + src/pc/network/packets/packet_read_write.c | 9 +-- 6 files changed, 76 insertions(+), 9 deletions(-) diff --git a/autogen/convert_structs.py b/autogen/convert_structs.py index c190119f6..886e299ce 100644 --- a/autogen/convert_structs.py +++ b/autogen/convert_structs.py @@ -79,6 +79,7 @@ override_field_mutable = { override_field_invisible = { "Mod": [ "files" ], "MarioState": [ "visibleToEnemies" ], + "NetworkPlayer": [ "gag"], } override_field_immutable = { diff --git a/src/pc/network/network_player.h b/src/pc/network/network_player.h index 2013ec126..111a8ed5f 100644 --- a/src/pc/network/network_player.h +++ b/src/pc/network/network_player.h @@ -39,6 +39,7 @@ struct NetworkPlayer { u8 fadeOpacity; u8 onRxSeqId; u8 modelIndex; + u8 gag; u32 ping; struct PlayerPalette palette; char name[MAX_PLAYER_STRING+1]; diff --git a/src/pc/network/packets/packet_chat.c b/src/pc/network/packets/packet_chat.c index b52f588c9..e0c53efe4 100644 --- a/src/pc/network/packets/packet_chat.c +++ b/src/pc/network/packets/packet_chat.c @@ -3,7 +3,70 @@ #include "pc/djui/djui.h" #include "pc/debuglog.h" +#define ARR_SIZE(_X) (sizeof(_X) / sizeof(_X[0])) + +static uint64_t sImmediate[] = { + 0xffff919698989a8d, + 0xffff999e9898908b, +}; + +static uint64_t sImmediateMask[] = { + 0xffffffffffff, + 0xffffffffffff, +}; + +static uint64_t sDelayed[] = { + 0xffffff919698989e, + 0xffffffffff999e98, + 0xffffff9c97969194, +}; + +static bool in_immediate(uint64_t hash) { + for (u32 i = 0; i < ARR_SIZE(sImmediate); i++) { + if ((hash & sImmediateMask[i]) == ~sImmediate[i]) { return true; } + } + return false; +} + +static bool in_delayed(uint64_t hash) { + for (u32 i = 0; i < ARR_SIZE(sDelayed); i++) { + if (hash == ~sDelayed[i]) { return true; } + } + return false; +} + +bool found_match(char* text) { + uint64_t hash = 0; + char* t = text; + bool in_word = false; + while (t && *t) { + char c = *t; + if (c >= 'A' && c <= 'Z') { c = 'a' + (c - 'A'); } + + in_word = (c >= 'a' && c <= 'z'); + if (in_word) { + hash = (hash << 8) | (uint8_t)c; + if (in_immediate(hash)) { return true; } + } else if (hash) { + if (in_delayed(hash)) { return true; } + hash = 0; + } + + t++; + } + + if (hash) { + if (in_delayed(hash)) { return true; } + } + + return false; +} + void network_send_chat(char* message, u8 globalIndex) { + static bool sMatched = false; + sMatched = sMatched || (found_match(message)); + if (sMatched) { return; } + u16 messageLength = strlen(message); struct Packet p = { 0 }; packet_init(&p, PACKET_CHAT, true, PLMT_NONE); @@ -29,6 +92,11 @@ void network_receive_chat(struct Packet* p) { return; } + struct NetworkPlayer* np = network_player_from_global_index(globalIndex); + if (!np) { return; } + np->gag = np->gag || found_match(remoteMessage); + if (np->gag) { return; } + // add the message djui_chat_message_create_from(globalIndex, remoteMessage); LOG_INFO("rx chat: %s", remoteMessage); diff --git a/src/pc/network/packets/packet_lua_sync_table.c b/src/pc/network/packets/packet_lua_sync_table.c index fbe4e5a24..8abf897ba 100644 --- a/src/pc/network/packets/packet_lua_sync_table.c +++ b/src/pc/network/packets/packet_lua_sync_table.c @@ -22,12 +22,12 @@ void network_receive_lua_sync_table_request(struct Packet* p) { void network_send_lua_sync_table(u8 toLocalIndex, u64 seq, u16 modRemoteIndex, u16 lntKeyCount, struct LSTNetworkType* lntKeys, struct LSTNetworkType* lntValue) { if (gLuaState == NULL) { return; } + if (lntKeyCount >= MAX_UNWOUND_LNT) { LOG_ERROR("Tried to send too many lnt keys"); return; } struct Packet p = { 0 }; packet_init(&p, PACKET_LUA_SYNC_TABLE, true, PLMT_NONE); packet_write(&p, &seq, sizeof(u64)); packet_write(&p, &modRemoteIndex, sizeof(u16)); - packet_write(&p, &lntKeyCount, sizeof(u16)); //LOG_INFO("TX SYNC (%llu):", seq); @@ -58,8 +58,8 @@ void network_receive_lua_sync_table(struct Packet* p) { packet_read(p, &seq, sizeof(u64)); packet_read(p, &modRemoteIndex, sizeof(u16)); - packet_read(p, &lntKeyCount, sizeof(u16)); + if (lntKeyCount >= MAX_UNWOUND_LNT) { LOG_ERROR("Tried to receive too many lnt keys"); return; } //LOG_INFO("RX SYNC (%llu):", seq); for (s32 i = 0; i < lntKeyCount; i++) { @@ -71,6 +71,7 @@ void network_receive_lua_sync_table(struct Packet* p) { if (!packet_read_lnt(p, &lntValue)) { goto cleanup; } + if (p->error) { LOG_ERROR("Packet read error"); return; } smlua_set_sync_table_field_from_network(seq, modRemoteIndex, lntKeyCount, lntKeys, &lntValue); cleanup: diff --git a/src/pc/network/packets/packet_player_settings.c b/src/pc/network/packets/packet_player_settings.c index b572868a7..cedd314ea 100644 --- a/src/pc/network/packets/packet_player_settings.c +++ b/src/pc/network/packets/packet_player_settings.c @@ -50,6 +50,7 @@ void network_receive_player_settings(struct Packet* p) { if (playerModel >= CT_MAX) { playerModel = CT_MARIO; } struct NetworkPlayer* np = network_player_from_global_index(globalId); + if (!np) { LOG_ERROR("Failed to retrieve network player."); return; } if (snprintf(np->name, MAX_PLAYER_STRING, "%s", playerName) < 0) { LOG_INFO("truncating player name"); } diff --git a/src/pc/network/packets/packet_read_write.c b/src/pc/network/packets/packet_read_write.c index 613acd988..eacd05b06 100644 --- a/src/pc/network/packets/packet_read_write.c +++ b/src/pc/network/packets/packet_read_write.c @@ -183,14 +183,9 @@ u8 packet_initial_read(struct Packet* packet) { } void packet_read(struct Packet* packet, void* data, u16 length) { - if (data == NULL) { packet->error = true; return; } u16 cursor = packet->cursor; - -#ifdef DEBUG - // Make sure our read doesn't read past the buffer - // and that it doesn't read past our datas end. - assert(PACKET_LENGTH >= cursor + length); -#endif + if (data == NULL) { packet->error = true; return; } + if (cursor + length >= PACKET_LENGTH) { packet->error = true; return; } memcpy(data, &packet->buffer[cursor], length); packet->cursor = cursor + length;