Skip to content

Commit da26e01

Browse files
authored
bugfix(network): Deny players with invalid names from joining a LAN game room (#1595)
1 parent b399119 commit da26e01

File tree

1 file changed

+64
-1
lines changed

1 file changed

+64
-1
lines changed

Core/GameEngine/Source/GameNetwork/LANAPIhandlers.cpp

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,51 @@ void LANAPI::handleRequestGameInfo( LANMessage *msg, UnsignedInt senderIP )
202202
}
203203
}
204204

205+
static Bool IsInvalidCharForPlayerName(const WideChar c)
206+
{
207+
return c < L' ' // C0 control chars
208+
|| c == L',' || c == L':' || c == L';' // chars used for strtok in ParseAsciiStringToGameInfo
209+
|| (c >= L'\x007f' && c <= L'\x009f') // DEL + C1 control chars
210+
|| c == L'\x2028' || c == L'\x2029' // line and paragraph separators
211+
|| (c >= L'\xdc00' && c <= L'\xdfff') // low surrogate, for chars beyond the Unicode Basic Multilingual Plane
212+
|| (c >= L'\xd800' && c <= L'\xdbff'); // high surrogate, for chars beyond the BMP
213+
}
214+
215+
static Bool IsSpaceCharacter(const WideChar c)
216+
{
217+
return c == L' ' // space
218+
|| c == L'\xA0' // no-break space
219+
|| c == L'\x1680' // ogham space mark
220+
|| (c >= L'\x2000' && c <= L'\x200A') // en/em spaces, figure, punctuation, thin, hair
221+
|| c == L'\x202F' // narrow no-break space
222+
|| c == L'\x205F' // medium mathematical space
223+
|| c == L'\x3000'; // ideographic space
224+
}
225+
226+
static Bool ContainsInvalidChars(const WideChar* playerName)
227+
{
228+
DEBUG_ASSERTCRASH(playerName != NULL, ("playerName is NULL"));
229+
while (*playerName)
230+
{
231+
if (IsInvalidCharForPlayerName(*playerName++))
232+
return true;
233+
}
234+
235+
return false;
236+
}
237+
238+
static Bool ContainsAnyReadableChars(const WideChar* playerName)
239+
{
240+
DEBUG_ASSERTCRASH(playerName != NULL, ("playerName is NULL"));
241+
while (*playerName)
242+
{
243+
if (!IsSpaceCharacter(*playerName++))
244+
return true;
245+
}
246+
247+
return false;
248+
}
249+
205250
void LANAPI::handleRequestJoin( LANMessage *msg, UnsignedInt senderIP )
206251
{
207252
UnsignedInt responseIP = senderIP; // need this cause the player may or may not be
@@ -290,7 +335,25 @@ void LANAPI::handleRequestJoin( LANMessage *msg, UnsignedInt senderIP )
290335
}
291336
#endif
292337

293-
// We're the host, so see if he has a duplicate name
338+
// TheSuperHackers @bugfix slurmlord 18/09/2025 need to validate the name of the connecting player before
339+
// allowing them to join to prevent messing up the format of game state string. Commas, colons, semicolons etc.
340+
// should not be in a player name. It should also not consist of only space characters.
341+
if (canJoin)
342+
{
343+
if (ContainsInvalidChars(msg->name) || !ContainsAnyReadableChars(msg->name))
344+
{
345+
// Just deny with a duplicate name reason, for backwards compatibility with retail
346+
reply.messageType = LANMessage::MSG_JOIN_DENY;
347+
reply.GameNotJoined.reason = LANAPIInterface::RET_DUPLICATE_NAME;
348+
reply.GameNotJoined.gameIP = m_localIP;
349+
reply.GameNotJoined.playerIP = senderIP;
350+
canJoin = false;
351+
352+
DEBUG_LOG(("LANAPI::handleRequestJoin - join denied because of illegal characters in the player name."));
353+
}
354+
}
355+
356+
// Then see if the player has a duplicate name
294357
for (player = 0; canJoin && player<MAX_SLOTS; ++player)
295358
{
296359
LANGameSlot *slot = m_currentGame->getLANSlot(player);

0 commit comments

Comments
 (0)