Skip to content

GitLab

  • Menu
Projects Groups Snippets
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
  • Sign in / Register
  • pan pan
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
  • Issues 89
    • Issues 89
    • List
    • Boards
    • Service Desk
    • Milestones
  • Merge requests 0
    • Merge requests 0
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
  • Deployments
    • Deployments
    • Environments
    • Releases
  • Monitor
    • Monitor
    • Incidents
  • Packages & Registries
    • Packages & Registries
    • Container Registry
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Repository
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • GNOME
  • panpan
  • Issues
  • #1

Closed
Open
Created Sep 16, 2018 by Albert Hofkamp@Alberth

Crash on startup (due to broken locale)

Since (I think, but it is a long time ago) 1.4.3-ish, pan crashed on start-up. Reading the notes on 1.4.5, I had hopes it would be fixed, but alas, nope.

So I decided to find out some more.

$ git lg
* 22c743d (HEAD -> master, origin/master, origin/HEAD) Update Swedish translation

$ cat build_it.sh
#!/bin/sh
set -e -u -x

CCFLAGS=-g CXXFLAGS=-g ./autogen.sh --prefix=$HOME/pan2/installed
make
make install

After running the script, starting the installed pan ~/pan2/installed/bin/pan with gdb. It crashed as normal, high-lights:

Thread 1 "pan" received signal SIGSEGV, Segmentation fault.
0x00007ffff417b845 in __strstr_sse2 () from /lib64/libc.so.6

#0  0x00007ffff417b845 in __strstr_sse2 () at /lib64/libc.so.6
#1  0x00000000007a0987 in EvolutionDateMaker::e_strftime_fix_am_pm(char*, unsigned long, char const*, tm const*) const (this=0x7fffffffa570, s=0x7fffffffa3f0 "0\244\377\377\377\177", max=100, fmt=0x0, tm=0x7fffffffa460) at e-util.cc:145
#2  0x00000000007a0ab3 in EvolutionDateMaker::e_utf8_strftime_fix_am_pm(char*, unsigned long, char const*, tm const*) const (this=0x7fffffffa570, s=0x7fffffffa3f0 "0\244\377\377\377\177", max=100, locale_fmt=0x0, tm=0x7fffffffa460) at e-util.cc:170
#3  0x00000000007a1262 in EvolutionDateMaker::get_date_string(long) const (this=0x7fffffffa570, then_time=1536904627) at e-util.cc:319
#4  0x0000000000667954 in pan::HeaderPane::create_row(EvolutionDateMaker const&, pan::Article const*) (this=0x1086c00, e=..., a=0x1c19e88) at header-pane.cc:429
#5  0x000000000066969d in pan::HeaderPane::on_tree_change(pan::Data::ArticleTree::Diffs const&) (this=0x1086c00, diffs=...) at header-pane.cc:831

... (omitted)

So it crashes inside libc. The fmt=0x0 argument doesn't look good, and indeed it's not:

145: if (am_pm_are_defined_in_locale || (!strstr(fmt,"%p") && !strstr(fmt,"%P")))
170: size_t ret = e_strftime_fix_am_pm(s, max, locale_fmt, tm);
319: e_utf8_strftime_fix_am_pm (buf, sizeof(buf), locale_this_week, &then_tm);

(lines may be off wrt the git version, as I added some debug lines I'll show below)

The locale_this_week is assigned in the constructor, and sure enough, it becomes NULL. Debug code:

diff --git a/pan/general/e-util.cc b/pan/general/e-util.cc
index af5ccd0..887a130 100644
--- a/pan/general/e-util.cc
+++ b/pan/general/e-util.cc
@@ -205,14 +205,61 @@ EvolutionDateMaker :: set_current_time (time_t now)
   }
 }
 
+static const char *safe_str(GError *e)
+{
+  return e ? e->message : "<null>";
+}
+
+static void pfmt(const char *t)
+{
+  if (!t) {
+    printf("fmt=<null>\n");
+    return;
+  }
+  printf("fmt:");
+  const char *s = t;
+  while (*s) {
+    printf(" %02x", *s);
+    s++;
+  }
+  printf(" \"");
+  s = t;
+  while (*s) {
+    if (*s >= 32 && *s <= 126) printf("%c", *s);
+    else printf(".");
+    s++;
+  }
+  printf("\"\n");
+}
+
 EvolutionDateMaker :: EvolutionDateMaker (time_t now)
 {
   // build the locale strings
-  locale_recent = g_locale_from_utf8 (_("%l∶%M %p"), -1, NULL, NULL, NULL);
-  locale_today = g_locale_from_utf8 (_("Today %l∶%M %p"), -1, NULL, NULL, NULL);
-  locale_this_week = g_locale_from_utf8 (_("%a %l∶%M %p"), -1, NULL, NULL, NULL);
-  locale_this_year = g_locale_from_utf8 (_("%b %d %l∶%M %p"), -1, NULL, NULL, NULL);
-  locale_old = g_locale_from_utf8 (_("%b %d %Y"), -1, NULL, NULL, NULL);
+  GError *e = NULL;
+  locale_recent = g_locale_from_utf8 (_("%l∶%M %p"), -1, NULL, NULL, &e);
+  pfmt(_("%l∶%M %p"));
+  printf("locale_recent = %p %s\n", locale_recent, safe_str(e));
+  if (e) g_error_free(e); e = NULL;
+
+  locale_today = g_locale_from_utf8 (_("Today %l∶%M %p"), -1, NULL, NULL, &e);
+  pfmt(_("Today %l∶%M %p"));
+  printf("locale_today = %p %s\n", locale_today, safe_str(e));
+  if (e) g_error_free(e); e = NULL;
+
+  locale_this_week = g_locale_from_utf8 (_("%a %l∶%M %p"), -1, NULL, NULL, &e);
+  pfmt(_("%a %l∶%M %p"));
+  printf("locale_this_week = %p %s\n", locale_this_week, safe_str(e));
+  if (e) g_error_free(e); e = NULL;
+
+  locale_this_year = g_locale_from_utf8 (_("%b %d %l∶%M %p"), -1, NULL, NULL, &e);
+  pfmt(_("%b %d %l∶%M %p"));
+  printf("locale_this_year = %p %s\n", locale_this_year, safe_str(e));
+  if (e) g_error_free(e); e = NULL;
+
+  locale_old = g_locale_from_utf8 (_("%b %d %Y"), -1, NULL, NULL, &e);
+  pfmt(_("%b %d %Y"));
+  printf("locale_old = %p %s\n", locale_old, safe_str(e));
+  if (e) g_error_free(e); e = NULL;
 
   // set the current time
   set_current_time (now);

Rebuilding with the patch, and running again gives:

fmt: 25 6c ffffffe2 ffffff88 ffffffb6 25 4d 20 25 70 "%l...%M %p"
locale_recent = (nil) Invalid byte sequence in conversion input
fmt: 54 6f 64 61 79 20 25 6c ffffffe2 ffffff88 ffffffb6 25 4d 20 25 70 "Today %l...%M %p"
locale_today = (nil) Invalid byte sequence in conversion input
fmt: 25 61 20 25 6c ffffffe2 ffffff88 ffffffb6 25 4d 20 25 70 "%a %l...%M %p"
locale_this_week = (nil) Invalid byte sequence in conversion input
fmt: 25 62 20 25 64 20 25 6c ffffffe2 ffffff88 ffffffb6 25 4d 20 25 70 "%b %d %l...%M %p"
locale_this_year = (nil) Invalid byte sequence in conversion input
fmt: 25 62 20 25 64 20 25 59 "%b %d %Y"
locale_old = 0x13f0290 <null>
fmt: 25 6c ffffffe2 ffffff88 ffffffb6 25 4d 20 25 70 "%l...%M %p"
locale_recent = (nil) Invalid byte sequence in conversion input
fmt: 54 6f 64 61 79 20 25 6c ffffffe2 ffffff88 ffffffb6 25 4d 20 25 70 "Today %l...%M %p"
locale_today = (nil) Invalid byte sequence in conversion input
fmt: 25 61 20 25 6c ffffffe2 ffffff88 ffffffb6 25 4d 20 25 70 "%a %l...%M %p"
locale_this_week = (nil) Invalid byte sequence in conversion input
fmt: 25 62 20 25 64 20 25 6c ffffffe2 ffffff88 ffffffb6 25 4d 20 25 70 "%b %d %l...%M %p"
locale_this_year = (nil) Invalid byte sequence in conversion input
fmt: 25 62 20 25 64 20 25 59 "%b %d %Y"
locale_old = 0x113d470 <null>

Note locale_this_week = (nil) Invalid byte sequence in conversion input, ie utf8 conversion is reporting an error and returns NULL. The output of pfmt(_("%a %l∶%M %p")); is at the line above: fmt: 25 61 20 25 6c ffffffe2 ffffff88 ffffffb6 25 4d 20 25 70 "%a %l...%M %p". There are 3 weird values in the utf8 string which may be the cause, given my quite broken locale (note that local_old does get converted correctly).

$ locale
LANG=C
LC_CTYPE="C"
LC_NUMERIC="C"
LC_TIME=en_DK.UTF-8
LC_COLLATE="C"
LC_MONETARY="C"
LC_MESSAGES="C"
LC_PAPER="C"
LC_NAME="C"
LC_ADDRESS="C"
LC_TELEPHONE="C"
LC_MEASUREMENT="C"
LC_IDENTIFICATION="C"
LC_ALL=

I haven't touched my locale for years, no idea why it's this strange. Fixing the locale with by all locale variables from env, and setting export LANG=en_US.utf8 fixes the problem.

In bugzilla, bugs https://bugzilla.gnome.org/show_bug.cgi?id=796482 and https://bugzilla.gnome.org/show_bug.cgi?id=791898 look like they also crash in the strftime libc function.

Something seems to attach too much to having a valid locale, but I don't know where. Hope it is useful.

To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information
Assignee
Assign to
Time tracking