]> git.lizzy.rs Git - rust.git/commitdiff
Fix calling destructor on uninitialized dynamic library crash.
authorSteven Stewart-Gallus <sstewartgallus00@mylangara.bc.ca>
Thu, 1 Aug 2013 21:58:37 +0000 (14:58 -0700)
committerSteven Stewart-Gallus <sstewartgallus00@mylangara.bc.ca>
Fri, 2 Aug 2013 06:41:33 +0000 (23:41 -0700)
A test case was also created for this situation to prevent the problem
occuring again.

A similar problem was also fixed for the symbol method.

There was some minor code cleanup.

src/libstd/unstable/dynamic_lib.rs

index ab44520454d62220a65915c1fec7f98d247c4245..8d5654255f14a7264f50a9b3294dec4b49ffcc3c 100644 (file)
@@ -31,7 +31,7 @@ fn drop(&self) {
                 dl::close(self.handle)
             }
         } {
-            Ok(()) => { },
+            Ok(()) => {},
             Err(str) => fail!(str)
         }
     }
@@ -41,14 +41,20 @@ impl DynamicLibrary {
     /// Lazily open a dynamic library. When passed None it gives a
     /// handle to the calling process
     pub fn open(filename: Option<&path::Path>) -> Result<DynamicLibrary, ~str> {
-        do dl::check_for_errors_in {
-            unsafe {
-                DynamicLibrary { handle:
-                    match filename {
-                        Some(name) => dl::open_external(name),
-                        None => dl::open_internal()
-                    }
+        unsafe {
+            let maybe_library = do dl::check_for_errors_in {
+                match filename {
+                    Some(name) => dl::open_external(name),
+                    None => dl::open_internal()
                 }
+            };
+
+            // The dynamic library must not be constructed if there is
+            // an error opening the library so the destructor does not
+            // run.
+            match maybe_library {
+                Err(err) => Err(err),
+                Ok(handle) => Ok(DynamicLibrary { handle: handle })
             }
         }
     }
@@ -58,41 +64,69 @@ pub unsafe fn symbol<T>(&self, symbol: &str) -> Result<T, ~str> {
         // This function should have a lifetime constraint of 'self on
         // T but that feature is still unimplemented
 
-        do dl::check_for_errors_in {
-            let symbol_value = do symbol.as_c_str |raw_string| {
+        let maybe_symbol_value = do dl::check_for_errors_in {
+            do symbol.as_c_str |raw_string| {
                 dl::symbol(self.handle, raw_string)
-            };
+            }
+        };
 
-            cast::transmute(symbol_value)
+        // The value must not be constructed if there is an error so
+        // the destructor does not run.
+        match maybe_symbol_value {
+            Err(err) => Err(err),
+            Ok(symbol_value) => Ok(cast::transmute(symbol_value))
         }
     }
 }
 
-#[test]
-#[ignore(cfg(windows))]
-priv fn test_loading_cosine () {
-    // The math library does not need to be loaded since it is already
-    // statically linked in
-    let libm = match DynamicLibrary::open(None) {
-        Err (error) => fail!("Could not load self as module: %s", error),
-        Ok (libm) => libm
-    };
-
-    // Unfortunately due to issue #6194 it is not possible to call
-    // this as a C function
-    let cosine: extern fn(libc::c_double) -> libc::c_double = unsafe {
-        match libm.symbol("cos") {
-            Err (error) => fail!("Could not load function cos: %s", error),
-            Ok (cosine) => cosine
+
+#[cfg(test)]
+mod test {
+    use super::*;
+    use option::*;
+    use result::*;
+    use path::*;
+    use libc;
+
+    #[test]
+    fn test_loading_cosine() {
+        // The math library does not need to be loaded since it is already
+        // statically linked in
+        let libm = match DynamicLibrary::open(None) {
+            Err(error) => fail!("Could not load self as module: %s", error),
+            Ok(libm) => libm
+        };
+
+        // Unfortunately due to issue #6194 it is not possible to call
+        // this as a C function
+        let cosine: extern fn(libc::c_double) -> libc::c_double = unsafe {
+            match libm.symbol("cos") {
+                Err(error) => fail!("Could not load function cos: %s", error),
+                Ok(cosine) => cosine
+            }
+        };
+
+        let argument = 0.0;
+        let expected_result = 1.0;
+        let result = cosine(argument);
+        if result != expected_result {
+            fail!("cos(%?) != %? but equaled %? instead", argument,
+                  expected_result, result)
+        }
+    }
+
+    #[test]
+    #[cfg(target_os = "linux")]
+    #[cfg(target_os = "macos")]
+    #[cfg(target_os = "freebsd")]
+    fn test_errors_do_not_crash() {
+        // Open /dev/null as a library to get an error, and make sure
+        // that only causes an error, and not a crash.
+        let path = GenericPath::from_str("/dev/null");
+        match DynamicLibrary::open(Some(&path)) {
+            Err(_) => {}
+            Ok(_) => fail!("Successfully opened the empty library.")
         }
-    };
-
-    let argument = 0.0;
-    let expected_result = 1.0;
-    let result = cosine(argument);
-    if result != expected_result {
-        fail!("cos(%?) != %? but equaled %? instead", argument,
-              expected_result, result)
     }
 }