Limit player names and chat messages, both in terms of visible and total characters.

fixes #1099
fixes #1098
This commit is contained in:
IntegratedQuantum 2025-02-23 19:21:11 +01:00
parent 8e4a39e84e
commit c343d434cb
4 changed files with 63 additions and 3 deletions

View File

@ -572,7 +572,7 @@ pub const TextBuffer = struct { // MARK: TextBuffer
}
}
const Parser = struct {
pub const Parser = struct {
unicodeIterator: std.unicode.Utf8Iterator,
currentFontEffect: FontEffect,
parsedText: main.List(u32),
@ -664,6 +664,49 @@ pub const TextBuffer = struct { // MARK: TextBuffer
}
};
}
pub fn countVisibleCharacters(text: []const u8) usize {
var unicodeIterator = std.unicode.Utf8Iterator{.bytes = text, .i = 0};
var count: usize = 0;
var curChar = unicodeIterator.nextCodepoint() orelse return count;
while(true) switch(curChar) {
'*' => {
curChar = unicodeIterator.nextCodepoint() orelse break;
},
'_' => {
curChar = unicodeIterator.nextCodepoint() orelse break;
if(curChar == '_') {
curChar = unicodeIterator.nextCodepoint() orelse break;
} else {
count += 1;
}
},
'~' => {
curChar = unicodeIterator.nextCodepoint() orelse break;
if(curChar == '~') {
curChar = unicodeIterator.nextCodepoint() orelse break;
} else {
count += 1;
}
},
'\\' => {
curChar = unicodeIterator.nextCodepoint() orelse break;
curChar = unicodeIterator.nextCodepoint() orelse break;
count += 1;
},
'#' => {
for(0..7) |_| curChar = unicodeIterator.nextCodepoint() orelse break;
},
'§' => {
curChar = unicodeIterator.nextCodepoint() orelse break;
},
else => {
count += 1;
curChar = unicodeIterator.nextCodepoint() orelse break;
}
};
return count;
}
};
pub fn init(allocator: NeverFailingAllocator, text: []const u8, initialFontEffect: FontEffect, showControlCharacters: bool, alignment: Alignment) TextBuffer {

View File

@ -20,6 +20,10 @@ var textComponent: *TextInput = undefined;
const padding: f32 = 8;
fn apply(_: usize) void {
if(textComponent.currentString.items.len > 500 or main.graphics.TextBuffer.Parser.countVisibleCharacters(textComponent.currentString.items) > 50) {
std.log.err("Name is too long with {}/{} characters. Limits are 50/500", .{main.graphics.TextBuffer.Parser.countVisibleCharacters(textComponent.currentString.items), textComponent.currentString.items.len});
return;
}
const oldName = settings.playerName;
main.globalAllocator.free(settings.playerName);
settings.playerName = main.globalAllocator.dupe(u8, textComponent.currentString.items);

View File

@ -139,7 +139,12 @@ pub fn addMessage(msg: []const u8) void {
pub fn sendMessage(_: usize) void {
if(input.currentString.items.len != 0) {
main.network.Protocols.chat.send(main.game.world.?.conn, input.currentString.items);
input.clear();
const data = input.currentString.items;
if(data.len > 10000 or main.graphics.TextBuffer.Parser.countVisibleCharacters(data) > 1000) {
std.log.err("Chat message is too long with {}/{} characters. Limits are 1000/10000", .{main.graphics.TextBuffer.Parser.countVisibleCharacters(data), data.len});
} else {
main.network.Protocols.chat.send(main.game.world.?.conn, data);
input.clear();
}
}
}

View File

@ -654,6 +654,10 @@ pub const Protocols = struct {
const zon = ZonElement.parseFromString(main.stackAllocator, data[1..]);
defer zon.deinit(main.stackAllocator);
const name = zon.get([]const u8, "name", "unnamed");
if(name.len > 500 or main.graphics.TextBuffer.Parser.countVisibleCharacters(name) > 50) {
std.log.err("Player has too long name with {}/{} characters.", .{main.graphics.TextBuffer.Parser.countVisibleCharacters(name), name.len});
return error.Invalid;
}
const version = zon.get([]const u8, "version", "unknown");
std.log.info("User {s} joined using version {s}.", .{name, version});
@ -1081,6 +1085,10 @@ pub const Protocols = struct {
pub const asynchronous = false;
fn receive(conn: *Connection, data: []const u8) !void {
if(conn.user) |user| {
if(data.len > 10000 or main.graphics.TextBuffer.Parser.countVisibleCharacters(data) > 1000) {
std.log.err("Received too long chat message with {}/{} characters.", .{main.graphics.TextBuffer.Parser.countVisibleCharacters(data), data.len});
return error.Invalid;
}
main.server.messageFrom(data, user);
} else {
main.gui.windowlist.chat.addMessage(data);