Fix problem of os_fatal() trying to write to SDL window when SDL not active.
authorDavid Griffith <dave@661.org>
Mon, 24 Jun 2019 00:11:45 +0000 (17:11 -0700)
committerDavid Griffith <dave@661.org>
Mon, 24 Jun 2019 00:11:45 +0000 (17:11 -0700)
If we have a showstopping problem right from the start, like trying to
load a file that's not a Zcode file or Blorb file that lacks a Zcode
chunk, then Frotz will call os_fatal() to complain about it and then
exit.  But sfrotz's version of os_fatal doesn't check if SDL is active
or not before calling functions that depend on SDL.  The first of these
is os_set_text_style().  This leads to a segfault when a call of
current.font->getglyph(current.font,c,1); dereferences getglyph, which
does not exist because current is not properly initialized yet.

src/sdl/sf_frotz.h
src/sdl/sf_resource.c
src/sdl/sf_video.c

index 7fbf312155f91913b831c920f5789da53dcd1cb1..22e6aaa7bc7e1dd3017c8b828c2d539f6b612d1d 100644 (file)
@@ -93,6 +93,8 @@ extern int m_frequency;
 
 extern double  m_gamma;
 
+extern bool sdl_active;
+
 // sf_resource.c
 
 // must be called as soon as possible (i.e. by os_process_arguments())
index 386cf31c224dbecddcba525b37d7cc1f0d0be4f3..f3a91f50b3b59f0f2fd3a846843b917444aa96b1 100644 (file)
@@ -50,6 +50,8 @@ char *        m_reslist_file = NULL;
 char * m_setupfile = ".sfrotzrc";
 extern int m_frequency;
 
+bool sdl_active;
+
 static int countedpics = 0;
 static int maxlegalpic = 0;
 static int releaseno = 0;
@@ -780,37 +782,41 @@ void os_fatal(const char *s, ...)
 //     if (theWnd != NULL)
 //             theWnd->FlushDisplay();
 
-  os_set_text_style(0);
-
-
-  os_display_string((zchar *)"\n\n");
-  os_beep(BEEP_HIGH);
-  os_set_text_style(BOLDFACE_STYLE);
-
   fprintf(stderr,"\n%s: ",sf_msgstring(IDS_FATAL));
   va_start( m, s);
   vfprintf( stderr, s, m);
   va_end(m);
   fprintf(stderr,"\n");
 
-  os_display_string((zchar *)"Fatal error: ");
-  os_set_text_style(0);
-  os_display_string((zchar *)s);
-  os_display_string((zchar *)"\n\n");
-  new_line();
-  flush_buffer();
+  if (sdl_active) {
+    os_set_text_style(0);
+    os_display_string((zchar *)"\n\n");
+    os_beep(BEEP_HIGH);
+    os_set_text_style(BOLDFACE_STYLE);
 
-  if (f_setup.ignore_errors) {
-    os_display_string((zchar *)"Continuing anyway...");
-    new_line();
+    os_display_string((zchar *)"Fatal error: ");
+    os_set_text_style(0);
+    os_display_string((zchar *)s);
+    os_display_string((zchar *)"\n\n");
     new_line();
+    flush_buffer();
+  }
+
+  if (f_setup.ignore_errors) {
+    if (sdl_active) {
+      os_display_string((zchar *)"Continuing anyway...");
+      new_line();
+      new_line();
+    }
     fprintf(stderr, "Continuing anyway...\n");
     return;
   }
 
-  os_reset_screen();
+  if (sdl_active) {
+    os_reset_screen();
+    SDL_Quit();
+  }
   sf_cleanup_all();
-  SDL_Quit();
   exit(EXIT_FAILURE);
 
 //     ::MessageBox(AfxGetMainWnd()->GetSafeHwnd(),s,CResString(IDS_FATAL),MB_ICONERROR|MB_OK);
@@ -1068,4 +1074,6 @@ void os_init_setup(void)
     f_setup.sound = 1;
     f_setup.err_report_mode = ERR_DEFAULT_REPORT_MODE;
     f_setup.restore_mode = 0;
+
+    sdl_active = FALSE;
 }
index d10782aaf11fcb889004ef79e8d77932368f5cd1..6dbceb62a4e9c265de1648e5b5370952882f175a 100644 (file)
@@ -22,6 +22,8 @@ static SDL_Renderer *renderer = NULL;
 static SDL_Texture *texture = NULL;
 int m_timerinterval = 100;
 
+bool sdl_active;
+
 static void sf_quitconf();
 
 // clipping region
@@ -433,6 +435,9 @@ void sf_initvideo( int W, int H, int full)
     if ( SDL_Init(initflags) < 0 ) {
         os_fatal("Couldn't initialize SDL: %s", SDL_GetError());
     }
+
+    sdl_active = TRUE;
+
     /* We don't handle text edit events.  Not that I know why anyone would
        want to use such an IME with Frotz. */
     SDL_SetHint(SDL_HINT_IME_INTERNAL_EDITING, "1");