Bug 1804595 - Update osclientcerts to libloading 0.7. r=keeler,supply-chain-reviewers

Differential Revision: https://phabricator.services.mozilla.com/D164177
This commit is contained in:
Mike Hommey 2022-12-13 00:37:50 +00:00
Родитель cb37196702
Коммит 5fd296e7b8
24 изменённых файлов: 12 добавлений и 1660 удалений

22
Cargo.lock сгенерированный
Просмотреть файл

@ -144,7 +144,7 @@ version = "0.37.0+1.3.209"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "006ca68e0f2b03f22d6fa9f2860f85aed430d257fec20f8879b2145e7c7ae1a6"
dependencies = [
"libloading 0.7.3",
"libloading",
]
[[package]]
@ -784,7 +784,7 @@ checksum = "5a050e2153c5be08febd6734e29298e844fdb0fa21aeddd63b4eb7baa106c69b"
dependencies = [
"glob",
"libc",
"libloading 0.7.3",
"libloading",
]
[[package]]
@ -1215,7 +1215,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "827914e1f53b1e0e025ecd3d967a7836b7bcb54520f90e21ef8df7b4d88a2759"
dependencies = [
"bitflags",
"libloading 0.7.3",
"libloading",
"winapi",
]
@ -2903,7 +2903,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c2352bd1d0bceb871cb9d40f24360c8133c11d7486b68b5381c1dd1a32015e3"
dependencies = [
"libc",
"libloading 0.7.3",
"libloading",
"pkg-config",
]
@ -3014,16 +3014,6 @@ dependencies = [
"pkg-config",
]
[[package]]
name = "libloading"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2b111a074963af1d37a139918ac6d49ad1d0d5e47f72fd55388619691a7d753"
dependencies = [
"cc",
"winapi",
]
[[package]]
name = "libloading"
version = "0.7.3"
@ -4001,7 +3991,7 @@ dependencies = [
"core-foundation",
"env_logger 0.9.0",
"lazy_static",
"libloading 0.5.2",
"libloading",
"log",
"mozilla-central-workspace-hack",
"pkcs11-bindings",
@ -6365,7 +6355,7 @@ dependencies = [
"gpu-descriptor",
"js-sys",
"khronos-egl",
"libloading 0.7.3",
"libloading",
"log",
"metal",
"naga",

Просмотреть файл

@ -91,7 +91,6 @@ TOLERATED_DUPES = {
"crossbeam-epoch": 2,
"crossbeam-utils": 3,
"futures": 2,
"libloading": 2,
"memoffset": 2,
"mio": 2,
# Transition from time 0.1 to 0.3 underway, but chrono is stuck on 0.1

Просмотреть файл

@ -21,7 +21,7 @@ sha2 = "0.10.2"
version = "0.9"
[target."cfg(target_os = \"macos\")".dependencies.libloading]
version = "0.5"
version = "0.7"
[target."cfg(target_os = \"windows\")".dependencies.winapi]
version = "0.3"

Просмотреть файл

@ -84,15 +84,17 @@ struct SecurityFramework<'a> {
}
lazy_static! {
static ref SECURITY_LIBRARY: std::io::Result<Library> =
Library::new("/System/Library/Frameworks/Security.framework/Security");
static ref SECURITY_LIBRARY: Result<Library, String> = unsafe {
Library::new("/System/Library/Frameworks/Security.framework/Security")
.map_err(|e| e.to_string())
};
}
impl<'a> SecurityFramework<'a> {
fn new() -> Result<SecurityFramework<'a>, Error> {
let library = match &*SECURITY_LIBRARY {
Ok(library) => library,
Err(e) => return Err(error_here!(ErrorType::ExternalError, e.to_string())),
Err(e) => return Err(error_here!(ErrorType::ExternalError, e.clone())),
};
let sec_certificate_copy_key = unsafe {
library

Просмотреть файл

@ -759,10 +759,6 @@ criteria = "safe-to-deploy"
version = "0.2.2"
criteria = "safe-to-deploy"
[[exemptions.libloading]]
version = "0.5.2"
criteria = "safe-to-deploy"
[[exemptions.libloading]]
version = "0.7.3"
criteria = "safe-to-deploy"

Просмотреть файл

@ -1 +0,0 @@
{"files":{"Cargo.toml":"9110a58fe827a68e5df22f8d38e4beab38c259724942e868c5ae3debc2f0ebae","LICENSE":"b29f8b01452350c20dd1af16ef83b598fea3053578ccc1c7a0ef40e57be2620f","README.mkd":"b4cd83f110d01dc5aa8fcaf3da34bdbe1478efdba767d73abc14d4d87e4775fa","appveyor.yml":"8382c7f1769f6cf78029a221058c4d73f35a48308b5dfc38d875facabec1c139","build.rs":"d8f7fce1b459d117cd48d85ba3643124bd09657a0df9e0e90a1fd997decff741","src/changelog.rs":"e8a769578ebe2db81055b131ce12fa14c9ad0f21a79035748f244e5b347b2ada","src/lib.rs":"0cc0f6b42c98c14183dea2bc9deaf5aa574fabbe61081fe3339d74430f25fc12","src/os/mod.rs":"51d733e5522dacd6069642ad66aa6d7acf6c82950c934eb040e8dfd112e6d610","src/os/unix/global_static.c":"b1096dedf7d4aed5c28b658fc917f6603339ffd92390c84e25cb543bdc9460ac","src/os/unix/mod.rs":"9a84c15d0b9e5125a6ca086854a0e18884cb6c04cea54f47f1a44243e69335c2","src/os/windows/mod.rs":"c0ee0068a0564d64b7f3d3053d799492693c34571a935fc893a41a62a86fccdd","src/test_helpers.rs":"3a55052e8cd5231e97d9282b43398c2f144c57ced2d2df64bde7f482f5c778e7","src/util.rs":"5d1d3fcf7e5e9dc67df0dbf91332c5e3f5875e90c8f80ada5cfad0bc3c402d7e","tests/functions.rs":"4633f3673db6a5b3623ea8927b13314c25502c9fbb63bb17a5a35650ea489012","tests/markers.rs":"8e9c1b883404d9190e4f23ed39b3d6cbbccb3a07883f733b04aed4357b9c6aca","tests/nagisa32.dll":"5c69b2bd9c8a6ad04165c221075fc9fade1dd66ca697399ace528a5a62328e36","tests/nagisa64.dll":"e20b95e3036f3289421abd100760874d4f455afd33c3b5b64fec56b191f7d477","tests/windows.rs":"7711dfe19062d91356cd127546542b1b6e13aeef76ad3098f32c8a6ae319b66a"},"package":"f2b111a074963af1d37a139918ac6d49ad1d0d5e47f72fd55388619691a7d753"}

27
third_party/rust/libloading-0.5.2/Cargo.toml поставляемый
Просмотреть файл

@ -1,27 +0,0 @@
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
#
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
# to registry (e.g., crates.io) dependencies
#
# If you believe there's an error in this file please file an
# issue against the rust-lang/cargo repository. If you're
# editing this file be aware that the upstream Cargo.toml
# will likely look very different (and much more reasonable)
[package]
name = "libloading"
version = "0.5.2"
authors = ["Simonas Kazlauskas <libloading@kazlauskas.me>"]
build = "build.rs"
description = "A safer binding to platforms dynamic library loading utilities"
documentation = "https://docs.rs/libloading/"
keywords = ["dlopen", "load", "shared", "dylib"]
license = "ISC"
repository = "https://github.com/nagisa/rust_libloading/"
[build-dependencies.cc]
version = "1.0"
[target."cfg(windows)".dependencies.winapi]
version = "0.3"
features = ["winerror", "errhandlingapi", "libloaderapi"]

12
third_party/rust/libloading-0.5.2/LICENSE поставляемый
Просмотреть файл

@ -1,12 +0,0 @@
Copyright © 2015, Simonas Kazlauskas
Permission to use, copy, modify, and/or distribute this software for any purpose with or without
fee is hereby granted, provided that the above copyright notice and this permission notice appear
in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
THIS SOFTWARE.

21
third_party/rust/libloading-0.5.2/README.mkd поставляемый
Просмотреть файл

@ -1,21 +0,0 @@
# libloading [![Travis CI][tcii]][tci] [![Appveyor CI][acii]][aci]
[tcii]: https://travis-ci.org/nagisa/rust_libloading.svg?branch=master
[tci]: https://travis-ci.org/nagisa/rust_libloading
[acii]: https://ci.appveyor.com/api/projects/status/cnncnu58qcxb1ikf/branch/master?svg=true
[aci]: https://ci.appveyor.com/project/nagisa/rust-libloading
A memory-safer wrapper around system dynamic library loading primitives. The most important safety
guarantee by this library is prevention of dangling-`Symbol`s that may occur after a `Library` is
unloaded.
Using this library allows loading dynamic libraries (also known as shared libraries) as well as use
functions and static variables these libraries contain.
* [Documentation][docs]
* [Changelog][changelog]
[docs]: https://docs.rs/libloading/
[changelog]: https://docs.rs/libloading/*/libloading/changelog/index.html
libloading is distributed under ISC (MIT-like) license.

Просмотреть файл

@ -1,19 +0,0 @@
environment:
matrix:
- TARGET: nightly-x86_64-pc-windows-msvc
- TARGET: nightly-i686-pc-windows-msvc
- TARGET: nightly-x86_64-pc-windows-gnu
- TARGET: nightly-i686-pc-windows-gnu
- TARGET: 1.14.0-x86_64-pc-windows-msvc
- TARGET: 1.14.0-i686-pc-windows-msvc
- TARGET: 1.14.0-x86_64-pc-windows-gnu
- TARGET: 1.14.0-i686-pc-windows-gnu
install:
- ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-${env:TARGET}.exe" -FileName "rust.exe"
- ps: .\rust.exe /VERYSILENT /NORESTART /DIR="C:\rust" | Out-Null
- ps: $env:PATH="$env:PATH;C:\rust\bin"
- rustc -vV
- cargo -vV
build: off
test_script:
- cargo test

32
third_party/rust/libloading-0.5.2/build.rs поставляемый
Просмотреть файл

@ -1,32 +0,0 @@
extern crate cc;
use std::io::Write;
use std::env;
fn main(){
let target_os = env::var("CARGO_CFG_TARGET_OS");
let is_unix = env::var_os("CARGO_CFG_UNIX").is_some();
match target_os.as_ref().map(|x| &**x) {
Ok("linux") | Ok("android") => println!("cargo:rustc-link-lib=dl"),
Ok("freebsd") | Ok("dragonfly") => println!("cargo:rustc-link-lib=c"),
// netbsd claims dl* will be available to any dynamically linked binary, but I havent
// found any libraries that have to be linked to on other platforms.
// What happens if the executable is not linked up dynamically?
Ok("openbsd") | Ok("bitrig") | Ok("netbsd") | Ok("macos") | Ok("ios") => {}
Ok("solaris") => {}
Ok("haiku") => {}
// dependencies come with winapi
Ok("windows") => {}
tos => {
writeln!(::std::io::stderr(),
"Building for an unknown target_os=`{:?}`!\nPlease report an issue ",
tos).expect("could not report the error");
::std::process::exit(0xfc);
}
}
if is_unix {
cc::Build::new()
.file("src/os/unix/global_static.c")
.compile("global_static");
}
}

Просмотреть файл

@ -1,103 +0,0 @@
//! Project changelog
/// Release 0.5.2 (2019-07-07)
///
/// * Added API to convert OS-specific `Library` and `Symbol` conversion to underlying resources.
pub mod r0_5_2 {}
/// Release 0.5.1 (2019-06-01)
///
/// * Build on Haiku targets.
pub mod r0_5_1 {}
/// Release 0.5.0 (2018-01-11)
///
/// * Update to `winapi = ^0.3`;
///
/// ## Breaking changes
///
/// * libloading now requires a C compiler to build on UNIX;
/// * This is a temporary measure until the [`linkage`] attribute is stabilised;
/// * Necessary to resolve [#32].
///
/// [`linkage`]: https://github.com/rust-lang/rust/issues/29603
/// [#32]: https://github.com/nagisa/rust_libloading/issues/32
pub mod r0_5_0 {}
/// Release 0.4.3 (2017-12-07)
///
/// * Bump lazy-static dependency to `^1.0`;
/// * `cargo test --release` now works when testing libloading.
pub mod r0_4_3 {}
/// Release 0.4.2 (2017-09-24)
///
/// * Improved error and race-condition handling on Windows;
/// * Improved documentation about thread-safety of Library;
/// * Added `Symbol::<Option<T>::lift_option() -> Option<Symbol<T>>` convenience method.
pub mod r0_4_2 {}
/// Release 0.4.1 (2017-08-29)
///
/// * Solaris support
pub mod r0_4_1 {}
/// Release 0.4.0 (2017-05-01)
///
/// * Remove build-time dependency on target_build_utils (and by extension serde/phf);
/// * Require at least version 1.14.0 of rustc to build;
/// * Actually, it is cargo which has to be more recent here. The one shipped with rustc 1.14.0
/// is whats being required from now on.
pub mod r0_4_0 {}
/// Release 0.3.4 (2017-03-25)
///
/// * Remove rogue println!
pub mod r0_3_4 {}
/// Release 0.3.3 (2017-03-25)
///
/// * Panics when `Library::get` is called for incompatibly sized type such as named function
/// types (which are zero-sized).
pub mod r0_3_3 {}
/// Release 0.3.2 (2017-02-10)
///
/// * Minimum version required is now rustc 1.12.0;
/// * Updated dependency versions (most notably target_build_utils to 0.3.0)
pub mod r0_3_2 {}
/// Release 0.3.1 (2016-10-01)
///
/// * `Symbol<T>` and `os::*::Symbol<T>` now implement `Send` where `T: Send`;
/// * `Symbol<T>` and `os::*::Symbol<T>` now implement `Sync` where `T: Sync`;
/// * `Library` and `os::*::Library` now implement `Sync` (they were `Send` in 0.3.0 already).
pub mod r0_3_1 {}
/// Release 0.3.0 (2016-07-27)
///
/// * Greatly improved documentation, especially around platform-specific behaviours;
/// * Improved test suite by building our own library to test against;
/// * All `Library`-ies now implement `Send`.
/// * Added `impl From<os::platform::Library> for Library` and `impl From<Library> for
/// os::platform::Library` allowing wrapping and extracting the platform-specific library handle;
/// * Added methods to wrap (`Symbol::from_raw`) and unwrap (`Symbol::into_raw`) the safe `Symbol`
/// wrapper into unsafe `os::platform::Symbol`.
///
/// The last two additions focus on not restricting potential usecases of this library, allowing
/// users of the library to circumvent safety checks if need be.
///
/// ## Breaking Changes
///
/// `Library::new` defaults to `RTLD_NOW` instead of `RTLD_LAZY` on UNIX for more consistent
/// cross-platform behaviour. If a library loaded with `Library::new` had any linking errors, but
/// unresolved references werent forced to be resolved, the library wouldve “just worked”,
/// whereas now the call to `Library::new` will return an error signifying presence of such error.
///
/// ## os::platform
/// * Added `os::unix::Library::open` which allows specifying arbitrary flags (e.g. `RTLD_LAZY`);
/// * Added `os::windows::Library::get_ordinal` which allows finding a function or variable by its
/// ordinal number;
pub mod r0_3_0 {}

310
third_party/rust/libloading-0.5.2/src/lib.rs поставляемый
Просмотреть файл

@ -1,310 +0,0 @@
//! A memory-safer wrapper around system dynamic library loading primitives.
//!
//! Using this library allows loading [dynamic libraries](struct.Library.html) (also known as
//! shared libraries) as well as use functions and static variables these libraries contain.
//!
//! While the library does expose a cross-platform interface to load a library and find stuff
//! inside it, little is done to paper over the platform differences, especially where library
//! loading is involved. The documentation for each function will attempt to document such
//! differences on the best-effort basis.
//!
//! Less safe, platform specific bindings are also available. See the
//! [`os::platform`](os/index.html) module for details.
//!
//! # Usage
//!
//! Add a dependency on this library to your `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
//! libloading = "0.5"
//! ```
//!
//! Then inside your project
//!
//! ```no_run
//! extern crate libloading as lib;
//!
//! fn call_dynamic() -> lib::Result<u32> {
//! let lib = lib::Library::new("/path/to/liblibrary.so")?;
//! unsafe {
//! let func: lib::Symbol<unsafe extern fn() -> u32> = lib.get(b"my_func")?;
//! Ok(func())
//! }
//! }
//! ```
//!
//! The compiler will ensure that the loaded `function` will not outlive the `Library` it comes
//! from, preventing a common cause of undefined behaviour and memory safety problems.
use std::ffi::OsStr;
use std::fmt;
use std::ops;
use std::marker;
#[cfg(unix)]
use self::os::unix as imp;
#[cfg(windows)]
use self::os::windows as imp;
pub mod os;
pub mod changelog;
mod util;
pub type Result<T> = ::std::io::Result<T>;
/// A loaded dynamic library.
pub struct Library(imp::Library);
impl Library {
/// Find and load a dynamic library.
///
/// The `filename` argument may be any of:
///
/// * A library filename;
/// * Absolute path to the library;
/// * Relative (to the current working directory) path to the library.
///
/// ## Thread-safety
///
/// The implementation strives to be as MT-safe as sanely possible, however due to certain
/// error-handling related resources not always being safe, this library is not MT-safe either.
///
/// * On Windows Vista and earlier error handling falls back to [`SetErrorMode`], which is not
/// MT-safe. MT-scenarios involving this function may cause a traditional data race;
/// * On some UNIX targets `dlerror` might not be MT-safe, resulting in garbage error messages
/// in certain MT-scenarios.
///
/// [`SetErrorMode`]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms680621(v=vs.85).aspx
///
/// Calling this function from multiple threads is not safe if used in conjunction with
/// path-less filename and library search path is modified (`SetDllDirectory` function on
/// Windows, `{DY,}LD_LIBRARY_PATH` environment variable on UNIX).
///
/// ## Platform-specific behaviour
///
/// When a plain library filename is supplied, locations where library is searched for is
/// platform specific and cannot be adjusted in a portable manner.
///
/// ### Windows
///
/// If the `filename` specifies a library filename without path and with extension omitted,
/// `.dll` extension is implicitly added. This behaviour may be suppressed by appending a
/// trailing `.` to the `filename`.
///
/// If the library contains thread local variables (MSVCs `_declspec(thread)`, Rusts
/// `#[thread_local]` attributes), loading the library will fail on versions prior to Windows
/// Vista.
///
/// ## Tips
///
/// Distributing your dynamic libraries under a filename common to all platforms (e.g.
/// `awesome.module`) allows to avoid code which has to account for platforms conventional
/// library filenames.
///
/// Strive to specify absolute or relative path to your library, unless system-wide libraries
/// are being loaded. Platform-dependent library search locations combined with various quirks
/// related to path-less filenames may cause flaky code.
///
/// ## Examples
///
/// ```no_run
/// # use ::libloading::Library;
/// // Any of the following are valid.
/// let _ = Library::new("/path/to/awesome.module").unwrap();
/// let _ = Library::new("../awesome.module").unwrap();
/// let _ = Library::new("libsomelib.so.1").unwrap();
/// ```
pub fn new<P: AsRef<OsStr>>(filename: P) -> Result<Library> {
imp::Library::new(filename).map(From::from)
}
/// Get a pointer to function or static variable by symbol name.
///
/// The `symbol` may not contain any null bytes, with an exception of last byte. A null
/// terminated `symbol` may avoid a string allocation in some cases.
///
/// Symbol is interpreted as-is; no mangling is done. This means that symbols like `x::y` are
/// most likely invalid.
///
/// ## Unsafety
///
/// Pointer to a value of arbitrary type is returned. Using a value with wrong type is
/// undefined.
///
/// ## Platform-specific behaviour
///
/// On Linux and Windows, a TLS variable acts just like any regular static variable. OS X uses
/// some sort of lazy initialization scheme, which makes loading TLS variables this way
/// impossible. Using a TLS variable loaded this way on OS X is undefined behaviour.
///
/// ## Examples
///
/// Given a loaded library:
///
/// ```no_run
/// # use ::libloading::Library;
/// let lib = Library::new("/path/to/awesome.module").unwrap();
/// ```
///
/// Loading and using a function looks like this:
///
/// ```no_run
/// # use ::libloading::{Library, Symbol};
/// # let lib = Library::new("/path/to/awesome.module").unwrap();
/// unsafe {
/// let awesome_function: Symbol<unsafe extern fn(f64) -> f64> =
/// lib.get(b"awesome_function\0").unwrap();
/// awesome_function(0.42);
/// }
/// ```
///
/// A static variable may also be loaded and inspected:
///
/// ```no_run
/// # use ::libloading::{Library, Symbol};
/// # let lib = Library::new("/path/to/awesome.module").unwrap();
/// unsafe {
/// let awesome_variable: Symbol<*mut f64> = lib.get(b"awesome_variable\0").unwrap();
/// **awesome_variable = 42.0;
/// };
/// ```
pub unsafe fn get<'lib, T>(&'lib self, symbol: &[u8]) -> Result<Symbol<'lib, T>> {
self.0.get(symbol).map(|from| Symbol::from_raw(from, self))
}
}
impl fmt::Debug for Library {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.0.fmt(f)
}
}
impl From<imp::Library> for Library {
fn from(lib: imp::Library) -> Library {
Library(lib)
}
}
impl From<Library> for imp::Library {
fn from(lib: Library) -> imp::Library {
lib.0
}
}
unsafe impl Send for Library {}
unsafe impl Sync for Library {}
/// Symbol from a library.
///
/// This type is a safeguard against using dynamically loaded symbols after a `Library` is
/// unloaded. Primary method to create an instance of a `Symbol` is via `Library::get`.
///
/// Due to implementation of the `Deref` trait, an instance of `Symbol` may be used as if it was a
/// function or variable directly, without taking care to “extract” function or variable manually
/// most of the time.
///
/// See [`Library::get`] for details.
///
/// [`Library::get`]: ./struct.Library.html#method.get
pub struct Symbol<'lib, T: 'lib> {
inner: imp::Symbol<T>,
pd: marker::PhantomData<&'lib T>
}
impl<'lib, T> Symbol<'lib, T> {
/// Extract the wrapped `os::platform::Symbol`.
///
/// ## Unsafety
/// Using this function relinquishes all the lifetime guarantees. It is up to programmer to
/// ensure the resulting `Symbol` is not used past the lifetime of the `Library` this symbol
/// was loaded from.
///
/// ## Examples
///
/// ```no_run
/// # use ::libloading::{Library, Symbol};
/// let lib = Library::new("/path/to/awesome.module").unwrap();
/// unsafe {
/// let symbol: Symbol<*mut u32> = lib.get(b"symbol\0").unwrap();
/// let symbol = symbol.into_raw();
/// }
/// ```
pub unsafe fn into_raw(self) -> imp::Symbol<T> {
self.inner
}
/// Wrap the `os::platform::Symbol` into this safe wrapper.
///
/// Note that, in order to create association between the symbol and the library this symbol
/// came from, this function requires reference to the library provided.
///
/// ## Unsafety
///
/// It is invalid to provide a reference to any other value other than the library the `sym`
/// was loaded from. Doing so invalidates any lifetime guarantees.
///
/// ## Examples
///
/// ```no_run
/// # use ::libloading::{Library, Symbol};
/// let lib = Library::new("/path/to/awesome.module").unwrap();
/// unsafe {
/// let symbol: Symbol<*mut u32> = lib.get(b"symbol\0").unwrap();
/// let symbol = symbol.into_raw();
/// let symbol = Symbol::from_raw(symbol, &lib);
/// }
/// ```
pub unsafe fn from_raw<L>(sym: imp::Symbol<T>, _: &'lib L) -> Symbol<'lib, T> {
Symbol {
inner: sym,
pd: marker::PhantomData
}
}
}
impl<'lib, T> Symbol<'lib, Option<T>> {
/// Lift Option out of the symbol.
///
/// ## Examples
///
/// ```no_run
/// # use ::libloading::{Library, Symbol};
/// let lib = Library::new("/path/to/awesome.module").unwrap();
/// unsafe {
/// let symbol: Symbol<Option<*mut u32>> = lib.get(b"symbol\0").unwrap();
/// let symbol: Symbol<*mut u32> = symbol.lift_option().expect("static is not null");
/// }
/// ```
pub fn lift_option(self) -> Option<Symbol<'lib, T>> {
self.inner.lift_option().map(|is| Symbol {
inner: is,
pd: marker::PhantomData,
})
}
}
impl<'lib, T> Clone for Symbol<'lib, T> {
fn clone(&self) -> Symbol<'lib, T> {
Symbol {
inner: self.inner.clone(),
pd: marker::PhantomData
}
}
}
// FIXME: implement FnOnce for callable stuff instead.
impl<'lib, T> ops::Deref for Symbol<'lib, T> {
type Target = T;
fn deref(&self) -> &T {
ops::Deref::deref(&self.inner)
}
}
impl<'lib, T> fmt::Debug for Symbol<'lib, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.inner.fmt(f)
}
}
unsafe impl<'lib, T: Send> Send for Symbol<'lib, T> {}
unsafe impl<'lib, T: Sync> Sync for Symbol<'lib, T> {}

Просмотреть файл

@ -1,45 +0,0 @@
//! Unsafe, platform specific bindings to dynamic library loading facilities.
//!
//! These modules expose more extensive, powerful, less principled bindings to the dynamic
//! library loading facilities. Use of these bindings come at the cost of less (in most cases,
//! none at all) safety guarantees, which are provided by the top-level bindings.
//!
//! # Examples
//!
//! Using these modules will likely involve conditional compilation:
//!
//! ```ignore
//! # extern crate libloading;
//! #[cfg(unix)]
//! use libloading::os::unix::*;
//! #[cfg(windows)]
//! use libloading::os::windows::*;
//! ```
macro_rules! unix {
($item: item) => {
/// UNIX implementation of dynamic library loading.
///
/// This module should be expanded with more UNIX-specific functionality in the future.
$item
}
}
macro_rules! windows {
($item: item) => {
/// Windows implementation of dynamic library loading.
///
/// This module should be expanded with more Windows-specific functionality in the future.
$item
}
}
#[cfg(unix)]
unix!(pub mod unix;);
#[cfg(unix)]
windows!(pub mod windows {});
#[cfg(windows)]
windows!(pub mod windows;);
#[cfg(windows)]
unix!(pub mod unix {});

Просмотреть файл

@ -1,20 +0,0 @@
#include <pthread.h>
#include <stdlib.h>
pthread_mutex_t __attribute__((weak)) rust_libloading_dlerror_mutex = PTHREAD_MUTEX_INITIALIZER;
void __attribute__((weak))
rust_libloading_dlerror_mutex_lock(void)
{
if (pthread_mutex_lock(&rust_libloading_dlerror_mutex) != 0) {
abort();
}
}
void __attribute__((weak))
rust_libloading_dlerror_mutex_unlock(void)
{
if (pthread_mutex_unlock(&rust_libloading_dlerror_mutex) != 0) {
abort();
}
}

Просмотреть файл

@ -1,336 +0,0 @@
use util::{ensure_compatible_types, cstr_cow_from_bytes};
use std::ffi::{CStr, OsStr};
use std::{fmt, io, marker, mem, ptr};
use std::os::raw;
use std::os::unix::ffi::OsStrExt;
extern "C" {
fn rust_libloading_dlerror_mutex_lock();
fn rust_libloading_dlerror_mutex_unlock();
}
struct DlerrorMutexGuard(());
impl DlerrorMutexGuard {
fn new() -> DlerrorMutexGuard {
unsafe {
rust_libloading_dlerror_mutex_lock();
}
DlerrorMutexGuard(())
}
}
impl Drop for DlerrorMutexGuard {
fn drop(&mut self) {
unsafe {
rust_libloading_dlerror_mutex_unlock();
}
}
}
// libdl is crazy.
//
// First of all, whole error handling scheme in libdl is done via setting and querying some global
// state, therefore it is not safe to use libdl in MT-capable environment at all. Only in POSIX
// 2008+TC1 a thread-local state was allowed, which for our purposes is way too late.
fn with_dlerror<T, F>(closure: F) -> Result<T, Option<io::Error>>
where F: FnOnce() -> Option<T> {
// We will guard all uses of libdl library with our own mutex. This makes libdl
// safe to use in MT programs provided the only way a program uses libdl is via this library.
let _lock = DlerrorMutexGuard::new();
// While we could could call libdl here to clear the previous error value, only the dlsym
// depends on it being cleared beforehand and only in some cases too. We will instead clear the
// error inside the dlsym binding instead.
//
// In all the other cases, clearing the error here will only be hiding misuse of these bindings
// or the libdl.
closure().ok_or_else(|| unsafe {
// This code will only get executed if the `closure` returns `None`.
let error = dlerror();
if error.is_null() {
// In non-dlsym case this may happen when therere bugs in our bindings or theres
// non-libloading user of libdl; possibly in another thread.
None
} else {
// You cant even rely on error string being static here; call to subsequent dlerror
// may invalidate or overwrite the error message. Why couldnt they simply give up the
// ownership over the message?
// TODO: should do locale-aware conversion here. OTOH Rust doesnt seem to work well in
// any system that uses non-utf8 locale, so I doubt theres a problem here.
let message = CStr::from_ptr(error).to_string_lossy().into_owned();
Some(io::Error::new(io::ErrorKind::Other, message))
// Since we do a copy of the error string above, maybe we should call dlerror again to
// let libdl know it may free its copy of the string now?
}
})
}
/// A platform-specific equivalent of the cross-platform `Library`.
pub struct Library {
handle: *mut raw::c_void
}
unsafe impl Send for Library {}
// That being said... this section in the volume 2 of POSIX.1-2008 states:
//
// > All functions defined by this volume of POSIX.1-2008 shall be thread-safe, except that the
// > following functions need not be thread-safe.
//
// With notable absence of any dl* function other than dlerror in the list. By “this volume”
// I suppose they refer precisely to the “volume 2”. dl* family of functions are specified
// by this same volume, so the conclusion is indeed that dl* functions are required by POSIX
// to be thread-safe. Great!
//
// See for more details:
//
// * https://github.com/nagisa/rust_libloading/pull/17
// * http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_09_01
unsafe impl Sync for Library {}
impl Library {
/// Find and load a shared library (module).
///
/// Locations where library is searched for is platform specific and cant be adjusted
/// portably.
///
/// Corresponds to `dlopen(filename, RTLD_NOW)`.
#[inline]
pub fn new<P: AsRef<OsStr>>(filename: P) -> ::Result<Library> {
Library::open(Some(filename), RTLD_NOW)
}
/// Load the dynamic libraries linked into main program.
///
/// This allows retrieving symbols from any **dynamic** library linked into the program,
/// without specifying the exact library.
///
/// Corresponds to `dlopen(NULL, RTLD_NOW)`.
#[inline]
pub fn this() -> Library {
Library::open(None::<&OsStr>, RTLD_NOW).unwrap()
}
/// Find and load a shared library (module).
///
/// Locations where library is searched for is platform specific and cant be adjusted
/// portably.
///
/// If the `filename` is None, null pointer is passed to `dlopen`.
///
/// Corresponds to `dlopen(filename, flags)`.
pub fn open<P>(filename: Option<P>, flags: raw::c_int) -> ::Result<Library>
where P: AsRef<OsStr> {
let filename = match filename {
None => None,
Some(ref f) => Some(try!(cstr_cow_from_bytes(f.as_ref().as_bytes()))),
};
with_dlerror(move || {
let result = unsafe {
let r = dlopen(match filename {
None => ptr::null(),
Some(ref f) => f.as_ptr()
}, flags);
// ensure filename lives until dlopen completes
drop(filename);
r
};
if result.is_null() {
None
} else {
Some(Library {
handle: result
})
}
}).map_err(|e| e.unwrap_or_else(||
panic!("dlopen failed but dlerror did not report anything")
))
}
/// Get a pointer to function or static variable by symbol name.
///
/// The `symbol` may not contain any null bytes, with an exception of last byte. A null
/// terminated `symbol` may avoid a string allocation in some cases.
///
/// Symbol is interpreted as-is; no mangling is done. This means that symbols like `x::y` are
/// most likely invalid.
///
/// ## Unsafety
///
/// Pointer to a value of arbitrary type is returned. Using a value with wrong type is
/// undefined.
///
/// ## Platform-specific behaviour
///
/// OS X uses some sort of lazy initialization scheme, which makes loading TLS variables
/// impossible. Using a TLS variable loaded this way on OS X is undefined behaviour.
pub unsafe fn get<T>(&self, symbol: &[u8]) -> ::Result<Symbol<T>> {
ensure_compatible_types::<T, *mut raw::c_void>();
let symbol = try!(cstr_cow_from_bytes(symbol));
// `dlsym` may return nullptr in two cases: when a symbol genuinely points to a null
// pointer or the symbol cannot be found. In order to detect this case a double dlerror
// pattern must be used, which is, sadly, a little bit racy.
//
// We try to leave as little space as possible for this to occur, but we cant exactly
// fully prevent it.
match with_dlerror(|| {
dlerror();
let symbol = dlsym(self.handle, symbol.as_ptr());
if symbol.is_null() {
None
} else {
Some(Symbol {
pointer: symbol,
pd: marker::PhantomData
})
}
}) {
Err(None) => Ok(Symbol {
pointer: ptr::null_mut(),
pd: marker::PhantomData
}),
Err(Some(e)) => Err(e),
Ok(x) => Ok(x)
}
}
/// Convert the `Library` to a raw handle.
///
/// The handle returned by this function shall be usable with APIs which accept handles
/// as returned by `dlopen`.
pub fn into_raw(self) -> *mut raw::c_void {
let handle = self.handle;
mem::forget(self);
handle
}
/// Convert a raw handle returned by `dlopen`-family of calls to a `Library`.
///
/// ## Unsafety
///
/// The pointer shall be a result of a successful call of the `dlopen`-family of functions or a
/// pointer previously returned by `Library::into_raw` call. It must be valid to call `dlclose`
/// with this pointer as an argument.
pub unsafe fn from_raw(handle: *mut raw::c_void) -> Library {
Library {
handle: handle
}
}
}
impl Drop for Library {
fn drop(&mut self) {
with_dlerror(|| if unsafe { dlclose(self.handle) } == 0 {
Some(())
} else {
None
}).unwrap();
}
}
impl fmt::Debug for Library {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str(&format!("Library@{:p}", self.handle))
}
}
/// Symbol from a library.
///
/// A major difference compared to the cross-platform `Symbol` is that this does not ensure the
/// `Symbol` does not outlive `Library` it comes from.
pub struct Symbol<T> {
pointer: *mut raw::c_void,
pd: marker::PhantomData<T>
}
impl<T> Symbol<T> {
/// Convert the loaded Symbol into a raw pointer.
pub fn into_raw(self) -> *mut raw::c_void {
let pointer = self.pointer;
mem::forget(self);
pointer
}
}
impl<T> Symbol<Option<T>> {
/// Lift Option out of the symbol.
pub fn lift_option(self) -> Option<Symbol<T>> {
if self.pointer.is_null() {
None
} else {
Some(Symbol {
pointer: self.pointer,
pd: marker::PhantomData,
})
}
}
}
unsafe impl<T: Send> Send for Symbol<T> {}
unsafe impl<T: Sync> Sync for Symbol<T> {}
impl<T> Clone for Symbol<T> {
fn clone(&self) -> Symbol<T> {
Symbol { ..*self }
}
}
impl<T> ::std::ops::Deref for Symbol<T> {
type Target = T;
fn deref(&self) -> &T {
unsafe {
// Additional reference level for a dereference on `deref` return value.
mem::transmute(&self.pointer)
}
}
}
impl<T> fmt::Debug for Symbol<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
unsafe {
let mut info: DlInfo = mem::uninitialized();
if dladdr(self.pointer, &mut info) != 0 {
if info.dli_sname.is_null() {
f.write_str(&format!("Symbol@{:p} from {:?}",
self.pointer,
CStr::from_ptr(info.dli_fname)))
} else {
f.write_str(&format!("Symbol {:?}@{:p} from {:?}",
CStr::from_ptr(info.dli_sname), self.pointer,
CStr::from_ptr(info.dli_fname)))
}
} else {
f.write_str(&format!("Symbol@{:p}", self.pointer))
}
}
}
}
// Platform specific things
extern {
fn dlopen(filename: *const raw::c_char, flags: raw::c_int) -> *mut raw::c_void;
fn dlclose(handle: *mut raw::c_void) -> raw::c_int;
fn dlsym(handle: *mut raw::c_void, symbol: *const raw::c_char) -> *mut raw::c_void;
fn dlerror() -> *mut raw::c_char;
fn dladdr(addr: *mut raw::c_void, info: *mut DlInfo) -> raw::c_int;
}
#[cfg(not(target_os="android"))]
const RTLD_NOW: raw::c_int = 2;
#[cfg(target_os="android")]
const RTLD_NOW: raw::c_int = 0;
#[repr(C)]
struct DlInfo {
dli_fname: *const raw::c_char,
dli_fbase: *mut raw::c_void,
dli_sname: *const raw::c_char,
dli_saddr: *mut raw::c_void
}
#[test]
fn this() {
Library::this();
}

Просмотреть файл

@ -1,313 +0,0 @@
extern crate winapi;
use self::winapi::shared::minwindef::{WORD, DWORD, HMODULE, FARPROC};
use self::winapi::shared::ntdef::WCHAR;
use self::winapi::shared::winerror;
use self::winapi::um::{errhandlingapi, libloaderapi};
use util::{ensure_compatible_types, cstr_cow_from_bytes};
use std::ffi::{OsStr, OsString};
use std::{fmt, io, marker, mem, ptr};
use std::os::windows::ffi::{OsStrExt, OsStringExt};
use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering};
/// A platform-specific equivalent of the cross-platform `Library`.
pub struct Library(HMODULE);
unsafe impl Send for Library {}
// Now, this is sort-of-tricky. MSDN documentation does not really make any claims as to safety of
// the Win32 APIs. Sadly, whomever I asked, even current and former Microsoft employees, couldnt
// say for sure, whether the Win32 APIs used to implement `Library` are thread-safe or not.
//
// My investigation ended up with a question about thread-safety properties of the API involved
// being sent to an internal (to MS) general question mailing-list. The conclusion of the mail is
// as such:
//
// * Nobody inside MS (at least out of all the people who have seen the question) knows for
// sure either;
// * However, the general consensus between MS developers is that one can rely on the API being
// thread-safe. In case it is not thread-safe it should be considered a bug on the Windows
// part. (NB: bugs filled at https://connect.microsoft.com/ against Windows Server)
unsafe impl Sync for Library {}
impl Library {
/// Find and load a shared library (module).
///
/// Corresponds to `LoadLibraryW(filename)`.
#[inline]
pub fn new<P: AsRef<OsStr>>(filename: P) -> ::Result<Library> {
let wide_filename: Vec<u16> = filename.as_ref().encode_wide().chain(Some(0)).collect();
let _guard = ErrorModeGuard::new();
let ret = with_get_last_error(|| {
// Make sure no winapi calls as a result of drop happen inside this closure, because
// otherwise that might change the return value of the GetLastError.
let handle = unsafe { libloaderapi::LoadLibraryW(wide_filename.as_ptr()) };
if handle.is_null() {
None
} else {
Some(Library(handle))
}
}).map_err(|e| e.unwrap_or_else(||
panic!("LoadLibraryW failed but GetLastError did not report the error")
));
drop(wide_filename); // Drop wide_filename here to ensure it doesnt get moved and dropped
// inside the closure by mistake. See comment inside the closure.
ret
}
/// Get a pointer to function or static variable by symbol name.
///
/// The `symbol` may not contain any null bytes, with an exception of last byte. A null
/// terminated `symbol` may avoid a string allocation in some cases.
///
/// Symbol is interpreted as-is; no mangling is done. This means that symbols like `x::y` are
/// most likely invalid.
///
/// ## Unsafety
///
/// Pointer to a value of arbitrary type is returned. Using a value with wrong type is
/// undefined.
pub unsafe fn get<T>(&self, symbol: &[u8]) -> ::Result<Symbol<T>> {
ensure_compatible_types::<T, FARPROC>();
let symbol = try!(cstr_cow_from_bytes(symbol));
with_get_last_error(|| {
let symbol = libloaderapi::GetProcAddress(self.0, symbol.as_ptr());
if symbol.is_null() {
None
} else {
Some(Symbol {
pointer: symbol,
pd: marker::PhantomData
})
}
}).map_err(|e| e.unwrap_or_else(||
panic!("GetProcAddress failed but GetLastError did not report the error")
))
}
/// Get a pointer to function or static variable by ordinal number.
///
/// ## Unsafety
///
/// Pointer to a value of arbitrary type is returned. Using a value with wrong type is
/// undefined.
pub unsafe fn get_ordinal<T>(&self, ordinal: WORD) -> ::Result<Symbol<T>> {
ensure_compatible_types::<T, FARPROC>();
with_get_last_error(|| {
let ordinal = ordinal as usize as *mut _;
let symbol = libloaderapi::GetProcAddress(self.0, ordinal);
if symbol.is_null() {
None
} else {
Some(Symbol {
pointer: symbol,
pd: marker::PhantomData
})
}
}).map_err(|e| e.unwrap_or_else(||
panic!("GetProcAddress failed but GetLastError did not report the error")
))
}
/// Convert the `Library` to a raw handle.
pub fn into_raw(self) -> HMODULE {
let handle = self.0;
mem::forget(self);
handle
}
/// Convert a raw handle to a `Library`.
///
/// ## Unsafety
///
/// The handle shall be a result of a successful call of `LoadLibraryW` or a
/// handle previously returned by the `Library::into_raw` call.
pub unsafe fn from_raw(handle: HMODULE) -> Library {
Library(handle)
}
}
impl Drop for Library {
fn drop(&mut self) {
with_get_last_error(|| {
if unsafe { libloaderapi::FreeLibrary(self.0) == 0 } {
None
} else {
Some(())
}
}).unwrap()
}
}
impl fmt::Debug for Library {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
unsafe {
let mut buf: [WCHAR; 1024] = mem::uninitialized();
let len = libloaderapi::GetModuleFileNameW(self.0,
(&mut buf[..]).as_mut_ptr(), 1024) as usize;
if len == 0 {
f.write_str(&format!("Library@{:p}", self.0))
} else {
let string: OsString = OsString::from_wide(&buf[..len]);
f.write_str(&format!("Library@{:p} from {:?}", self.0, string))
}
}
}
}
/// Symbol from a library.
///
/// A major difference compared to the cross-platform `Symbol` is that this does not ensure the
/// `Symbol` does not outlive `Library` it comes from.
pub struct Symbol<T> {
pointer: FARPROC,
pd: marker::PhantomData<T>
}
impl<T> Symbol<T> {
/// Convert the loaded Symbol into a handle.
pub fn into_raw(self) -> FARPROC {
let pointer = self.pointer;
mem::forget(self);
pointer
}
}
impl<T> Symbol<Option<T>> {
/// Lift Option out of the symbol.
pub fn lift_option(self) -> Option<Symbol<T>> {
if self.pointer.is_null() {
None
} else {
Some(Symbol {
pointer: self.pointer,
pd: marker::PhantomData,
})
}
}
}
unsafe impl<T: Send> Send for Symbol<T> {}
unsafe impl<T: Sync> Sync for Symbol<T> {}
impl<T> Clone for Symbol<T> {
fn clone(&self) -> Symbol<T> {
Symbol { ..*self }
}
}
impl<T> ::std::ops::Deref for Symbol<T> {
type Target = T;
fn deref(&self) -> &T {
unsafe {
// Additional reference level for a dereference on `deref` return value.
mem::transmute(&self.pointer)
}
}
}
impl<T> fmt::Debug for Symbol<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str(&format!("Symbol@{:p}", self.pointer))
}
}
static USE_ERRORMODE: AtomicBool = ATOMIC_BOOL_INIT;
struct ErrorModeGuard(DWORD);
impl ErrorModeGuard {
fn new() -> Option<ErrorModeGuard> {
const SEM_FAILCE: DWORD = 1;
unsafe {
if !USE_ERRORMODE.load(Ordering::Acquire) {
let mut previous_mode = 0;
let success = errhandlingapi::SetThreadErrorMode(SEM_FAILCE, &mut previous_mode) != 0;
if !success && errhandlingapi::GetLastError() == winerror::ERROR_CALL_NOT_IMPLEMENTED {
USE_ERRORMODE.store(true, Ordering::Release);
} else if !success {
// SetThreadErrorMode failed with some other error? How in the world is it
// possible for what is essentially a simple variable swap to fail?
// For now we just ignore the error -- the worst that can happen here is
// the previous mode staying on and user seeing a dialog error on older Windows
// machines.
return None;
} else if previous_mode == SEM_FAILCE {
return None;
} else {
return Some(ErrorModeGuard(previous_mode));
}
}
match errhandlingapi::SetErrorMode(SEM_FAILCE) {
SEM_FAILCE => {
// This is important to reduce racy-ness when this library is used on multiple
// threads. In particular this helps with following race condition:
//
// T1: SetErrorMode(SEM_FAILCE)
// T2: SetErrorMode(SEM_FAILCE)
// T1: SetErrorMode(old_mode) # not SEM_FAILCE
// T2: SetErrorMode(SEM_FAILCE) # restores to SEM_FAILCE on drop
//
// This is still somewhat racy in a sense that T1 might restore the error
// mode before T2 finishes loading the library, but that is less of a
// concern – it will only end up in end user seeing a dialog.
//
// Also, SetErrorMode itself is probably not an atomic operation.
None
}
a => Some(ErrorModeGuard(a))
}
}
}
}
impl Drop for ErrorModeGuard {
fn drop(&mut self) {
unsafe {
if !USE_ERRORMODE.load(Ordering::Relaxed) {
errhandlingapi::SetThreadErrorMode(self.0, ptr::null_mut());
} else {
errhandlingapi::SetErrorMode(self.0);
}
}
}
}
fn with_get_last_error<T, F>(closure: F) -> Result<T, Option<io::Error>>
where F: FnOnce() -> Option<T> {
closure().ok_or_else(|| {
let error = unsafe { errhandlingapi::GetLastError() };
if error == 0 {
None
} else {
Some(io::Error::from_raw_os_error(error as i32))
}
})
}
#[test]
fn works_getlasterror() {
let lib = Library::new("kernel32.dll").unwrap();
let gle: Symbol<unsafe extern "system" fn() -> DWORD> = unsafe {
lib.get(b"GetLastError").unwrap()
};
unsafe {
errhandlingapi::SetLastError(42);
assert_eq!(errhandlingapi::GetLastError(), gle())
}
}
#[test]
fn works_getlasterror0() {
let lib = Library::new("kernel32.dll").unwrap();
let gle: Symbol<unsafe extern "system" fn() -> DWORD> = unsafe {
lib.get(b"GetLastError\0").unwrap()
};
unsafe {
errhandlingapi::SetLastError(42);
assert_eq!(errhandlingapi::GetLastError(), gle())
}
}

Просмотреть файл

@ -1,49 +0,0 @@
//! This is a separate file containing helpers for tests of this library. It is built into a
//! dynamic library by the build.rs script.
#![crate_type="dylib"] // FIXME: should become a cdylib in due time
#![cfg_attr(test_nightly, feature(thread_local))]
#[no_mangle]
pub static mut TEST_STATIC_U32: u32 = 0;
#[no_mangle]
pub static mut TEST_STATIC_PTR: *mut () = 0 as *mut _;
#[cfg(test_nightly)]
#[thread_local]
#[no_mangle]
pub static mut TEST_THREAD_LOCAL: u32 = 0;
#[no_mangle]
pub extern "C" fn test_identity_u32(x: u32) -> u32 {
x
}
#[repr(C)]
pub struct S {
a: u64,
b: u32,
c: u16,
d: u8
}
#[no_mangle]
pub extern "C" fn test_identity_struct(x: S) -> S {
x
}
#[no_mangle]
pub unsafe extern "C" fn test_get_static_u32() -> u32 {
TEST_STATIC_U32
}
#[no_mangle]
pub unsafe extern "C" fn test_check_static_ptr() -> bool {
TEST_STATIC_PTR == (&mut TEST_STATIC_PTR as *mut *mut _ as *mut _)
}
#[cfg(test_nightly)]
#[no_mangle]
pub unsafe extern "C" fn test_get_thread_local() -> u32 {
TEST_THREAD_LOCAL
}

61
third_party/rust/libloading-0.5.2/src/util.rs поставляемый
Просмотреть файл

@ -1,61 +0,0 @@
use std::ffi::{CStr, CString, NulError, FromBytesWithNulError};
use std::borrow::Cow;
use std::os::raw;
#[derive(Debug)]
pub struct NullError;
impl From<NulError> for NullError {
fn from(_: NulError) -> NullError {
NullError
}
}
impl From<FromBytesWithNulError> for NullError {
fn from(_: FromBytesWithNulError) -> NullError {
NullError
}
}
impl From<NullError> for ::std::io::Error {
fn from(e: NullError) -> ::std::io::Error {
::std::io::Error::new(::std::io::ErrorKind::Other, format!("{}", e))
}
}
impl ::std::error::Error for NullError {
fn description(&self) -> &str { "non-final null byte found" }
}
impl ::std::fmt::Display for NullError {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
write!(f, "non-final null byte found")
}
}
/// Checks for last byte and avoids allocating if it is zero.
///
/// Non-last null bytes still result in an error.
pub fn cstr_cow_from_bytes<'a>(slice: &'a [u8]) -> Result<Cow<'a, CStr>, NullError> {
static ZERO: raw::c_char = 0;
Ok(match slice.last() {
// Slice out of 0 elements
None => unsafe { Cow::Borrowed(CStr::from_ptr(&ZERO)) },
// Slice with trailing 0
Some(&0) => Cow::Borrowed(try!(CStr::from_bytes_with_nul(slice))),
// Slice with no trailing 0
Some(_) => Cow::Owned(try!(CString::new(slice))),
})
}
#[inline]
pub fn ensure_compatible_types<T, E>() {
#[cold]
#[inline(never)]
fn dopanic() {
panic!("value of requested type cannot be dynamically loaded");
}
if ::std::mem::size_of::<T>() != ::std::mem::size_of::<E>() {
dopanic()
}
}

Просмотреть файл

@ -1,151 +0,0 @@
extern crate libloading;
use libloading::{Symbol, Library};
const LIBPATH: &'static str = concat!(env!("OUT_DIR"), "/libtest_helpers.dll");
fn make_helpers() {
static ONCE: ::std::sync::Once = ::std::sync::ONCE_INIT;
ONCE.call_once(|| {
let mut outpath = String::from(if let Some(od) = option_env!("OUT_DIR") { od } else { return });
let rustc = option_env!("RUSTC").unwrap_or_else(|| { "rustc".into() });
outpath.push_str(&"/libtest_helpers.dll"); // extension for windows required, POSIX does not care.
let _ = ::std::process::Command::new(rustc)
.arg("src/test_helpers.rs")
.arg("-o")
.arg(outpath)
.arg("-O")
.output()
.expect("could not compile the test helpers!");
});
}
#[test]
fn test_id_u32() {
make_helpers();
let lib = Library::new(LIBPATH).unwrap();
unsafe {
let f: Symbol<unsafe extern fn(u32) -> u32> = lib.get(b"test_identity_u32\0").unwrap();
assert_eq!(42, f(42));
}
}
#[repr(C)]
#[derive(Clone,Copy,PartialEq,Debug)]
struct S {
a: u64,
b: u32,
c: u16,
d: u8
}
#[test]
fn test_id_struct() {
make_helpers();
let lib = Library::new(LIBPATH).unwrap();
unsafe {
let f: Symbol<unsafe extern fn(S) -> S> = lib.get(b"test_identity_struct\0").unwrap();
assert_eq!(S { a: 1, b: 2, c: 3, d: 4 }, f(S { a: 1, b: 2, c: 3, d: 4 }));
}
}
#[test]
fn test_0_no_0() {
make_helpers();
let lib = Library::new(LIBPATH).unwrap();
unsafe {
let f: Symbol<unsafe extern fn(S) -> S> = lib.get(b"test_identity_struct\0").unwrap();
let f2: Symbol<unsafe extern fn(S) -> S> = lib.get(b"test_identity_struct").unwrap();
assert_eq!(*f, *f2);
}
}
#[test]
fn wrong_name_fails() {
Library::new(concat!(env!("OUT_DIR"), "/libtest_help")).err().unwrap();
}
#[test]
fn missing_symbol_fails() {
make_helpers();
let lib = Library::new(LIBPATH).unwrap();
unsafe {
lib.get::<*mut ()>(b"test_does_not_exist").err().unwrap();
lib.get::<*mut ()>(b"test_does_not_exist\0").err().unwrap();
}
}
#[test]
fn interior_null_fails() {
make_helpers();
let lib = Library::new(LIBPATH).unwrap();
unsafe {
lib.get::<*mut ()>(b"test_does\0_not_exist").err().unwrap();
lib.get::<*mut ()>(b"test\0_does_not_exist\0").err().unwrap();
}
}
#[test]
#[should_panic]
fn test_incompatible_type() {
make_helpers();
let lib = Library::new(LIBPATH).unwrap();
unsafe {
let _ = lib.get::<()>(b"test_identity_u32\0");
}
}
#[test]
#[should_panic]
fn test_incompatible_type_named_fn() {
make_helpers();
unsafe fn get<'a, T>(l: &'a Library, _: T) -> libloading::Result<Symbol<'a, T>> {
l.get::<T>(b"test_identity_u32\0")
}
let lib = Library::new(LIBPATH).unwrap();
unsafe {
let _ = get(&lib, test_incompatible_type_named_fn);
}
}
#[test]
fn test_static_u32() {
make_helpers();
let lib = Library::new(LIBPATH).unwrap();
unsafe {
let var: Symbol<*mut u32> = lib.get(b"TEST_STATIC_U32\0").unwrap();
**var = 42;
let help: Symbol<unsafe extern fn() -> u32> = lib.get(b"test_get_static_u32\0").unwrap();
assert_eq!(42, help());
}
}
#[test]
fn test_static_ptr() {
make_helpers();
let lib = Library::new(LIBPATH).unwrap();
unsafe {
let var: Symbol<*mut *mut ()> = lib.get(b"TEST_STATIC_PTR\0").unwrap();
**var = *var as *mut _;
let works: Symbol<unsafe extern fn() -> bool> =
lib.get(b"test_check_static_ptr\0").unwrap();
assert!(works());
}
}
#[cfg(any(windows, target_os="linux"))]
#[cfg(test_nightly)]
#[test]
fn test_tls_static() {
make_helpers();
let lib = Library::new(LIBPATH).unwrap();
unsafe {
let var: Symbol<*mut u32> = lib.get(b"TEST_THREAD_LOCAL\0").unwrap();
**var = 84;
let help: Symbol<unsafe extern fn() -> u32> = lib.get(b"test_get_thread_local\0").unwrap();
assert_eq!(84, help());
}
::std::thread::spawn(move || unsafe {
let help: Symbol<unsafe extern fn() -> u32> = lib.get(b"test_get_thread_local\0").unwrap();
assert_eq!(0, help());
}).join().unwrap();
}

Просмотреть файл

@ -1,79 +0,0 @@
extern crate libloading;
#[cfg(test)]
fn assert_send<T: Send>() {}
#[cfg(test)]
fn assert_sync<T: Sync>() {}
#[test]
fn check_library_send() {
assert_send::<libloading::Library>();
}
#[cfg(unix)]
#[test]
fn check_unix_library_send() {
assert_send::<libloading::os::unix::Library>();
}
#[cfg(windows)]
#[test]
fn check_windows_library_send() {
assert_send::<libloading::os::windows::Library>();
}
#[test]
fn check_library_sync() {
assert_sync::<libloading::Library>();
}
#[cfg(unix)]
#[test]
fn check_unix_library_sync() {
assert_sync::<libloading::os::unix::Library>();
}
#[cfg(windows)]
#[test]
fn check_windows_library_sync() {
assert_sync::<libloading::os::windows::Library>();
}
#[test]
fn check_symbol_send() {
assert_send::<libloading::Symbol<fn() -> ()>>();
// assert_not_send::<libloading::Symbol<*const ()>>();
}
#[cfg(unix)]
#[test]
fn check_unix_symbol_send() {
assert_send::<libloading::os::unix::Symbol<fn() -> ()>>();
// assert_not_send::<libloading::os::unix::Symbol<*const ()>>();
}
#[cfg(windows)]
#[test]
fn check_windows_symbol_send() {
assert_send::<libloading::os::windows::Symbol<fn() -> ()>>();
}
#[test]
fn check_symbol_sync() {
assert_sync::<libloading::Symbol<fn() -> ()>>();
// assert_not_sync::<libloading::Symbol<*const ()>>();
}
#[cfg(unix)]
#[test]
fn check_unix_symbol_sync() {
assert_sync::<libloading::os::unix::Symbol<fn() -> ()>>();
// assert_not_sync::<libloading::os::unix::Symbol<*const ()>>();
}
#[cfg(windows)]
#[test]
fn check_windows_symbol_sync() {
assert_sync::<libloading::os::windows::Symbol<fn() -> ()>>();
// assert_not_sync::<libloading::os::windows::Symbol<*const ()>>();
}

Двоичные данные
third_party/rust/libloading-0.5.2/tests/nagisa32.dll поставляемый

Двоичный файл не отображается.

Двоичные данные
third_party/rust/libloading-0.5.2/tests/nagisa64.dll поставляемый

Двоичный файл не отображается.

Просмотреть файл

@ -1,56 +0,0 @@
#![cfg(windows)]
extern crate libloading;
use libloading::os::windows::*;
use std::ffi::CStr;
// The ordinal DLL contains exactly one function (other than DllMain, that is) with ordinal number
// 1. This function has the sugnature `fn() -> *const c_char` and returns a string "bunny\0" (in
// reference to WindowsBunny).
//
// Both x86_64 and x86 versions of the .dll are functionally the same. Ideally we would compile the
// dlls with well known ordinals from our own testing helpers library, but rustc does not allow
// specifying a custom .def file (https://github.com/rust-lang/rust/issues/35089)
//
// The DLLs were kindly compiled by WindowsBunny (aka. @retep998).
#[cfg(target_arch="x86")]
fn load_ordinal_lib() -> Library {
Library::new("tests/nagisa32.dll").expect("nagisa32.dll")
}
#[cfg(target_arch="x86_64")]
fn load_ordinal_lib() -> Library {
Library::new("tests/nagisa64.dll").expect("nagisa64.dll")
}
#[cfg(any(target_arch="x86", target_arch="x86_64"))]
#[test]
fn test_ordinal() {
let lib = load_ordinal_lib();
unsafe {
let windows: Symbol<unsafe fn() -> *const i8> = lib.get_ordinal(1).expect("function");
assert_eq!(CStr::from_ptr(windows()).to_bytes(), b"bunny");
}
}
#[cfg(any(target_arch="x86", target_arch="x86_64"))]
#[test]
fn test_ordinal_missing_fails() {
let lib = load_ordinal_lib();
unsafe {
let r: Result<Symbol<unsafe fn() -> *const i8>, _> = lib.get_ordinal(2);
r.err().unwrap();
let r: Result<Symbol<unsafe fn() -> *const i8>, _> = lib.get_ordinal(!0);
r.err().unwrap();
}
}
#[test]
fn test_new_kernel23() {
Library::new("kernel23").err().unwrap();
}
#[test]
fn test_new_kernel32_no_ext() {
Library::new("kernel32").unwrap();
}