summaryrefslogtreecommitdiff
path: root/src/locale/localed-util.c
diff options
context:
space:
mode:
authorOlivier Gayot <olivier.gayot@sigexec.com>2023-04-07 10:32:07 +0200
committerMike Yuan <me@yhndnzj.com>2023-04-08 00:08:43 +0800
commitb24b10592d74b73529817813ff33f7e28e79ca41 (patch)
treed623173badba11d251005bda18fefc19baafdd55 /src/locale/localed-util.c
parent381ccb424643acd8bf99e5db16ad96b64996e4e9 (diff)
downloadsystemd-b24b10592d74b73529817813ff33f7e28e79ca41.tar.gz
localed: fix invalid free after shifting pointers using strstrip
After manually editing /etc/locale.gen, calling localectl set-locale sometimes fails. When it fails, the systemd journal shows: systemd-localed: free() / invalid pointer. It turned out that it only fails if some of the uncommented lines in /etc/locale.gen have leading spaces, as in: * C.UTF-8 <= OK * en_US.UTF-8 <= OK * fr_FR.UTF-8 <= NOK After parsing a line from /etc/locale.gen, we use strstrip() to obtain the "trimmed" line (without leading or trailing spaces). However, we store the result of strstrip() in the original pointer containing the untrimmed line. This pointer is later passed to free (this is done automatically using _cleanup_free_). This is a problem because if any leading space is present, the pointer will essentially be shifted from its original value. This will result in an invalid free upon cleanup. The same issue is present in the locale_gen_locale_supported function. Fixed by storing the result of strstrip() in a different pointer.
Diffstat (limited to 'src/locale/localed-util.c')
-rw-r--r--src/locale/localed-util.c10
1 files changed, 5 insertions, 5 deletions
diff --git a/src/locale/localed-util.c b/src/locale/localed-util.c
index 8ad5256ad9..5247d139eb 100644
--- a/src/locale/localed-util.c
+++ b/src/locale/localed-util.c
@@ -948,6 +948,7 @@ static int locale_gen_locale_supported(const char *locale_entry) {
for (;;) {
_cleanup_free_ char *line = NULL;
+ char *l;
r = read_line(f, LONG_LINE_MAX, &line);
if (r < 0)
@@ -955,8 +956,8 @@ static int locale_gen_locale_supported(const char *locale_entry) {
if (r == 0)
return 0;
- line = strstrip(line);
- if (strcaseeq_ptr(line, locale_entry))
+ l = strstrip(line);
+ if (strcaseeq_ptr(l, locale_entry))
return 1;
}
}
@@ -1034,14 +1035,13 @@ int locale_gen_enable_locale(const char *locale) {
continue;
}
- line = strstrip(line);
- if (isempty(line)) {
+ line_locale = strstrip(line);
+ if (isempty(line_locale)) {
fputc('\n', fw);
first_line = false;
continue;
}
- line_locale = line;
if (line_locale[0] == '#')
line_locale = strstrip(line_locale + 1);
else if (strcaseeq_ptr(line_locale, locale_entry))