dcf21/pyxplot9

Pyxplot segfaults immediately in Ventura

Dave-Allured opened this issue · 2 comments

kencu commented

the function ppl_unixGetHomeDir seems to be returning NULL on Ventura, resulting in the crash.

This doesn't fix the function, but avoids the crash, at least:

% cat patch-pyxplot-no-crash-ventura.diff
--- ./src/settings/settingsInit.c.orig	2023-01-07 16:41:23
+++ ./src/settings/settingsInit.c	2023-01-07 16:41:31
@@ -364,7 +364,14 @@
   se->session_default.color_rep= SW_TERMCOL_GRN;
   se->session_default.color_wrn= SW_TERMCOL_BRN;
   se->session_default.color_err= SW_TERMCOL_RED;
-  strcpy(se->session_default.homedir, ppl_unixGetHomeDir(&context->errcontext));
+
+  char  *myhomedir;
+  myhomedir = ppl_unixGetHomeDir(&context->errcontext);
+  if (myhomedir == NULL) {
+  	myhomedir = "~";
+  }
+  strncpy(se->session_default.homedir,myhomedir,4096);
+  //strcpy(se->session_default.homedir, ppl_unixGetHomeDir(&context->errcontext));
 
   // Estimate the machine precision of the floating point unit we are using
   ppl_makeMachineEpsilon();
kencu commented

this problem is in the way this function works:

struct passwd *UnixGetPwEntry(pplerr_context *context)
 {
  int uid;
  struct passwd *ptr;

  uid = getuid();
  setpwent(); // Memory leak which valgrind reveals here is probably okay; getpwent sets up a static variable with malloc
  while ((ptr = getpwent()) != NULL)
   if (ptr->pw_uid == uid) break;
  endpwent();
  return(ptr);
 }

calling endpwent(); is clearing the ptr before returning it, resulting in the NULL:

adding this:

  printf("these are findings before endpwent: userid = %d, homedir = %s\n", ptr->pw_uid, ptr->pw_dir);
  endpwent();
  printf("these are findings after endpwent: userid = %d, homedir = %s\n", ptr->pw_uid, ptr->pw_dir);
  
  return(ptr);

we see:

% ./a.out     
these are findings before endpwent: userid = 501, homedir = /Users/myusername
these are findings after endpwent: userid = 0, homedir = (null)

there are several ways this might be fixed, but one way is to use a different function to find pw entry:

char *ppl_unixGetHomeDir(pplerr_context *context)
 {
  struct passwd *ptr;
  static char   *failover=NULL;

//  ptr = UnixGetPwEntry(context);

  //use this function instead
  ptr = getpwuid(getuid());