Skip to content

Commit f9a3408

Browse files
committed
Add a test for CString drop
1 parent 04b776e commit f9a3408

File tree

1 file changed

+49
-0
lines changed

1 file changed

+49
-0
lines changed

src/test/run-pass/cstring-drop.rs

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
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+
}

0 commit comments

Comments
 (0)