gnucash stable: Bug 799320 - GNUCash Immediately Exits on Startup
John Ralls
jralls at code.gnucash.org
Thu May 30 18:40:27 EDT 2024
Updated via https://github.com/Gnucash/gnucash/commit/35a0e777 (commit)
from https://github.com/Gnucash/gnucash/commit/99a92659 (commit)
commit 35a0e7774e798063aae488ba956a5b57afe8f0c6
Author: John Ralls <jralls at ceridwen.us>
Date: Thu May 30 15:34:11 2024 -0700
Bug 799320 - GNUCash Immediately Exits on Startup
Some excellent and insightful debugging by the reporter found that the cause was specifying
a locale as en_US.utf8 instead of en_US.utf-8. GnuLib's locale functions and so Guile's are
apparently quite picky on Win32.
To address this move reading the environment file to before we set the mac and Windows
locales and ensure that UTF/UCS and ISO-8859 character sets are specified with minus
separators on Windows. I tested on macOS and didn't experience the crash.
diff --git a/gnucash/gnucash-core-app.cpp b/gnucash/gnucash-core-app.cpp
index 08ae1fc9cb..e35055a274 100644
--- a/gnucash/gnucash-core-app.cpp
+++ b/gnucash/gnucash-core-app.cpp
@@ -175,10 +175,10 @@ Gnucash::CoreApp::CoreApp (const char* app_name) : m_app_name {app_name}
* The user may have configured a different language via
* the environment file.
*/
+ gnc_environment_setup();
#if defined MAC_INTEGRATION || defined __MINGW32__
sys_locale = set_platform_locale();
#endif
- gnc_environment_setup();
#if ! defined MAC_INTEGRATION && ! defined __MINGW32__/* setlocale already done */
sys_locale = g_strdup (setlocale (LC_ALL, ""));
if (!sys_locale)
diff --git a/gnucash/gnucash-locale-windows.c b/gnucash/gnucash-locale-windows.c
index 753af7c204..6e7666ed4a 100644
--- a/gnucash/gnucash-locale-windows.c
+++ b/gnucash/gnucash-locale-windows.c
@@ -27,6 +27,74 @@
#include <glib/gi18n.h>
#include "gnucash-locale-platform.h"
+static void
+rectify_utf(const char* envvar, const char* locale,
+ const char* dot, const char* rest)
+{
+ char *new_locale;
+ if (rest && *rest)
+ new_locale = g_strdup_printf ("%s.UTF-%s@%s",
+ locale, dot + 3, rest);
+ else
+ new_locale = g_strdup_printf ("%s.UTF-%s", locale, dot + 3);
+
+ _putenv_s (envvar, new_locale);
+ g_free(new_locale);
+}
+
+static void
+rectify_iso(const char* envvar, const char* locale,
+ const char* dot, const char* rest)
+{
+
+ char *eefn = strstr (dot, "8859");
+
+ if (!(eefn && *eefn))
+ return;
+
+ char* isonum = (*(eefn + 4) == '-') ? eefn + 5 : eefn + 4;
+
+ if (*isonum == '\0')
+ return;
+
+ char *new_locale;
+ if (rest && *rest)
+ new_locale = g_strdup_printf ("%s.ISO-8859-%s@%s", locale, isonum, rest);
+ else
+ new_locale = g_strdup_printf ("%s.ISO-8859-%s", locale, isonum);
+
+ _putenv_s (envvar, new_locale);
+ g_free (new_locale);
+}
+
+static void
+rectify_environment_charset(const char* envvar)
+{
+ if (!(envvar && *envvar))
+ return;
+ if (strcmp (envvar, "LANG") && strncmp (envvar, "LC_", 3))
+ return;
+ char* saveptr;
+ char* varval = getenv (envvar);
+ char* locale = strtok_r (varval, ".", &saveptr);
+ char* dot = strtok_r (NULL, "@", &saveptr);
+
+ if (!dot) //strsep didn't find a .
+ return;
+
+ char* rest = strtok_r (NULL, "@", &saveptr);
+
+ if ((strncasecmp (dot, "utf", 3) == 0 || strncasecmp (dot, "ucs", 3) == 0) &&
+ dot[3] != '-')
+ return rectify_utf (envvar, locale, dot, rest);
+
+ if (strncasecmp (dot, "iso", 3) == 0 && strlen (dot) >= 8 &&
+ dot[3] != '-' && dot[8] != '-')
+ return rectify_iso (envvar, locale, dot, rest);
+
+ //Otherwise do nothing
+}
+
/* If one of the Unix locale variables LC_ALL, LC_MESSAGES, or LANG is
* set in the environment check to see if it's a valid locale and if
* it is set both the Windows and POSIX locales to that. If not
@@ -37,6 +105,17 @@ set_platform_locale(void)
{
WCHAR lpLocaleName[LOCALE_NAME_MAX_LENGTH];
char *locale = NULL;
+ /* Prevent Bug 799320 by ensuring that the localization
+ environment variables of interest have well-formed UTF or
+ ISO-8859 specifiers for GnuLib's interpretation of well-formed,
+ which means having minuses in the right places. This only
+ protects agains missing hyphens, it won't help if you specify
+ utf42 as a charset when you meant utf32.
+ */
+ rectify_environment_charset ("LANG");
+ rectify_environment_charset ("LC_ALL");
+ rectify_environment_charset ("LC_MESSAGES");
+ rectify_environment_charset ("LC_CTYPE");
if (((locale = getenv ("LC_ALL")) != NULL && locale[0] != '\0') ||
((locale = getenv ("LC_MESSAGES")) != NULL && locale[0] != '\0') ||
Summary of changes:
gnucash/gnucash-core-app.cpp | 2 +-
gnucash/gnucash-locale-windows.c | 79 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 80 insertions(+), 1 deletion(-)
More information about the gnucash-changes
mailing list