1
0
mirror of https://github.com/weechat/weechat.git synced 2026-07-10 19:53:13 +02:00

core: fix time-of-check/time-of-use race condition on theme files

Open theme files directly instead of probing them with access() first in
commands /theme apply, /theme rename and /theme info. The renamed file is
now created with O_CREAT | O_EXCL so an existing theme is never clobbered.
This commit is contained in:
Sébastien Helleu
2026-07-05 12:34:38 +02:00
parent f65591cb56
commit 3950041801
17 changed files with 79 additions and 177 deletions
+1 -3
View File
@@ -7369,9 +7369,7 @@ COMMAND_CALLBACK(theme)
COMMAND_MIN_ARGS(3, "info");
/* file shadows registry: try user file first */
path = theme_user_file_path (argv[2]);
file_theme = NULL;
if (path && (access (path, R_OK) == 0))
file_theme = theme_file_parse (path);
file_theme = (path) ? theme_file_parse (path) : NULL;
if (!file_theme)
{
free (path);
+39 -32
View File
@@ -25,6 +25,8 @@
#include "config.h"
#endif
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -945,18 +947,11 @@ theme_apply (const char *name)
* so user themes have no steady-state memory footprint.
*/
path = theme_user_file_path (name);
if (path && (access (path, R_OK) == 0))
{
if (path)
file_theme = theme_file_parse (path);
if (!file_theme)
{
gui_chat_printf (NULL,
_("%sFailed to parse theme file \"%s\""),
gui_chat_prefix[GUI_CHAT_PREFIX_ERROR],
path);
free (path);
return WEECHAT_RC_ERROR;
}
free (path);
if (file_theme)
{
theme = file_theme;
}
else
@@ -968,11 +963,9 @@ theme_apply (const char *name)
_("%sTheme \"%s\" not found"),
gui_chat_prefix[GUI_CHAT_PREFIX_ERROR],
name);
free (path);
return WEECHAT_RC_ERROR;
}
}
free (path);
/* create a backup of current themable state, if enabled */
if (CONFIG_BOOLEAN(config_look_theme_backup)
@@ -1187,7 +1180,7 @@ theme_rename (const char *old_name, const char *new_name)
char *old_path, *new_path, line[2048];
FILE *fin, *fout;
const char *trimmed;
int in_info, name_done;
int in_info, name_done, fd;
if (!old_name || !old_name[0] || !new_name || !new_name[0])
return WEECHAT_RC_ERROR;
@@ -1230,39 +1223,53 @@ theme_rename (const char *old_name, const char *new_name)
old_path = theme_user_file_path (old_name);
if (!old_path)
return WEECHAT_RC_ERROR;
if (access (old_path, R_OK) != 0)
{
gui_chat_printf (NULL,
_("%sTheme \"%s\" not found"),
gui_chat_prefix[GUI_CHAT_PREFIX_ERROR],
old_name);
free (old_path);
return WEECHAT_RC_ERROR;
}
new_path = theme_user_file_path (new_name);
if (!new_path)
{
free (old_path);
return WEECHAT_RC_ERROR;
}
if (access (new_path, F_OK) == 0)
fin = fopen (old_path, "r");
if (!fin)
{
gui_chat_printf (NULL,
_("%sTheme \"%s\" already exists"),
_("%sTheme \"%s\" not found"),
gui_chat_prefix[GUI_CHAT_PREFIX_ERROR],
new_name);
old_name);
free (old_path);
free (new_path);
return WEECHAT_RC_ERROR;
}
fin = fopen (old_path, "r");
fout = (fin) ? fopen (new_path, "w") : NULL;
if (!fin || !fout)
fd = open (new_path, O_WRONLY | O_CREAT | O_EXCL, 0666);
if (fd < 0)
{
if (fin)
fclose (fin);
if (errno == EEXIST)
{
gui_chat_printf (NULL,
_("%sTheme \"%s\" already exists"),
gui_chat_prefix[GUI_CHAT_PREFIX_ERROR],
new_name);
}
else
{
gui_chat_printf (NULL,
_("%sFailed to rename theme \"%s\" to \"%s\""),
gui_chat_prefix[GUI_CHAT_PREFIX_ERROR],
old_name, new_name);
}
fclose (fin);
free (old_path);
free (new_path);
return WEECHAT_RC_ERROR;
}
fout = fdopen (fd, "w");
if (!fout)
{
close (fd);
unlink (new_path);
fclose (fin);
gui_chat_printf (NULL,
_("%sFailed to rename theme \"%s\" to \"%s\""),
gui_chat_prefix[GUI_CHAT_PREFIX_ERROR],