x11-rs icon indicating copy to clipboard operation
x11-rs copied to clipboard

Debug implementation for XEvent is unsound

Open WaffleLapkin opened this issue 3 years ago • 0 comments

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

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::<impl std::fmt::Display for u64>::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::<impl std::fmt::Debug for u64>::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 `<x11::xlib::XButtonEvent as std::fmt::Debug>::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 `<x11::xlib::XEvent as std::fmt::Debug>::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 `<std::io::StdoutLock 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/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 `<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:636:9
    = note: inside `std::io::stdio::print_to::<std::io::Stdout>` 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 `<fn() as std::ops::FnOnce<()>>::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::<fn(), ()>` 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::<impl std::ops::FnOnce<()> 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, &dyn std::ops::Fn() -> 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

WaffleLapkin avatar Mar 11 '21 08:03 WaffleLapkin