gtk-rs / gtk4-rs

Rust bindings of GTK 4
https://gtk-rs.org/gtk4-rs/
MIT License
1.74k stars 168 forks source link

[BUG] TextIter is unsound #1280

Open jf2048 opened 1 year ago

jf2048 commented 1 year ago

Bug description

This struct holds a borrowed reference to a TextBuffer and needs a lifetime parameter to be safe. Background here: https://discourse.gnome.org/t/can-bindings-for-textiter-be-memory-safe/13660

Test case:

use gtk::prelude::*;

fn main() {
    gtk::init().unwrap();
    let (start, end) = {
        let buf = gtk::TextBuffer::new(None);
        let mut s = String::new();
        for _ in 0..100 {
            s.push_str("hello world ");
        }
        buf.insert(&mut buf.start_iter(), &s);
        let (start, end) = (buf.start_iter(), buf.end_iter());
        println!("{}", start.text(&end));
        (start, end)
    };
    println!("{}", start.text(&end));
}

See also https://github.com/gtk-rs/gtk-rs-core/issues/610

Backtrace

First println! works, but the second one causes a segfault:

hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world

Thread 1 "gtk4rstest" received signal SIGSEGV, Segmentation fault.
#0  _gtk_text_line_char_to_byte_offsets (seg_byte_offset=0x7fffffffd2f8, line_byte_offset=0x7fffffffd2d0, char_offset=0, line=0x7fffd800b790) at ../gtk/gtktextbtree.c:4200
#1  ensure_byte_offsets (iter=0x7fffffffd2c0) at ../gtk/gtktextiter.c:358
#2  ensure_byte_offsets (iter=0x7fffffffd2c0) at ../gtk/gtktextiter.c:352
#3  _gtk_text_iter_get_segment_byte (iter=<optimized out>) at ../gtk/gtktextiter.c:529
#4  0x00007ffff78d5342 in copy_segment (string=string@entry=0x55555566fba0, include_hidden=include_hidden@entry=1, include_nonchars=include_nonchars@entry=0, start=start@entry=0x7fffffffd2c0, end=end@entry=0x7fffffffd220)
    at ../gtk/gtktextbtree.c:2339
#5  0x00007ffff78d55a3 in copy_segment (end=0x7fffffffd220, start=0x7fffffffd2c0, include_nonchars=0, include_hidden=1, string=0x55555566fba0) at ../gtk/gtktextbtree.c:2318
#6  _gtk_text_btree_get_text (start_orig=<optimized out>, end_orig=<optimized out>, include_hidden=1, include_nonchars=0) at ../gtk/gtktextbtree.c:2440
#7  0x00005555555af703 in gtk4::auto::text_iter::TextIter::text (self=0x7fffffffd430, end=0x7fffffffd480) at src/auto/text_iter.rs:631
#8  0x00005555555ae24e in gtktest::main () at src/main.rs:16
bilelmoussaoui commented 1 year ago

I suppose we can't use a lifetime param with glib::wrapper neither right?

sdroege commented 1 year ago

You actually can :)

jf2048 commented 1 year ago

How? The lifetime params would need to match on $x:lifetime instead of $x:ident

sdroege commented 1 year ago

Hmm, I think then only generics work but lifetimes not.