minetest icon indicating copy to clipboard operation
minetest copied to clipboard

Server crashes if generated chat message is too long

Open gpcf opened this issue 5 years ago • 4 comments

Minetest version
Minetest 5.2.0-dev-03e1f23a (Linux)

OS / Hardware

Operating system: Debian 10 CPU: Intel(R) Xeon(R) Gold 6140 CPU @ 2.30GHz

Summary

Server crashes if a generated chat message is too long with the following output:

2020-01-19 21:22:47: ERROR[Main]: ServerError: AsyncErr: ServerThread::run Lua: Runtime error from mod '' in callback on_chat_message(): String too long
2020-01-19 21:22:47: ERROR[Main]: stack traceback:
2020-01-19 21:22:47: ERROR[Main]:       [C]: in function 'chat_send_player'
2020-01-19 21:22:47: ERROR[Main]:       /usr/share/games/minetest/builtin/game/chat.lua:71: in function </usr/share/games/minetest/builtin/game/chat.lua:48>
2020-01-19 21:22:47: ERROR[Main]:       /usr/share/games/minetest/builtin/game/register.lua:429: in function </usr/share/games/minetest/builtin/game/register.lua:413>

In this case, it was caused by /list_areas from the areas mod, on a server with 10k+ areas. Given the number of mods that might take user input, this could be a serious security risk.

Steps to reproduce

call minetest.chat_send_player with an extremely long chat message.

gpcf avatar Jan 19 '20 20:01 gpcf

Should probably raise a warning + stack trace instead.

sfan5 avatar Jan 19 '20 20:01 sfan5

I'm interested into contributing a fix for this issue. Would it make sense to split the chat message into multiple messages and send one by one, or it is wise to cap at the maximum byte size and log a warning?

ronoaldo avatar Aug 02 '22 19:08 ronoaldo

How about putting some ellipsis and log a warning? The limit is around 66 000 characters, that's definitely more than annoying already to see in chat. It should be up to the modder to split their output in pages, such as /list_areas 2, /list_areas 3 etc

Zughy avatar Aug 10 '22 11:08 Zughy

in case anyone wants some lua code to patch their server to keep /profiler print from crashing their server, here's some:

local old_chat_send_player = minetest.chat_send_player

function minetest.chat_send_player(name, text)
	while #text > 65000 do
		local found_newline = false
		for i = 65000, 1, -1 do
			if text:sub(i, i) == "\n" then
				old_chat_send_player(name, text:sub(1, i - 1))
				text = text:sub(i + 1)
				found_newline = true
				break
			end
		end

		if not found_newline then
			old_chat_send_player(name, text:sub(1, 65000))
			text = text:sub(65000 + 1)
		end
	end

	old_chat_send_player(name, text)
end

fluxionary avatar Aug 30 '22 23:08 fluxionary