AltF02 / x11-rs

Rust bindings for X11 libraries
https://docs.rs/x11
MIT License
207 stars 66 forks source link

Debug implementation for XEvent is unsound #123

Open WaffleLapkin opened 3 years ago

WaffleLapkin commented 3 years ago

The Debug implementation for XEvent assumes that .type_ is set right, but it is public and can be set to any value in safe code.

https://github.com/erlepereira/x11-rs/blob/c4dcb13ae894c761722769088829d5cd7db3fb71/src/xlib.rs#L1042-L1049

This allows, for example, to read uninitialized memory in safe code:

// x11 = "2.18"

fn main() {
    let wrong = x11::xlib::XCirculateEvent { 
        // Wrong tag
        type_: x11::xlib::ButtonPress,
        // All other fields don't matter
        serial: 0,
        send_event: 0,
        display: core::ptr::null_mut(),
        event: 0,
        window: 0,
        place: 0,
    };

    // button event have more fields, so this reads uninitialized memory
    println!("{:?}", x11::xlib::XEvent { circulate: wrong });
}

Example outputs:

XEvent { button: XButtonEvent { type_: 4, serial: 0, send_event: 0, display: 0x0, window: 0, root: 0, subwindow: 0, time: 140436485040640, x: 32, y: 0, x_root: -150365344, y_root: 22003, state: 3937517568, button: 32697, same_screen: -357449728 } }
XEvent { button: XButtonEvent { type_: 4, serial: 0, send_event: 0, display: 0x0, window: 0, root: 0, subwindow: 0, time: 139885648939520, x: 32, y: 0, x_root: -714048672, y_root: 22090, state: 2857230336, button: 32569, same_screen: -1437736960 } }

miri output:

spoiler

```text error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory --> /home/waffle/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/fmt/num.rs:462:5 | 462 | / impl_Display!( 463 | | i8, u8, i16, u16, i32, u32, i64, u64, usize, isize 464 | | as u64 via to_u64 named fmt_u64 465 | | ); | |______^ using uninitialized data, but this operation requires initialized memory | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = note: inside `core::fmt::num::imp::::fmt` at /home/waffle/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/fmt/num.rs:280:38 = note: inside `core::fmt::num::::fmt` at /home/waffle/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/fmt/num.rs:191:21 = note: inside `<&u64 as std::fmt::Debug>::fmt` at /home/waffle/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/fmt/mod.rs:2010:62 = note: inside closure at /home/waffle/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/fmt/builders.rs:154:17 = note: inside `std::result::Result::<(), std::fmt::Error>::and_then::<(), [closure@std::fmt::DebugStruct::field::{closure#0}]>` at /home/waffle/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/result.rs:704:22 = note: inside `std::fmt::DebugStruct::field` at /home/waffle/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/fmt/builders.rs:137:23 = note: inside `::fmt` at /home/waffle/.cargo/registry/src/github.com-1ecc6299db9ec823/x11-2.18.2/src/xlib.rs:1181:10 = note: inside closure at /home/waffle/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/fmt/builders.rs:154:17 = note: inside `std::result::Result::<(), std::fmt::Error>::and_then::<(), [closure@std::fmt::DebugStruct::field::{closure#0}]>` at /home/waffle/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/result.rs:704:22 = note: inside `std::fmt::DebugStruct::field` at /home/waffle/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/fmt/builders.rs:137:23 = note: inside `::fmt` at /home/waffle/.cargo/registry/src/github.com-1ecc6299db9ec823/x11-2.18.2/src/xlib.rs:1049:24 = note: inside `std::fmt::write` at /home/waffle/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/fmt/mod.rs:1092:17 = note: inside `::write_fmt` at /home/waffle/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/io/mod.rs:1567:15 = note: inside `<&std::io::Stdout as std::io::Write>::write_fmt` at /home/waffle/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/io/stdio.rs:662:9 = note: inside `::write_fmt` at /home/waffle/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/io/stdio.rs:636:9 = note: inside `std::io::stdio::print_to::` at /home/waffle/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/io/stdio.rs:939:21 = note: inside `std::io::_print` at /home/waffle/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/io/stdio.rs:952:5 note: inside `main` at /home/waffle/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/macros.rs:97:9 --> src/main.rs:14:5 | 14 | println!("{:?}", x11::xlib::XEvent { circulate: wrong }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: inside `>::call_once - shim(fn())` at /home/waffle/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ops/function.rs:227:5 = note: inside `std::sys_common::backtrace::__rust_begin_short_backtrace::` at /home/waffle/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys_common/backtrace.rs:125:18 = note: inside closure at /home/waffle/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/rt.rs:66:18 = note: inside `std::ops::function::impls:: for &dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe>::call_once` at /home/waffle/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ops/function.rs:259:13 = note: inside `std::panicking::r#try::do_call::<&dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe, i32>` at /home/waffle/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/panicking.rs:379:40 = note: inside `std::panicking::r#try:: i32 + std::marker::Sync + std::panic::RefUnwindSafe>` at /home/waffle/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/panicking.rs:343:19 = note: inside `std::panic::catch_unwind::<&dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe, i32>` at /home/waffle/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/panic.rs:431:14 = note: inside `std::rt::lang_start_internal` at /home/waffle/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/rt.rs:51:25 = note: inside `std::rt::lang_start::<()>` at /home/waffle/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/rt.rs:65:5 = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error ```