From f9a340804c998f25691be182fc8bc40b8fc9a496 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 7 Sep 2016 10:13:49 +0300 Subject: [PATCH] Add a test for CString drop --- src/test/run-pass/cstring-drop.rs | 49 +++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 src/test/run-pass/cstring-drop.rs diff --git a/src/test/run-pass/cstring-drop.rs b/src/test/run-pass/cstring-drop.rs new file mode 100644 index 00000000000..960391bb8de --- /dev/null +++ b/src/test/run-pass/cstring-drop.rs @@ -0,0 +1,49 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-emscripten + +// Test that `CString::new("hello").unwrap().as_ptr()` pattern +// leads to failure. + +use std::env; +use std::ffi::{CString, CStr}; +use std::os::raw::c_char; +use std::process::{Command, Stdio}; + +fn main() { + let args: Vec = env::args().collect(); + if args.len() > 1 && args[1] == "child" { + // Repeat several times to be more confident that + // it is `Drop` for `CString` that does the cleanup, + // and not just some lucky UB. + let xs = vec![CString::new("Hello").unwrap(); 10]; + let ys = xs.iter().map(|s| s.as_ptr()).collect::>(); + drop(xs); + assert!(ys.into_iter().any(is_hello)); + return; + } + + let output = Command::new(&args[0]).arg("child").output().unwrap(); + assert!(!output.status.success()); +} + +fn is_hello(s: *const c_char) -> bool { + // `s` is a dangling pointer and reading it is technically + // undefined behavior. But we want to prevent the most diabolical + // kind of UB (apart from nasal demons): reading a value that was + // previously written. + // + // Segfaulting or reading an empty string is Ok, + // reading "Hello" is bad. + let s = unsafe { CStr::from_ptr(s) }; + let hello = CString::new("Hello").unwrap(); + s == hello.as_ref() +}