about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAleksey Kladov <aleksey.kladov@gmail.com>2016-09-26 15:22:22 +0300
committerAleksey Kladov <aleksey.kladov@gmail.com>2016-09-26 20:50:32 +0300
commit300e13808e679e6224f51705794b234dfd8bf73a (patch)
treef9315cf93ecaceb0307b6cbc76afacf198b9eb6c
parentb786976a158e79196254f489bb3a6f87e4d16a5a (diff)
downloadrust-300e13808e679e6224f51705794b234dfd8bf73a.tar.gz
rust-300e13808e679e6224f51705794b234dfd8bf73a.zip
Remove CString drop test.
The test relies on the undefined behavior, and so may fail in some
circumstances. This can be worked around by stubbing a memory allocator
in the test, but it is a bit of work, and LLVM could still theoretically
eliminate the write of the zero byte in release mode (which is
intended).

So let's just remove the test and mark the function as inline. It
shouldn't be optimized away when inlined into the debug build of user's
code.
-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()
-}