gtk-rs / gtk-rs-core

Rust bindings for GNOME libraries
https://gtk-rs.org/gtk-rs-core
MIT License
272 stars 105 forks source link

[BUG] `ArgumentList::remove` causes segmentation fault #1330

Closed vhakulinen closed 4 months ago

vhakulinen commented 4 months ago

Bug description

Calling ArgumentList::remove with anything other that 0 causes segmentation fault.

Additionally, calling ArgumentList::remove with 0 causes segmentation fault after returning from local_command_line.

use gtk::gio;
use gtk::glib;
use gtk::prelude::*;

glib::wrapper! {
    pub struct App(ObjectSubclass<imp::App>)
        @extends gio::Application, gtk::Application;
}

impl App {
    pub fn new() -> Self {
        glib::Object::builder()
            .property("application-id", "com.github.vhakulinen.gtk-app-bug")
            .build()
    }
}

mod imp {
    use gtk::glib;

    use gtk::{prelude::*, subclass::prelude::*};

    #[derive(Default)]
    pub struct App {}

    #[glib::object_subclass]
    impl ObjectSubclass for App {
        const NAME: &'static str = "App";
        type Type = super::App;
        type ParentType = gtk::Application;
    }

    impl ObjectImpl for App {}

    impl ApplicationImpl for App {
        fn local_command_line(
            &self,
            arguments: &mut gtk::gio::subclass::ArgumentList,
        ) -> Option<glib::ExitCode> {
            dbg!("REMOVE");
            dbg!(arguments.len());
            arguments.remove(1);  // <---------- crash here
            dbg!("REMOVED");

            None
        }
    }

    impl GtkApplicationImpl for App {}
}

fn main() -> glib::ExitCode {
    let app = App::new();
    app.run()
}

Backtrace

ville@pop-os:~/src/gtk-app-bug$ RUST_BACKTRACE=full cargo run -- foo bar
warning: unused import: `prelude`
  --> src/main.rs:21:15
   |
21 |     use gtk::{prelude::*, subclass::prelude::*};
   |               ^^^^^^^
   |
   = note: `#[warn(unused_imports)]` on by default

warning: `gtk-app-bug` (bin "gtk-app-bug") generated 1 warning
    Finished dev [unoptimized + debuginfo] target(s) in 0.04s
     Running `target/debug/gtk-app-bug foo bar`
[src/main.rs:40] "REMOVE" = "REMOVE"
[src/main.rs:41] arguments.len() = 3
free(): invalid pointer
Aborted (core dumped)

gdb backtrace:

ville@pop-os:~/src/gtk-app-bug$ gdb target/debug/gtk-app-bug 
<snip>
(gdb) r foo bar
Starting program: /home/ville/src/gtk-app-bug/target/debug/gtk-app-bug foo bar
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[src/main.rs:40] "REMOVE" = "REMOVE"
[src/main.rs:41] arguments.len() = 3
free(): invalid pointer

Program received signal SIGABRT, Aborted.
__pthread_kill_implementation (no_tid=0, signo=6, threadid=140737323567680) at ./nptl/pthread_kill.c:44
44      ./nptl/pthread_kill.c: No such file or directory.
(gdb) bt
#0  __pthread_kill_implementation (no_tid=0, signo=6, threadid=140737323567680) at ./nptl/pthread_kill.c:44
#1  __pthread_kill_internal (signo=6, threadid=140737323567680) at ./nptl/pthread_kill.c:78
#2  __GI___pthread_kill (threadid=140737323567680, signo=signo@entry=6) at ./nptl/pthread_kill.c:89
#3  0x00007ffff6e42476 in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26
#4  0x00007ffff6e287f3 in __GI_abort () at ./stdlib/abort.c:79
#5  0x00007ffff6e89676 in __libc_message (action=action@entry=do_abort, fmt=fmt@entry=0x7ffff6fdbb77 "%s\n")
    at ../sysdeps/posix/libc_fatal.c:155
#6  0x00007ffff6ea0cfc in malloc_printerr (str=str@entry=0x7ffff6fd9744 "free(): invalid pointer") at ./malloc/malloc.c:5664
#7  0x00007ffff6ea2a44 in _int_free (av=<optimized out>, p=<optimized out>, have_lock=0) at ./malloc/malloc.c:4439
#8  0x00007ffff6ea5453 in __GI___libc_free (mem=<optimized out>) at ./malloc/malloc.c:3391
#9  0x000055555556e1b1 in gio::subclass::application::ArgumentList::remove (self=0x7fffffffd9d0, idx=1) at src/subclass/application.rs:36
#10 0x0000555555568452 in gtk_app_bug::imp::{impl#1}::local_command_line (self=0x555555613020, arguments=0x7fffffffd9d0) at src/main.rs:42
#11 0x0000555555565451 in gio::subclass::application::application_local_command_line<gtk_app_bug::imp::App>
    (ptr=0x555555613100, arguments=0x7fffffffda48, exit_status=0x7fffffffda44)
    at /home/ville/.cargo/registry/src/index.crates.io-6f17d22bba15001f/gio-0.19.2/src/subclass/application.rs:338
#12 0x00007ffff73dff46 in g_application_run () at /lib/x86_64-linux-gnu/libgio-2.0.so.0
#13 0x000055555556780e in gio::application::ApplicationExtManual::run_with_args<gtk_app_bug::App, alloc::string::String>
    (self=0x7fffffffdc20, args=...) at /home/ville/.cargo/registry/src/index.crates.io-6f17d22bba15001f/gio-0.19.2/src/application.rs:29
#14 0x0000555555567929 in gio::application::ApplicationExtManual::run<gtk_app_bug::App> (self=0x7fffffffdc20)
    at /home/ville/.cargo/registry/src/index.crates.io-6f17d22bba15001f/gio-0.19.2/src/application.rs:22
#15 0x0000555555566958 in gtk_app_bug::main () at src/main.rs:54
vhakulinen commented 4 months ago

There seems to be a test case for this here: https://github.com/gtk-rs/gtk-rs-core/blob/55f5117feb720248c75e02169cff35d31be806c6/gio/src/subclass/application.rs#L431-L449

Tho' that has a bug: the arguments passed to it are just --local, while they should be --local-arg so something like that.

vhakulinen commented 4 months ago

This patch might fix the issue:

diff --git a/gio/src/subclass/application.rs b/gio/src/subclass/application.rs
index e6005847bd..3e8f4c9655 100644
--- a/gio/src/subclass/application.rs
+++ b/gio/src/subclass/application.rs
@@ -33,7 +33,7 @@ impl ArgumentList {

             self.items.remove(idx);

-            glib::ffi::g_free((*self.ptr).add(idx) as *mut c_void);
+            glib::ffi::g_free(*(*self.ptr).add(idx) as *mut c_void);

             for i in idx..n_args - 1 {
                 ptr::write((*self.ptr).add(i), *(*self.ptr).add(i + 1))
@@ -464,6 +464,6 @@ mod tests {

         app.set_inactivity_timeout(10000);

-        assert_eq!(app.run_with_args(&["--local"]), EXIT_STATUS.into());
+        assert_eq!(app.run_with_args(&["--local-"]), EXIT_STATUS.into());
     }
 }