|
8 | 8 | // option. This file may not be copied, modified, or distributed
|
9 | 9 | // except according to those terms.
|
10 | 10 |
|
11 |
| -// ignore-emscripten |
| 11 | +// no-prefer-dynamic |
| 12 | +// aux-build:allocator-leaking.rs |
12 | 13 |
|
13 | 14 | // Test that `CString::new("hello").unwrap().as_ptr()` pattern
|
14 | 15 | // leads to failure.
|
15 | 16 |
|
16 |
| -use std::env; |
17 |
| -use std::ffi::{CString, CStr}; |
18 |
| -use std::os::raw::c_char; |
19 |
| -use std::process::{Command, Stdio}; |
| 17 | +extern crate allocator_leaking; |
20 | 18 |
|
21 |
| -fn main() { |
22 |
| - let args: Vec<String> = env::args().collect(); |
23 |
| - if args.len() > 1 && args[1] == "child" { |
24 |
| - // Repeat several times to be more confident that |
25 |
| - // it is `Drop` for `CString` that does the cleanup, |
26 |
| - // and not just some lucky UB. |
27 |
| - let xs = vec![CString::new("Hello").unwrap(); 10]; |
28 |
| - let ys = xs.iter().map(|s| s.as_ptr()).collect::<Vec<_>>(); |
29 |
| - drop(xs); |
30 |
| - assert!(ys.into_iter().any(is_hello)); |
31 |
| - return; |
32 |
| - } |
33 |
| - |
34 |
| - let output = Command::new(&args[0]).arg("child").output().unwrap(); |
35 |
| - assert!(!output.status.success()); |
36 |
| -} |
| 19 | +use std::ffi::CString; |
| 20 | +use std::ptr; |
37 | 21 |
|
38 |
| -fn is_hello(s: *const c_char) -> bool { |
39 |
| - // `s` is a dangling pointer and reading it is technically |
| 22 | +fn main() { |
| 23 | + let ptr = CString::new("Hello").unwrap().as_ptr(); |
| 24 | + // `ptr` is a dangling pointer and reading it is almost always |
40 | 25 | // undefined behavior. But we want to prevent the most diabolical
|
41 | 26 | // kind of UB (apart from nasal demons): reading a value that was
|
42 |
| - // previously written. |
43 |
| - // |
44 |
| - // Segfaulting or reading an empty string is Ok, |
45 |
| - // reading "Hello" is bad. |
46 |
| - let s = unsafe { CStr::from_ptr(s) }; |
47 |
| - let hello = CString::new("Hello").unwrap(); |
48 |
| - s == hello.as_ref() |
| 27 | + // previously written. So we make sure that CString zeros the |
| 28 | + // first byte in the `Drop`. |
| 29 | + // To make the test itself UB-free we use a custom allocator |
| 30 | + // which always leaks memory. |
| 31 | + assert_eq!(unsafe { ptr::read(ptr as *const [u8; 6]) } , *b"\0ello\0"); |
49 | 32 | }
|
0 commit comments