rust/tests/ui/std/issue-81357-unsound-file-me...

82 lines
2.3 KiB
Rust

//@ run-fail
//@ only-windows
fn main() {
use std::fs;
use std::io::prelude::*;
use std::os::windows::prelude::*;
use std::ptr;
use std::sync::Arc;
use std::thread;
use std::time::Duration;
const FILE_FLAG_OVERLAPPED: u32 = 0x40000000;
fn create_pipe_server(path: &str) -> fs::File {
let mut path0 = path.as_bytes().to_owned();
path0.push(0);
extern "system" {
fn CreateNamedPipeA(
lpName: *const u8,
dwOpenMode: u32,
dwPipeMode: u32,
nMaxInstances: u32,
nOutBufferSize: u32,
nInBufferSize: u32,
nDefaultTimeOut: u32,
lpSecurityAttributes: *mut u8,
) -> RawHandle;
}
unsafe {
let h = CreateNamedPipeA(path0.as_ptr(), 3, 0, 1, 0, 0, 0, ptr::null_mut());
assert_ne!(h as isize, -1);
fs::File::from_raw_handle(h)
}
}
let path = "\\\\.\\pipe\\repro";
let mut server = create_pipe_server(path);
let client = Arc::new(
fs::OpenOptions::new().custom_flags(FILE_FLAG_OVERLAPPED).read(true).open(path).unwrap(),
);
let spawn_read = |is_first: bool| {
thread::spawn({
let f = client.clone();
move || {
let mut buf = [0xcc; 1];
let mut f = f.as_ref();
f.read(&mut buf).unwrap();
if is_first {
assert_ne!(buf[0], 0xcc);
} else {
let b = buf[0]; // capture buf[0]
thread::sleep(Duration::from_millis(200));
// Check the buffer hasn't been written to after read.
dbg!(buf[0], b);
assert_eq!(buf[0], b);
}
}
})
};
let t1 = spawn_read(true);
thread::sleep(Duration::from_millis(20));
let t2 = spawn_read(false);
thread::sleep(Duration::from_millis(100));
let _ = server.write(b"x");
thread::sleep(Duration::from_millis(100));
let _ = server.write(b"y");
// This is run fail because we need to test for the `abort`.
// That failing to run is the success case.
if t1.join().is_err() || t2.join().is_err() {
return;
} else {
panic!("success");
}
}