Possible SEGV (null pointer deref) with libxi API issue
Description
The XIQueryDevice()
function can return NULL
if an error condition occurs. However:
- The
gdk_x11_device_manager_xi2_constructed()
function (fromgdkdevicemanager-xi2.c
) does not do anyNULL
check on the returned value before passing it toXIFreeDeviceInfo()
. - The argument to
XIFreeDeviceInfo()
must be non-NULL
(seelibxi
source code) or else it will crash (null pointer deref). This seems to be an API misuse error.
Relevant code snippet:
static void
gdk_x11_device_manager_xi2_constructed (GObject *object)
{
...
info = XIQueryDevice (xdisplay, XIAllDevices, &ndevices); /* info can be NULL */
... /* No NULL check */
XIFreeDeviceInfo (info); /* SEGV if info==NULL */
...
}
Relevant code location:
Steps to reproduce
This is somewhat difficult to reproduce, since it involves coaxing XIQueryDevice()
to fail with NULL
. Nevertheless, the bug is evident from inspecting the source code.
Version information
Checked on Ubuntu 23.04 (shipped libs) and the latest git head.
Backtrace
Thread 1 "gnome-mines" received signal SIGSEGV, Segmentation fault.
0x00007ffde827275d in XIFreeDeviceInfo (info=info@entry=0x0) at ../../src/XIQueryDevice.c:153
#0 0x00007ffde827275d in XIFreeDeviceInfo (info=info@entry=0x0) at ../../src/XIQueryDevice.c:153
#1 0x00007ffde8b8787a in gdk_x11_device_manager_xi2_constructed (object=0x5555555d29f0)
at ../../../gdk/x11/gdkdevicemanager-xi2.c:747
#2 0x00007ffff7e2a2e6 in g_object_new_internal
(class=class@entry=0x5555555d2660, params=params@entry=0x7fffffffd4a0, n_params=n_params@entry=4)
at ../../../gobject/gobject.c:2297
#3 0x00007ffff7e2bee3 in g_object_new_valist
(object_type=<optimized out>, first_property_name=first_property_name@entry=0x7ffde8bad6b2 "display", var_args=var_args@entry=0x7fffffffd770) at ../../../gobject/gobject.c:2585
#4 0x00007ffff7e2c53d in g_object_new
(object_type=<optimized out>, first_property_name=first_property_name@entry=0x7ffde8bad6b2 "display")
at ../../../gobject/gobject.c:2058
#5 0x00007ffde8b8f684 in _gdk_x11_device_manager_new (display=0x5555555bacb0)
at ../../../gdk/x11/gdkdevicemanager-x11.c:61
#6 _gdk_x11_display_open (display_name=<optimized out>) at ../../../gdk/x11/gdkdisplay-x11.c:1613
#7 0x00007ffde8b3c9a7 in gdk_display_manager_open_display (manager=<optimized out>, name=0x0)
at ../../../gdk/gdkdisplaymanager.c:462
#8 0x00007ffde8df4728 in gtk_init_check (argc=<optimized out>, argv=<optimized out>)
at ../../../gtk/gtkmain.c:1110
#9 gtk_init_check (argc=<optimized out>, argv=<optimized out>) at ../../../gtk/gtkmain.c:1102
#10 0x00007ffde8df5d2d in gtk_init (argc=<optimized out>, argv=<optimized out>)
at ../../../gtk/gtkmain.c:1167
#11 0x00007ffde8cbaeec in gtk_application_startup (g_application=0x55555558ba10)
at ../../../gtk/gtkapplication.c:304
#12 0x000055555556062c in mines_real_startup (base=0x55555558ba10) at src/gnome-mines.p/gnome-mines.c:1096
#13 0x00007ffff7e3783c in _g_closure_invoke_va
(param_types=<optimized out>, n_params=<optimized out>, args=0x7fffffffdc50, instance=<optimized out>, return_value=<optimized out>, closure=0x555555588320) at ../../../gobject/gclosure.c:895
#14 g_signal_emit_valist
(instance=<optimized out>, signal_id=<optimized out>, detail=<optimized out>, var_args=var_args@entry=0x7fffffffdc50) at ../../../gobject/gsignal.c:3462
#15 0x00007ffff7e37923 in g_signal_emit
(instance=instance@entry=0x55555558ba10, signal_id=<optimized out>, detail=detail@entry=0)
at ../../../gobject/gsignal.c:3612
#16 0x00007ffde8a100a6 in g_application_register
(application=application@entry=0x55555558ba10, cancellable=cancellable@entry=0x0, error=error@entry=0x7fffffffddc0) at ../../../gio/gapplication.c:2213
#17 0x00007ffde8a107fe in g_application_real_local_command_line
(application=0x55555558ba10, arguments=0x7fffffffde18, exit_status=0x7fffffffde14)
at ../../../gio/gapplication.c:1115
#18 0x00007ffde8a10bc8 in g_application_run
(application=application@entry=0x55555558ba10, argc=argc@entry=1, argv=argv@entry=0x7fffffffdf88)
at ../../../gio/gapplication.c:2542
#19 0x000055555555ae67 in mines_main (args_length1=1, args=0x7fffffffdf88)
at src/gnome-mines.p/gnome-mines.c:3216
#20 main (argc=1, argv=0x7fffffffdf88) at src/gnome-mines.p/gnome-mines.c:3225