View Issue Details

IDProjectCategoryView StatusLast Update
0010270Dwarf FortressTechnical -- Renderingpublic2017-07-28 11:10
ReporterMuffindrake Assigned To 
PriorityhighSeveritycrashReproducibilityalways
Status newResolutionopen 
PlatformLinux x86_64OSGentoo Linux 
Product Version0.43.05 
Summary0010270: libgraphics.so dlopen()ing libncursesw.so.5 instead of .so.6 can segfault on some systems with PRINT_MODE:TEXT
DescriptionI tried to launch DF in text mode after some time and find that it crashes instantly.

After some time spent researching the problem, I see that the game and libgraphics.so are linked to libncurses(w).so.6, while libgraphics.so tries to dlopen .so.5. Both ncurses 5 and 6 are installed at the same time on this machine (slotted), as per standard gentoo repo. The crash doesn't occur if a symlink is used to trick it into thinking it found .so.5, despite it being .so.6, hence it seems that the wrong version is being opened in libgraphics.

The library also tried to dlopen libncursesw.so (which it does try if I uninstall ncurses 5 from the system), but inexplicably fails here as it doesn't seem to be a symlink here but an LD script and proclaims "Didn't find any flavor of libncursesw, attempting libncurses" and then "Unable to open any flavor of libncurses!" before exiting cleanly. Again, a symlink in /lib/ (or df/libs) with that name pointing to the right shared object resolves the problem. If that symlink points to ncurses 5 (.so.5), it crashes.

TL;DR: Add some lines in g_src/renderer_curses.cpp

Patch:

--- a/g_src/renderer_curses.cpp
+++ b/g_src/renderer_curses.cpp
@@ -294,7 +294,7 @@ extern "C" {
     if (!stub_initialized) {

       stub_initialized = true;

       // We prefer libncursesw, but we'll accept libncurses if we have to

+ handle = dlopen("libncursesw.so.6", RTLD_LAZY);

+ if (handle) goto opened;

      handle = dlopen("libncursesw.so.5", RTLD_LAZY);

       if (handle) goto opened;

       handle = dlopen("libncursesw.so", RTLD_LAZY);

       if (handle) goto opened;

@@ -302,7 +302,7 @@ extern "C" {
       sleep(5);

       handle = dlopen("libncurses.dylib", RTLD_LAZY);

       if (handle) goto opened;

+ handle = dlopen("libncurses.so.6", RTLD_LAZY);

+ if (handle) goto opened;

       handle = dlopen("libncurses.so.5", RTLD_LAZY);

       if (handle) goto opened;

       handle = dlopen("libncurses.so", RTLD_LAZY);

       if (handle) goto opened;

Steps To ReproduceHave libncurses-5 installed
Launch DF in PRINT_MODE:TEXT, perhaps put a symlink in df/libs named libncursesw.so.6 pointing to the installed (/usr)/lib/libncurses.so.5
Additional InformationCore was generated by `./libs/Dwarf_Fortress'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0 0x00007f674e864d07 in init_pair () from /usr/lib64/libncursesw.so.5
[...]
(gdb) where
#0 0x00007f674e864d07 in init_pair () from /usr/lib64/libncursesw.so.5
0000001 0x00007f676452dfda in init_curses () from /opt/dwarf-fortress/libs/libgraphics.so
0000002 0x00007f6764533fed in enablerst::loop(std::string) () from /opt/dwarf-fortress/libs/libgraphics.so
0000003 0x00007f67645281c4 in main () from /opt/dwarf-fortress/libs/libgraphics.so
0000004 0x00007f676390311a in __libc_start_main () from /lib64/libc.so.6
0000005 0x0000000000408f1f in ?? ()
TagsNo tags attached.

Activities

lethosor

2017-07-28 11:09

manager   ~0036677

As I pointed out on IRC, libgraphics is supposed to use ncurses 5. That part hasn't changed significantly in ages (since around 2010). I'm not sure why it's claiming to link to ncurses 6, but I imagine that's part of the build process. All of the ncurses interface is set up with dlopen()/dlsym(), not dynamic linking.

Since some systems are distributing ncurses 6, but some still have ncurses 5, a better patch would check for ncurses 6 without dropping support for ncurses 5. I updated the patch above to do that.

Add Note

Note

Issue History

Date Modified Username Field Change
2017-07-25 16:25 Muffindrake New Issue
2017-07-28 11:04 lethosor Description Updated
2017-07-28 11:04 lethosor Description Updated
2017-07-28 11:06 lethosor Description Updated
2017-07-28 11:06 lethosor Description Updated
2017-07-28 11:09 lethosor Note Added: 0036677
2017-07-28 11:10 lethosor Summary libgraphics.so incorrectly dlopens libncursesw.so.5, even though it needs .so.6, resulting in a segfault with PRINT_MODE:TEXT => libgraphics.so dlopen()ing libncursesw.so.5 can segfault on some systems with PRINT_MODE:TEXT
2017-07-28 11:10 lethosor Summary libgraphics.so dlopen()ing libncursesw.so.5 can segfault on some systems with PRINT_MODE:TEXT => libgraphics.so dlopen()ing libncursesw.so.5 instead of .so.6 can segfault on some systems with PRINT_MODE:TEXT