about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/libstd/ffi/c_str.rs4
-rw-r--r--src/test/run-pass/cstring-drop.rs49
2 files changed, 3 insertions, 50 deletions
diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs
index d6a5efbd279..6f5ce350e6c 100644
--- a/src/libstd/ffi/c_str.rs
+++ b/src/libstd/ffi/c_str.rs
@@ -314,9 +314,11 @@ impl CString {
 }
 
 // Turns this `CString` into an empty string to prevent
-// memory unsafe code from working by accident.
+// memory unsafe code from working by accident. Inline
+// to prevent LLVM from optimizing it away in debug builds.
 #[stable(feature = "cstring_drop", since = "1.13.0")]
 impl Drop for CString {
+    #[inline]
     fn drop(&mut self) {
         unsafe { *self.inner.get_unchecked_mut(0) = 0; }
     }
diff --git a/src/test/run-pass/cstring-drop.rs b/src/test/run-pass/cstring-drop.rs
deleted file mode 100644
index 960391bb8de..00000000000
--- a/src/test/run-pass/cstring-drop.rs
+++ /dev/null
@@ -1,49 +0,0 @@
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<String> = 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::<Vec<_>>();
-        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()
-}