Skip to content

Certain Unicode chars can trigger ASan stack-buffer-overflow or panic in char_to_key_code #55

Description

@cicilzx

Hi! I'm currently developing a fuzzer to test safe abstractions in Rust crates. I noticed two edge cases on Linux/X11 that related to how char_to_key_code(character: char) -> XKeyCode converts a Rust char to the C string passed into XStringToKeysym.

Environment

  • OS: Linux x86_64 (Ubuntu)
  • Rust toolchain: nightly-2024-12-15
  • Sanitizer: AddressSanitizer
  • autopilot version: 0.4.1

Case 1:

#[test]
fn test1() {
    let s = "Hello, world! \u{04E2} DONE";
    crate::key::type_string(s, &[], 200.0, 0.0);
    let _ = crate::alert::alert(s, None, None, None);
}

Run:

ASAN_OPTIONS="detect_leaks=0" RUSTFLAGS="-Zsanitizer=address" cargo test test1 --lib --target x86_64-unknown-linux-gnu -Zbuild-std=std

When the input contains \u{04E2}, AddressSanitizer reports a stack-buffer-overflow (out-of-bounds read).

ASan output (trimmed):

ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7d7efef16b62 at pc 0x63a1e9620713 bp 0x7d7effbfce60 sp 0x7d7effbfc628
READ of size 3 at 0x7d7efef16b62 thread T1

Case 2:

extern crate autopilot;

fn main() {
    let s = "Hello, world! \u{F2B2C} DONE";
    autopilot::key::type_string(s, &[], 200.0, 0.0);
    let _ = autopilot::alert::alert(s, None, None, None);
}

Run:

cargo run

When the input contains a character like \u{F2B2C}, it panics with:

thread 'main' panicked at .../core/src/char/methods.rs:1814:13:
encode_utf8: need 4 bytes to encode U+F2B2C but buffer has just 2

Potential Relevant code

#[cfg(target_os = "linux")]
fn char_to_key_code(character: char) -> XKeyCode {
    match character {
        // ... many ASCII mappings ...
        _ => unsafe {
            let mut buf = [0; 2];
            x11::xlib::XStringToKeysym(
                character.encode_utf8(&mut buf).as_ptr() as *const libc::c_char
            ) as XKeyCode
        },
    }
}

The code uses a fixed [u8; 2] buffer and passes character.encode_utf8(&mut buf) directly to XStringToKeysym. This can panic for characters that require 3–4 UTF-8 bytes, and even for 2-byte UTF-8 characters the produced bytes are not NUL-terminated, so XStringToKeysym (which expects a C string) may read past the stack buffer and trigger an ASan out-of-bounds read. A small robustness improvement could be to use a buffer large enough for any UTF-8 char plus \0 and explicitly NUL-terminate it (or use CString/CStr) before calling XStringToKeysym.

Thanks for taking a look!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions