]> git.lizzy.rs Git - rust.git/blob - src/test/run-pass/cstring-drop.rs
Add a test for CString drop
[rust.git] / src / test / run-pass / cstring-drop.rs
1 // Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 // ignore-emscripten
12
13 // Test that `CString::new("hello").unwrap().as_ptr()` pattern
14 // leads to failure.
15
16 use std::env;
17 use std::ffi::{CString, CStr};
18 use std::os::raw::c_char;
19 use std::process::{Command, Stdio};
20
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 }
37
38 fn is_hello(s: *const c_char) -> bool {
39     // `s` is a dangling pointer and reading it is technically
40     // undefined behavior. But we want to prevent the most diabolical
41     // 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()
49 }