-
Notifications
You must be signed in to change notification settings - Fork 11
Description
I've recently introduced AppImage packaging with appimage-builder to 86Box/86Box. While the setup I came up with works perfectly on x86_64, armhf and aarch64, I run into a consistent segfault related to widechar file operations (used to load our 86box.cfg config file) on i386, reproduced on glibc 2.31 both provided by the system and the AppImage, and both Debug and Release versions of AppRun:
#
# 86Box v3.2 logfile, created 2022/02/13 16:35:56
#
# VM: 86Box
#
# Emulator path: /tmp/.mount_test.ABJfmNC/usr/local/bin/
# Userfiles path: /home/richard/86Box/
# ROM path: /home/richard/86Box/roms/
# Configuration file: /home/richard/86Box/86box.cfg
#
APPRUN_HOOK_DEBUG: fopen "/home/richard/86Box/86box.cfg"
APPRUN_HOOK_DEBUG: fopen "/home/richard/86Box/86box.cfg"
Thread 1 "86Box" received signal SIGSEGV, Segmentation fault.
0xf62d6e0a in _IO_getwline_info (fp=0x58eb9f30, buf=0xffff9d10 L"", n=1023, delim=10, extract_delim=1, eof=0x0) at iogetwline.c:58
58 iogetwline.c: No such file or directory.
(gdb) bt
#0 0xf62d6e0a in _IO_getwline_info (fp=0x58eb9f30, buf=0xffff9d10 L"", n=1023, delim=10, extract_delim=1, eof=0x0) at iogetwline.c:58
#1 0xf62d6f5a in _IO_getwline (fp=0x58eb9f30, buf=0xffff9d10 L"", n=1023, delim=10, extract_delim=1) at iogetwline.c:35
#2 0xf62d69f1 in fgetws (buf=buf@entry=0xffff9d10 L"", n=n@entry=1024, fp=fp@entry=0x58eb9f30) at iofgetws.c:53
#3 0x565f97c7 in config_read (fn=<optimized out>) at /86Box/src/config.c:331
#4 0x565ff725 in config_load () at /86Box/src/config.c:2063
#5 0x565f7eff in pc_init (argc=<optimized out>, argv=<optimized out>) at /86Box/src/86box.c:720
#6 0x569c89a4 in main (argc=<optimized out>, argv=0xffffc4f4) at /86Box/src/qt/qt_main.cpp:160
The relevant config_read function is here (line 303). Some debugging with gdb reveals that the segfault is caused by an access to fp->_wide_data, because the FILE structure returned by fopen is somehow bogus (I've had it end up in the middle of a Qt5-related string on other occasions):
(gdb) p *fp
$1 = {_flags = -72539000, _IO_read_ptr = 0x0, _IO_read_end = 0x0, _IO_read_base = 0x0, _IO_write_base = 0x0, _IO_write_ptr = 0x0, _IO_write_end = 0x0,
_IO_buf_base = 0x0, _IO_buf_end = 0x0, _IO_save_base = 0x0, _IO_backup_base = 0x0, _IO_save_end = 0x0, _markers = 0x0,
_chain = 0xf644ac80 <_IO_2_1_stderr_>, _fileno = 8, _flags2 = 128, _old_offset = -1, _cur_column = 0, _vtable_offset = -72 '\270', _shortbuf = "",
_lock = 0x58eef4e8, _offset = 4131698336, _codecvt = 0x0, _wide_data = 0x0, _freeres_list = 0x0, _freeres_buf = 0x0, __pad5 = 0, _mode = -1,
_unused2 = '\000' <repeats 39 times>}
(gdb) p *fp->_wide_data
Cannot access memory at address 0x0
(gdb) dump memory dump.bin fp fp+1
(gdb) shell xxd dump.bin
00000000: 8824 adfb 0000 0000 0000 0000 0000 0000 .$..............
00000010: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000020: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000030: 0000 0000 80ac 44f6 0800 0000 8000 0000 ......D.........
00000040: ffff ffff 0000 b800 e8f4 ee58 a0b6 44f6 ...........X..D.
00000050: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000060: 0000 0000 0000 0000 ffff ffff 0000 0000 ................
00000070: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000080: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000090: 0000 0000
If the config reading code is skipped (by 86box.cfg being absent), the config saving code (line 417) doesn't segfault, but the resulting 86box.cfg file ends up empty, because all calls to fwprintf return -1 (with no errno set) due to the bogus FILE. While debugging this issue, I recall inserting a standard non-wchar fprintf into that code, and that did work but fwprintf did not.
All this weird file behavior doesn't happen when the 86Box binary is executed without AppRun, either directly or through a manually-generated AppImage, or with AppRun on non-i386 architectures.