From 98762992fbe409f5c6c93d6760ee1e37e6f7049b Mon Sep 17 00:00:00 2001 From: Oneric Date: Sat, 17 May 2025 14:14:38 +0200 Subject: [PATCH 1/2] emoji: avoid crashing whole server on broken JSON It may still crash due to a race condition between checking for file existence and opening/streaming, but File.stream! has no safe version we can use to avoid this completely. Just not deleting such files during a reload is easy enough. --- lib/pleroma/emoji.ex | 6 +++--- lib/pleroma/emoji/loader.ex | 24 +++++++++++++++++------- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/lib/pleroma/emoji.ex b/lib/pleroma/emoji.ex index 933f4275a..1f8bc927a 100644 --- a/lib/pleroma/emoji.ex +++ b/lib/pleroma/emoji.ex @@ -76,9 +76,6 @@ def get_all do :ets.tab2list(@ets) end - @doc "Clear out old emojis" - def clear_all, do: :ets.delete_all_objects(@ets) - @doc false def init(_) do @ets = :ets.new(@ets, @ets_options) @@ -109,7 +106,10 @@ def code_change(_old_vsn, state, _extra) do {:ok, state} end + defp update_emojis([]), do: true + defp update_emojis(emojis) do + :ets.delete_all_objects(@ets) :ets.insert(@ets, emojis) end diff --git a/lib/pleroma/emoji/loader.ex b/lib/pleroma/emoji/loader.ex index 03c96fbcf..96a8747ff 100644 --- a/lib/pleroma/emoji/loader.ex +++ b/lib/pleroma/emoji/loader.ex @@ -69,7 +69,6 @@ def load do load_pack(Path.join(emoji_dir_path, pack), emoji_groups) end) - Emoji.clear_all() emojis end @@ -104,13 +103,9 @@ defp load_pack(pack_dir, emoji_groups) do if File.exists?(pack_file) do Logger.debug("Loading emoji pack from JSON: #{pack_file}") - contents = Jason.decode!(File.read!(pack_file)) - contents["files"] - |> Enum.map(fn {name, rel_file} -> - filename = Path.join("/emoji/#{pack_name}", rel_file) - {name, filename, ["pack:#{pack_name}"]} - end) + Jason.decode(File.read!(pack_file)) + |> load_from_pack(pack_name) else # Load from emoji.txt / all files emoji_txt = Path.join(pack_dir, "emoji.txt") @@ -135,6 +130,21 @@ defp load_pack(pack_dir, emoji_groups) do end end + defp load_from_pack({:ok, %{"files" => files}}, pack_name) when is_map(files) do + Enum.map(files, fn {name, rel_file} -> + filename = Path.join("/emoji/#{pack_name}", rel_file) + {name, filename, ["pack:#{pack_name}"]} + end) + end + + defp load_from_pack(pack_json_result, pack_name) do + Logger.error( + "Failed to load emoji pack #{pack_name} from pack.json:\n#{inspect(pack_json_result)}" + ) + + [] + end + def make_shortcode_to_file_map(pack_dir, exts) do find_all_emoji(pack_dir, exts) |> Enum.map(&Path.relative_to(&1, pack_dir)) From 489b17a60dcbbdb8bf2aab6a94ec7aec998e9877 Mon Sep 17 00:00:00 2001 From: Oneric Date: Sat, 17 May 2025 14:31:55 +0200 Subject: [PATCH 2/2] test/emoji: clean up after failure Since the cleanup is only registered after everything succeeded, no cleanup was done on failure permanently breaking the test --- test/mix/tasks/pleroma/emoji_test.exs | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/test/mix/tasks/pleroma/emoji_test.exs b/test/mix/tasks/pleroma/emoji_test.exs index 6549fbb70..57105acaf 100644 --- a/test/mix/tasks/pleroma/emoji_test.exs +++ b/test/mix/tasks/pleroma/emoji_test.exs @@ -144,6 +144,12 @@ test "with default extensions", %{url: url} do name = "pack1" pack_json = "#{name}.json" files_json = "#{name}_file.json" + + on_exit(fn -> + File.rm(pack_json) + File.rm(files_json) + end) + refute File.exists?(pack_json) refute File.exists?(files_json) @@ -172,17 +178,18 @@ test "with default extensions", %{url: url} do assert File.exists?(pack_json) assert File.exists?(files_json) - - on_exit(fn -> - File.rm!(pack_json) - File.rm!(files_json) - end) end test "with custom extensions and update existing files", %{url: url} do name = "pack2" pack_json = "#{name}.json" files_json = "#{name}_file.json" + + on_exit(fn -> + File.rm(pack_json) + File.rm(files_json) + end) + refute File.exists?(pack_json) refute File.exists?(files_json) @@ -233,11 +240,6 @@ test "with custom extensions and update existing files", %{url: url} do end) assert captured =~ "#{pack_json} has been updated with the pack2 pack" - - on_exit(fn -> - File.rm!(pack_json) - File.rm!(files_json) - end) end end end