更新libclamav库1.0.0版本
This commit is contained in:
1
clamav/libclamav_rust/.cargo/vendor/libloading/.cargo-checksum.json
vendored
Normal file
1
clamav/libclamav_rust/.cargo/vendor/libloading/.cargo-checksum.json
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"files":{"Cargo.toml":"30f23c025249e7779afd2a52fdaba7145dd75c2a3e5a0a23f3322261d6b94c59","LICENSE":"b29f8b01452350c20dd1af16ef83b598fea3053578ccc1c7a0ef40e57be2620f","README.mkd":"973a5fa332a8f33abc73ffc0ed509f81c66dbd681d8f50969cac32cdfe16ecb2","src/changelog.rs":"a49ff30e81a245fdcef957a3fffed5a5a5b56825bc51f6ed26fe4c12f75d359c","src/error.rs":"156c53e299e8f1cd4694b277a5d92772a8a9e7ec4004bae067367f4c2502de8b","src/lib.rs":"2eebab93230a59cd87c7884e95c91b3a8736c0a76814dd040864b8c25f0d5f9e","src/os/mod.rs":"6c59ef8c1120953ae6b6c32f27766c643ca90d85075c49c3545d2fe1ed82cedd","src/os/unix/consts.rs":"1418cc26329d01ee6bc9c1144881873a66ac2183c1bf1d589904d569656c80f2","src/os/unix/mod.rs":"dff9590acbbb9a02baea9d2eb870515104c9d519b1896887f3bf1434db442929","src/os/windows/mod.rs":"b14478d7f9d4e8edc8afcbc7aa695ede1ccdd739a94242cb8dbb154fe04e4999","src/safe.rs":"b0dc1cb5c8e0216e365063b5e84218b2377bb7a62714fca9a6215a22a7bc58b8","src/test_helpers.rs":"201403e143e5b3204864124cd38067cf8813d5273dc1a9099288a9dc4bdd15b6","src/util.rs":"0b6dcfb9eafff2d87966460ef6b1b99980f888813037e787ed92deee602f8c2b","tests/constants.rs":"4778c062605ed22238c1bed16de4c076d0857282f090f36e6d985dafb7b4544d","tests/functions.rs":"0cbcc193f8aad71df626aefab9881a76f17c5a4b241855b602ce874018392db7","tests/library_filename.rs":"b1481f0bb374687c5f24e25113426d2a95f08a45fb8bc41a41e8702bd5a7b4bf","tests/markers.rs":"0ebc8f807b92e39452d35732988012cdca7ce96231c57eaac9c3f4217225ad39","tests/nagisa32.dll":"5c69b2bd9c8a6ad04165c221075fc9fade1dd66ca697399ace528a5a62328e36","tests/nagisa64.dll":"e20b95e3036f3289421abd100760874d4f455afd33c3b5b64fec56b191f7d477","tests/windows.rs":"35584a46658b305cd539712d3ba3c21fe7a130fd693aa1389e4886a67625d532"},"package":"b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f"}
|
||||
51
clamav/libclamav_rust/.cargo/vendor/libloading/Cargo.toml
vendored
Normal file
51
clamav/libclamav_rust/.cargo/vendor/libloading/Cargo.toml
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
# 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 are reading this file be aware that the original Cargo.toml
|
||||
# will likely look very different (and much more reasonable).
|
||||
# See Cargo.toml.orig for the original contents.
|
||||
|
||||
[package]
|
||||
rust-version = "1.40.0"
|
||||
name = "libloading"
|
||||
version = "0.7.4"
|
||||
authors = ["Simonas Kazlauskas <libloading@kazlauskas.me>"]
|
||||
description = "Bindings around the platform's dynamic library loading primitives with greatly improved memory safety."
|
||||
documentation = "https://docs.rs/libloading/"
|
||||
readme = "README.mkd"
|
||||
keywords = [
|
||||
"dlopen",
|
||||
"load",
|
||||
"shared",
|
||||
"dylib",
|
||||
]
|
||||
categories = ["api-bindings"]
|
||||
license = "ISC"
|
||||
repository = "https://github.com/nagisa/rust_libloading/"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
all-features = true
|
||||
rustdoc-args = [
|
||||
"--cfg",
|
||||
"libloading_docs",
|
||||
]
|
||||
|
||||
[dev-dependencies.libc]
|
||||
version = "0.2"
|
||||
|
||||
[dev-dependencies.static_assertions]
|
||||
version = "1.1"
|
||||
|
||||
[target."cfg(unix)".dependencies.cfg-if]
|
||||
version = "1"
|
||||
|
||||
[target."cfg(windows)".dependencies.winapi]
|
||||
version = "0.3"
|
||||
features = [
|
||||
"errhandlingapi",
|
||||
"libloaderapi",
|
||||
]
|
||||
12
clamav/libclamav_rust/.cargo/vendor/libloading/LICENSE
vendored
Normal file
12
clamav/libclamav_rust/.cargo/vendor/libloading/LICENSE
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
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.
|
||||
13
clamav/libclamav_rust/.cargo/vendor/libloading/README.mkd
vendored
Normal file
13
clamav/libclamav_rust/.cargo/vendor/libloading/README.mkd
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
# libloading
|
||||
|
||||
Bindings around the platform's dynamic library loading primitives with greatly improved memory safety. The most important safety guarantee of this library is the prevention of dangling `Symbol`s that may occur after a `Library` is unloaded.
|
||||
|
||||
Using this library allows the loading of dynamic libraries, also known as shared libraries, as well as the use of the functions and static variables that these libraries may contain.
|
||||
|
||||
* [Documentation][docs]
|
||||
* [Changelog][changelog]
|
||||
|
||||
[docs]: https://docs.rs/libloading/
|
||||
[changelog]: https://docs.rs/libloading/*/libloading/changelog/index.html
|
||||
|
||||
libloading is available to use under ISC (MIT-like) license.
|
||||
332
clamav/libclamav_rust/.cargo/vendor/libloading/src/changelog.rs
vendored
Normal file
332
clamav/libclamav_rust/.cargo/vendor/libloading/src/changelog.rs
vendored
Normal file
@@ -0,0 +1,332 @@
|
||||
//! The change log.
|
||||
|
||||
/// Release 0.7.4 (2022-11-07)
|
||||
///
|
||||
/// This release has no functional changes.
|
||||
///
|
||||
/// `RTLD_LAZY`, `RTLD_GLOBAL` and `RTLD_LOCAL` constants have been implemented for AIX platforms.
|
||||
pub mod r0_7_4 {}
|
||||
|
||||
/// Release 0.7.3 (2022-01-15)
|
||||
///
|
||||
/// This release has no functional changes.
|
||||
///
|
||||
/// In this release the `docsrs` `cfg` has been renamed to `libloading_docs` to better reflect that
|
||||
/// this `cfg` is intended to be only used by `libloading` and only specifically for the invocation
|
||||
/// of `rustdoc` when documenting `libloading`. Setting this `cfg` in any other situation is
|
||||
/// unsupported and will not work.
|
||||
pub mod r0_7_3 {}
|
||||
|
||||
/// Release 0.7.2 (2021-11-14)
|
||||
///
|
||||
/// Cargo.toml now specifies the MSRV bounds, which enables tooling to report an early failure when
|
||||
/// the version of the toolchain is insufficient. Refer to the [min-rust-version RFC] and its
|
||||
/// [tracking issue].
|
||||
///
|
||||
/// [min-rust-version RFC]: https://rust-lang.github.io/rfcs/2495-min-rust-version.html
|
||||
/// [tracking issue]: https://github.com/rust-lang/rust/issues/65262
|
||||
///
|
||||
/// Additionally, on platforms `libloading` has no support (today: `not(any(unix, windows))`), we
|
||||
/// will no longer attempt to implement the cross-platform `Library` and `Symbol` types. This makes
|
||||
/// `libloading` compile on targets such as `wasm32-unknown-unknown` and gives ability to the
|
||||
/// downstream consumers of this library to decide how they want to handle the absence of the
|
||||
/// library loading implementation in their code. One of such approaches could be depending on
|
||||
/// `libloading` itself optionally as such:
|
||||
///
|
||||
/// ```toml
|
||||
/// [target.'cfg(any(unix, windows))'.dependencies.libloading]
|
||||
/// version = "0.7"
|
||||
/// ```
|
||||
pub mod r0_7_2 {}
|
||||
|
||||
/// Release 0.7.1 (2021-10-09)
|
||||
///
|
||||
/// Significantly improved the consistency and style of the documentation.
|
||||
pub mod r0_7_1 {}
|
||||
|
||||
/// Release 0.7.0 (2021-02-06)
|
||||
///
|
||||
/// ## Breaking changes
|
||||
///
|
||||
/// ### Loading functions are now `unsafe`
|
||||
///
|
||||
/// A number of associated methods involved in loading a library were changed to
|
||||
/// be `unsafe`. The affected functions are: [`Library::new`], [`os::unix::Library::new`],
|
||||
/// [`os::unix::Library::open`], [`os::windows::Library::new`],
|
||||
/// [`os::windows::Library::load_with_flags`]. This is the most prominent breaking change in this
|
||||
/// release and affects majority of the users of `libloading`.
|
||||
///
|
||||
/// In order to see why it was necessary, consider the following snippet of C++ code:
|
||||
///
|
||||
/// ```c++
|
||||
/// #include <vector>
|
||||
/// #include <iostream>
|
||||
///
|
||||
/// static std::vector<unsigned int> UNSHUU = { 1, 2, 3 };
|
||||
///
|
||||
/// int main() {
|
||||
/// std::cout << UNSHUU[0] << UNSHUU[1] << UNSHUU[2] << std::endl; // Prints 123
|
||||
/// return 0;
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// The `std::vector` type, much like in Rust's `Vec`, stores its contents in a buffer allocated on
|
||||
/// the heap. In this example the vector object itself is stored and initialized as a static
|
||||
/// variable – a compile time construct. The heap, on the other hand, is a runtime construct. And
|
||||
/// yet the code works exactly as you'd expect – the vector contains numbers 1, 2 and 3 stored in
|
||||
/// a buffer on heap. So, _what_ makes it work out, exactly?
|
||||
///
|
||||
/// Various executable and shared library formats define conventions and machinery to execute
|
||||
/// arbitrary code when a program or a shared library is loaded. On systems using the PE format
|
||||
/// (e.g. Windows) this is available via the optional `DllMain` initializer. Various systems
|
||||
/// utilizing the ELF format take a sightly different approach of maintaining an array of function
|
||||
/// pointers in the `.init_array` section. A very similar mechanism exists on systems that utilize
|
||||
/// the Mach-O format.
|
||||
///
|
||||
/// For the C++ program above, the object stored in the `UNSHUU` global variable is constructed
|
||||
/// by code run as part of such an initializer routine. This initializer is run before the entry
|
||||
/// point (the `main` function) is executed, allowing for this magical behaviour to be possible.
|
||||
/// Were the C++ code built as a shared library instead, the initialization routines would run as
|
||||
/// the resulting shared library is loaded. In case of `libloading` – during the call to
|
||||
/// `Library::new` and other methods affected by this change.
|
||||
///
|
||||
/// These initialization (and very closely related termination) routines can be utilized outside of
|
||||
/// C++ too. Anybody can build a shared library in variety of different programming languages and
|
||||
/// set up the initializers to execute arbitrary code. Potentially code that does all sorts of
|
||||
/// wildly unsound stuff.
|
||||
///
|
||||
/// The routines are executed by components that are an integral part of the operating system.
|
||||
/// Changing or controlling the operation of these components is infeasible. With that in
|
||||
/// mind, the initializer and termination routines are something anybody loading a library must
|
||||
/// carefully evaluate the libraries loaded for soundness.
|
||||
///
|
||||
/// In practice, a vast majority of the libraries can be considered a good citizen and their
|
||||
/// initialization and termination routines, if they have any at all, can be trusted to be sound.
|
||||
///
|
||||
/// Also see: [issue #86].
|
||||
///
|
||||
/// ### Better & more consistent default behaviour on UNIX systems
|
||||
///
|
||||
/// On UNIX systems the [`Library::new`], [`os::unix::Library::new`] and
|
||||
/// [`os::unix::Library::this`] methods have been changed to use
|
||||
/// <code>[RTLD_LAZY] | [RTLD_LOCAL]</code> as the default set of loader options (previously:
|
||||
/// [`RTLD_NOW`]). This has a couple benefits. Namely:
|
||||
///
|
||||
/// * Lazy binding is generally quicker to execute when only a subset of symbols from a library are
|
||||
/// used and is typically the default when neither `RTLD_LAZY` nor `RTLD_NOW` are specified when
|
||||
/// calling the underlying `dlopen` API;
|
||||
/// * On most UNIX systems (macOS being a notable exception) `RTLD_LOCAL` is the default when
|
||||
/// neither `RTLD_LOCAL` nor [`RTLD_GLOBAL`] are specified. The explicit setting of the
|
||||
/// `RTLD_LOCAL` flag makes this behaviour consistent across platforms.
|
||||
///
|
||||
/// ### Dropped support for Windows XP/Vista
|
||||
///
|
||||
/// The (broken) support for Windows XP and Windows Vista environments was removed. This was
|
||||
/// prompted primarily by a similar policy change in the [Rust
|
||||
/// project](https://github.com/rust-lang/compiler-team/issues/378) but also as an acknowledgement
|
||||
/// to the fact that `libloading` never worked in these environments anyway.
|
||||
///
|
||||
/// ### More accurate error variant names
|
||||
///
|
||||
/// Finally, the `Error::LoadLibraryW` renamed to [`Error::LoadLibraryExW`] to more accurately
|
||||
/// represent the underlying API that's failing. No functional changes as part of this rename
|
||||
/// intended.
|
||||
///
|
||||
/// [issue #86]: https://github.com/nagisa/rust_libloading/issues/86
|
||||
/// [`Library::new`]: crate::Library::new
|
||||
/// [`Error::LoadLibraryExW`]: crate::Error::LoadLibraryExW
|
||||
/// [`os::unix::Library::this`]: crate::os::unix::Library::this
|
||||
/// [`os::unix::Library::new`]: crate::os::unix::Library::new
|
||||
/// [`os::unix::Library::open`]: crate::os::unix::Library::new
|
||||
/// [`os::windows::Library::new`]: crate::os::windows::Library::new
|
||||
/// [`os::windows::Library::load_with_flags`]: crate::os::windows::Library::load_with_flags
|
||||
/// [`RTLD_NOW`]: crate::os::unix::RTLD_NOW
|
||||
/// [RTLD_LAZY]: crate::os::unix::RTLD_LAZY
|
||||
/// [RTLD_LOCAL]: crate::os::unix::RTLD_LOCAL
|
||||
/// [`RTLD_GLOBAL`]: crate::os::unix::RTLD_GLOBAL
|
||||
pub mod r0_7_0 {}
|
||||
|
||||
/// Release 0.6.7 (2021-01-14)
|
||||
///
|
||||
/// * Added a [`os::windows::Library::open_already_loaded`] to obtain a handle to a library that
|
||||
/// must already be loaded. There is no portable equivalent for all UNIX targets. Users who do not
|
||||
/// care about portability across UNIX platforms may use [`os::unix::Library::open`] with
|
||||
/// `libc::RTLD_NOLOAD`;
|
||||
///
|
||||
/// [`os::windows::Library::open_already_loaded`]: crate::os::windows::Library::open_already_loaded
|
||||
/// [`os::unix::Library::open`]: crate::os::unix::Library::open
|
||||
pub mod r0_6_7 {}
|
||||
|
||||
/// Release 0.6.6 (2020-12-03)
|
||||
///
|
||||
/// * Fix a double-release of resources when [`Library::close`] or [`os::windows::Library::close`]
|
||||
/// is used on Windows.
|
||||
///
|
||||
/// [`Library::close`]: crate::Library::close
|
||||
/// [`os::windows::Library::close`]: crate::os::windows::Library::close
|
||||
pub mod r0_6_6 {}
|
||||
|
||||
/// Release 0.6.5 (2020-10-23)
|
||||
///
|
||||
/// * Upgrade cfg-if 0.1 to 1.0
|
||||
pub mod r0_6_5 {}
|
||||
|
||||
/// Release 0.6.4 (2020-10-10)
|
||||
///
|
||||
/// * Remove use of `build.rs` making it easier to build `libloading` without cargo. It also
|
||||
/// almost halves the build time of this crate.
|
||||
pub mod r0_6_4 {}
|
||||
|
||||
/// Release 0.6.3 (2020-08-22)
|
||||
///
|
||||
/// * Improve documentation, allowing to view all of the os-specific functionality from
|
||||
/// documentation generated for any target;
|
||||
/// * Add [`os::windows::Library::this`];
|
||||
/// * Added constants to use with OS-specific `Library::open`;
|
||||
/// * Add [`library_filename`].
|
||||
///
|
||||
/// [`os::windows::Library::this`]: crate::os::windows::Library::this
|
||||
/// [`library_filename`]: crate::library_filename
|
||||
pub mod r0_6_3 {}
|
||||
|
||||
/// Release 0.6.2 (2020-05-06)
|
||||
///
|
||||
/// * Fixed building of this library on Illumos.
|
||||
pub mod r0_6_2 {}
|
||||
|
||||
/// Release 0.6.1 (2020-04-15)
|
||||
///
|
||||
/// * Introduced a new method [`os::windows::Library::load_with_flags`];
|
||||
/// * Added support for the Illumos triple.
|
||||
///
|
||||
/// [`os::windows::Library::load_with_flags`]: crate::os::windows::Library::load_with_flags
|
||||
pub mod r0_6_1 {}
|
||||
|
||||
/// Release 0.6.0 (2020-04-05)
|
||||
///
|
||||
/// * Introduced a new method [`os::unix::Library::get_singlethreaded`];
|
||||
/// * Added (untested) support for building when targeting Redox and Fuchsia;
|
||||
/// * The APIs exposed by this library no longer panic and instead return an `Err` when it used
|
||||
/// to panic.
|
||||
///
|
||||
/// ## Breaking changes
|
||||
///
|
||||
/// * Minimum required (stable) version of Rust to build this library is now 1.40.0;
|
||||
/// * This crate now implements a custom [`Error`] type and all APIs now return this type rather
|
||||
/// than returning the `std::io::Error`;
|
||||
/// * `libloading::Result` has been removed;
|
||||
/// * Removed the dependency on the C compiler to build this library on UNIX-like platforms.
|
||||
/// `libloading` used to utilize a snippet written in C to work-around the unlikely possibility
|
||||
/// of the target having a thread-unsafe implementation of the `dlerror` function. The effect of
|
||||
/// the work-around was very opportunistic: it would not work if the function was called by
|
||||
/// forgoing `libloading`.
|
||||
///
|
||||
/// Starting with 0.6.0, [`Library::get`] on platforms where `dlerror` is not MT-safe (such as
|
||||
/// FreeBSD, DragonflyBSD or NetBSD) will unconditionally return an error when the underlying
|
||||
/// `dlsym` returns a null pointer. For the use-cases where loading null pointers is necessary
|
||||
/// consider using [`os::unix::Library::get_singlethreaded`] instead.
|
||||
///
|
||||
/// [`Library::get`]: crate::Library::get
|
||||
/// [`os::unix::Library::get_singlethreaded`]: crate::os::unix::Library::get_singlethreaded
|
||||
/// [`Error`]: crate::Error
|
||||
pub mod r0_6_0 {}
|
||||
|
||||
/// 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 what’s 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 weren’t forced to be resolved, the library would’ve “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 {}
|
||||
130
clamav/libclamav_rust/.cargo/vendor/libloading/src/error.rs
vendored
Normal file
130
clamav/libclamav_rust/.cargo/vendor/libloading/src/error.rs
vendored
Normal file
@@ -0,0 +1,130 @@
|
||||
use std::ffi::CString;
|
||||
|
||||
/// A `dlerror` error.
|
||||
pub struct DlDescription(pub(crate) CString);
|
||||
|
||||
impl std::fmt::Debug for DlDescription {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
std::fmt::Debug::fmt(&self.0, f)
|
||||
}
|
||||
}
|
||||
|
||||
/// A Windows API error.
|
||||
pub struct WindowsError(pub(crate) std::io::Error);
|
||||
|
||||
impl std::fmt::Debug for WindowsError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
std::fmt::Debug::fmt(&self.0, f)
|
||||
}
|
||||
}
|
||||
|
||||
/// Errors.
|
||||
#[derive(Debug)]
|
||||
#[non_exhaustive]
|
||||
pub enum Error {
|
||||
/// The `dlopen` call failed.
|
||||
DlOpen {
|
||||
/// The source error.
|
||||
desc: DlDescription
|
||||
},
|
||||
/// The `dlopen` call failed and system did not report an error.
|
||||
DlOpenUnknown,
|
||||
/// The `dlsym` call failed.
|
||||
DlSym {
|
||||
/// The source error.
|
||||
desc: DlDescription
|
||||
},
|
||||
/// The `dlsym` call failed and system did not report an error.
|
||||
DlSymUnknown,
|
||||
/// The `dlclose` call failed.
|
||||
DlClose {
|
||||
/// The source error.
|
||||
desc: DlDescription
|
||||
},
|
||||
/// The `dlclose` call failed and system did not report an error.
|
||||
DlCloseUnknown,
|
||||
/// The `LoadLibraryW` call failed.
|
||||
LoadLibraryExW {
|
||||
/// The source error.
|
||||
source: WindowsError
|
||||
},
|
||||
/// The `LoadLibraryW` call failed and system did not report an error.
|
||||
LoadLibraryExWUnknown,
|
||||
/// The `GetModuleHandleExW` call failed.
|
||||
GetModuleHandleExW {
|
||||
/// The source error.
|
||||
source: WindowsError
|
||||
},
|
||||
/// The `GetModuleHandleExW` call failed and system did not report an error.
|
||||
GetModuleHandleExWUnknown,
|
||||
/// The `GetProcAddress` call failed.
|
||||
GetProcAddress {
|
||||
/// The source error.
|
||||
source: WindowsError
|
||||
},
|
||||
/// The `GetProcAddressUnknown` call failed and system did not report an error.
|
||||
GetProcAddressUnknown,
|
||||
/// The `FreeLibrary` call failed.
|
||||
FreeLibrary {
|
||||
/// The source error.
|
||||
source: WindowsError
|
||||
},
|
||||
/// The `FreeLibrary` call failed and system did not report an error.
|
||||
FreeLibraryUnknown,
|
||||
/// The requested type cannot possibly work.
|
||||
IncompatibleSize,
|
||||
/// Could not create a new CString.
|
||||
CreateCString {
|
||||
/// The source error.
|
||||
source: std::ffi::NulError
|
||||
},
|
||||
/// Could not create a new CString from bytes with trailing null.
|
||||
CreateCStringWithTrailing {
|
||||
/// The source error.
|
||||
source: std::ffi::FromBytesWithNulError
|
||||
},
|
||||
}
|
||||
|
||||
impl std::error::Error for Error {
|
||||
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
||||
use Error::*;
|
||||
match *self {
|
||||
CreateCString { ref source } => Some(source),
|
||||
CreateCStringWithTrailing { ref source } => Some(source),
|
||||
LoadLibraryExW { ref source } => Some(&source.0),
|
||||
GetProcAddress { ref source } => Some(&source.0),
|
||||
FreeLibrary { ref source } => Some(&source.0),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for Error {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
use Error::*;
|
||||
match *self {
|
||||
DlOpen { ref desc } => write!(f, "{}", desc.0.to_string_lossy()),
|
||||
DlOpenUnknown => write!(f, "dlopen failed, but system did not report the error"),
|
||||
DlSym { ref desc } => write!(f, "{}", desc.0.to_string_lossy()),
|
||||
DlSymUnknown => write!(f, "dlsym failed, but system did not report the error"),
|
||||
DlClose { ref desc } => write!(f, "{}", desc.0.to_string_lossy()),
|
||||
DlCloseUnknown => write!(f, "dlclose failed, but system did not report the error"),
|
||||
LoadLibraryExW { .. } => write!(f, "LoadLibraryExW failed"),
|
||||
LoadLibraryExWUnknown =>
|
||||
write!(f, "LoadLibraryExW failed, but system did not report the error"),
|
||||
GetModuleHandleExW { .. } => write!(f, "GetModuleHandleExW failed"),
|
||||
GetModuleHandleExWUnknown =>
|
||||
write!(f, "GetModuleHandleExWUnknown failed, but system did not report the error"),
|
||||
GetProcAddress { .. } => write!(f, "GetProcAddress failed"),
|
||||
GetProcAddressUnknown =>
|
||||
write!(f, "GetProcAddress failed, but system did not report the error"),
|
||||
FreeLibrary { .. } => write!(f, "FreeLibrary failed"),
|
||||
FreeLibraryUnknown =>
|
||||
write!(f, "FreeLibrary failed, but system did not report the error"),
|
||||
CreateCString { .. } => write!(f, "could not create a C string from bytes"),
|
||||
CreateCStringWithTrailing { .. } =>
|
||||
write!(f, "could not create a C string from bytes with trailing null"),
|
||||
IncompatibleSize => write!(f, "requested type cannot possibly work"),
|
||||
}
|
||||
}
|
||||
}
|
||||
80
clamav/libclamav_rust/.cargo/vendor/libloading/src/lib.rs
vendored
Normal file
80
clamav/libclamav_rust/.cargo/vendor/libloading/src/lib.rs
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
//! Bindings around the platform's dynamic library loading primitives with greatly improved memory safety.
|
||||
//!
|
||||
//! Using this library allows the loading of [dynamic libraries](struct.Library.html), also known as
|
||||
//! shared libraries, and the use of the functions and static variables they contain.
|
||||
//!
|
||||
//! The `libloading` crate exposes a cross-platform interface to load a library and make use of its
|
||||
//! contents, but little is done to hide the differences in behaviour between platforms.
|
||||
//! The API documentation strives to document such differences as much as possible.
|
||||
//!
|
||||
//! Platform-specific APIs are also available in the [`os`](crate::os) module. These APIs are more
|
||||
//! flexible, but less safe.
|
||||
//!
|
||||
//! # Installation
|
||||
//!
|
||||
//! Add the `libloading` library to your dependencies in `Cargo.toml`:
|
||||
//!
|
||||
//! ```toml
|
||||
//! [dependencies]
|
||||
//! libloading = "0.7"
|
||||
//! ```
|
||||
//!
|
||||
//! # Usage
|
||||
//!
|
||||
//! In your code, run the following:
|
||||
//!
|
||||
//! ```no_run
|
||||
//! fn call_dynamic() -> Result<u32, Box<dyn std::error::Error>> {
|
||||
//! unsafe {
|
||||
//! let lib = libloading::Library::new("/path/to/liblibrary.so")?;
|
||||
//! let func: libloading::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` from which it comes,
|
||||
//! preventing the most common memory-safety issues.
|
||||
#![cfg_attr(any(unix, windows), deny(missing_docs, clippy::all, unreachable_pub, unused))]
|
||||
#![cfg_attr(libloading_docs, feature(doc_cfg))]
|
||||
|
||||
pub mod changelog;
|
||||
pub mod os;
|
||||
mod util;
|
||||
|
||||
mod error;
|
||||
pub use self::error::Error;
|
||||
|
||||
#[cfg(any(unix, windows, libloading_docs))]
|
||||
mod safe;
|
||||
#[cfg(any(unix, windows, libloading_docs))]
|
||||
pub use self::safe::{Library, Symbol};
|
||||
|
||||
use std::env::consts::{DLL_PREFIX, DLL_SUFFIX};
|
||||
use std::ffi::{OsStr, OsString};
|
||||
|
||||
/// Converts a library name to a filename generally appropriate for use on the system.
|
||||
///
|
||||
/// This function will prepend prefixes (such as `lib`) and suffixes (such as `.so`) to the library
|
||||
/// `name` to construct the filename.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// It can be used to load global libraries in a platform independent manner:
|
||||
///
|
||||
/// ```
|
||||
/// use libloading::{Library, library_filename};
|
||||
/// // Will attempt to load `libLLVM.so` on Linux, `libLLVM.dylib` on macOS and `LLVM.dll` on
|
||||
/// // Windows.
|
||||
/// let library = unsafe {
|
||||
/// Library::new(library_filename("LLVM"))
|
||||
/// };
|
||||
/// ```
|
||||
pub fn library_filename<S: AsRef<OsStr>>(name: S) -> OsString {
|
||||
let name = name.as_ref();
|
||||
let mut string = OsString::with_capacity(name.len() + DLL_PREFIX.len() + DLL_SUFFIX.len());
|
||||
string.push(DLL_PREFIX);
|
||||
string.push(name);
|
||||
string.push(DLL_SUFFIX);
|
||||
string
|
||||
}
|
||||
27
clamav/libclamav_rust/.cargo/vendor/libloading/src/os/mod.rs
vendored
Normal file
27
clamav/libclamav_rust/.cargo/vendor/libloading/src/os/mod.rs
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
//! Unsafe but flexible platform-specific bindings to dynamic library loading facilities.
|
||||
//!
|
||||
//! These modules expose more extensive and powerful 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::*;
|
||||
//! ```
|
||||
|
||||
/// UNIX implementation of dynamic library loading.
|
||||
#[cfg(any(unix, libloading_docs))]
|
||||
#[cfg_attr(libloading_docs, doc(cfg(unix)))]
|
||||
pub mod unix;
|
||||
|
||||
/// Windows implementation of dynamic library loading.
|
||||
#[cfg(any(windows, libloading_docs))]
|
||||
#[cfg_attr(libloading_docs, doc(cfg(windows)))]
|
||||
pub mod windows;
|
||||
237
clamav/libclamav_rust/.cargo/vendor/libloading/src/os/unix/consts.rs
vendored
Normal file
237
clamav/libclamav_rust/.cargo/vendor/libloading/src/os/unix/consts.rs
vendored
Normal file
@@ -0,0 +1,237 @@
|
||||
use std::os::raw::c_int;
|
||||
|
||||
/// Perform lazy binding.
|
||||
///
|
||||
/// Relocations shall be performed at an implementation-defined time, ranging from the time
|
||||
/// of the [`Library::open`] call until the first reference to a given symbol occurs.
|
||||
/// Specifying `RTLD_LAZY` should improve performance on implementations supporting dynamic
|
||||
/// symbol binding since a process might not reference all of the symbols in an executable
|
||||
/// object file. And, for systems supporting dynamic symbol resolution for normal process
|
||||
/// execution, this behaviour mimics the normal handling of process execution.
|
||||
///
|
||||
/// Conflicts with [`RTLD_NOW`].
|
||||
///
|
||||
/// [`Library::open`]: crate::os::unix::Library::open
|
||||
pub const RTLD_LAZY: c_int = posix::RTLD_LAZY;
|
||||
|
||||
/// Perform eager binding.
|
||||
///
|
||||
/// All necessary relocations shall be performed when the executable object file is first
|
||||
/// loaded. This may waste some processing if relocations are performed for symbols
|
||||
/// that are never referenced. This behaviour may be useful for applications that need to
|
||||
/// know that all symbols referenced during execution will be available before
|
||||
/// [`Library::open`] returns.
|
||||
///
|
||||
/// Conflicts with [`RTLD_LAZY`].
|
||||
///
|
||||
/// [`Library::open`]: crate::os::unix::Library::open
|
||||
pub const RTLD_NOW: c_int = posix::RTLD_NOW;
|
||||
|
||||
/// Make loaded symbols available for resolution globally.
|
||||
///
|
||||
/// The executable object file's symbols shall be made available for relocation processing of any
|
||||
/// other executable object file. In addition, calls to [`Library::get`] on `Library` obtained from
|
||||
/// [`Library::this`] allows executable object files loaded with this mode to be searched.
|
||||
///
|
||||
/// [`Library::this`]: crate::os::unix::Library::this
|
||||
/// [`Library::get`]: crate::os::unix::Library::get
|
||||
pub const RTLD_GLOBAL: c_int = posix::RTLD_GLOBAL;
|
||||
|
||||
/// Load symbols into an isolated namespace.
|
||||
///
|
||||
/// The executable object file's symbols shall not be made available for relocation processing of
|
||||
/// any other executable object file. This mode of operation is most appropriate for e.g. plugins.
|
||||
pub const RTLD_LOCAL: c_int = posix::RTLD_LOCAL;
|
||||
|
||||
#[cfg(all(libloading_docs, not(unix)))]
|
||||
mod posix {
|
||||
use super::c_int;
|
||||
pub(super) const RTLD_LAZY: c_int = !0;
|
||||
pub(super) const RTLD_NOW: c_int = !0;
|
||||
pub(super) const RTLD_GLOBAL: c_int = !0;
|
||||
pub(super) const RTLD_LOCAL: c_int = !0;
|
||||
}
|
||||
|
||||
#[cfg(any(not(libloading_docs), unix))]
|
||||
mod posix {
|
||||
extern crate cfg_if;
|
||||
use self::cfg_if::cfg_if;
|
||||
use super::c_int;
|
||||
cfg_if! {
|
||||
if #[cfg(target_os = "haiku")] {
|
||||
pub(super) const RTLD_LAZY: c_int = 0;
|
||||
} else if #[cfg(target_os = "aix")] {
|
||||
pub(super) const RTLD_LAZY: c_int = 4;
|
||||
} else if #[cfg(any(
|
||||
target_os = "linux",
|
||||
target_os = "android",
|
||||
target_os = "emscripten",
|
||||
|
||||
target_os = "macos",
|
||||
target_os = "ios",
|
||||
target_os = "freebsd",
|
||||
target_os = "dragonfly",
|
||||
target_os = "openbsd",
|
||||
target_os = "netbsd",
|
||||
|
||||
target_os = "solaris",
|
||||
target_os = "illumos",
|
||||
|
||||
target_env = "uclibc",
|
||||
target_env = "newlib",
|
||||
|
||||
target_os = "fuchsia",
|
||||
target_os = "redox",
|
||||
))] {
|
||||
pub(super) const RTLD_LAZY: c_int = 1;
|
||||
} else {
|
||||
compile_error!(
|
||||
"Target has no known `RTLD_LAZY` value. Please submit an issue or PR adding it."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(target_os = "haiku")] {
|
||||
pub(super) const RTLD_NOW: c_int = 1;
|
||||
} else if #[cfg(any(
|
||||
target_os = "linux",
|
||||
all(target_os = "android", target_pointer_width = "64"),
|
||||
target_os = "emscripten",
|
||||
|
||||
target_os = "macos",
|
||||
target_os = "ios",
|
||||
target_os = "freebsd",
|
||||
target_os = "dragonfly",
|
||||
target_os = "openbsd",
|
||||
target_os = "netbsd",
|
||||
|
||||
target_os = "aix",
|
||||
target_os = "solaris",
|
||||
target_os = "illumos",
|
||||
|
||||
target_env = "uclibc",
|
||||
target_env = "newlib",
|
||||
|
||||
target_os = "fuchsia",
|
||||
target_os = "redox",
|
||||
))] {
|
||||
pub(super) const RTLD_NOW: c_int = 2;
|
||||
} else if #[cfg(all(target_os = "android",target_pointer_width = "32"))] {
|
||||
pub(super) const RTLD_NOW: c_int = 0;
|
||||
} else {
|
||||
compile_error!(
|
||||
"Target has no known `RTLD_NOW` value. Please submit an issue or PR adding it."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(any(
|
||||
target_os = "haiku",
|
||||
all(target_os = "android",target_pointer_width = "32"),
|
||||
))] {
|
||||
pub(super) const RTLD_GLOBAL: c_int = 2;
|
||||
} else if #[cfg(target_os = "aix")] {
|
||||
pub(super) const RTLD_GLOBAL: c_int = 0x10000;
|
||||
} else if #[cfg(any(
|
||||
target_env = "uclibc",
|
||||
all(target_os = "linux", target_arch = "mips"),
|
||||
all(target_os = "linux", target_arch = "mips64"),
|
||||
))] {
|
||||
pub(super) const RTLD_GLOBAL: c_int = 4;
|
||||
} else if #[cfg(any(
|
||||
target_os = "macos",
|
||||
target_os = "ios",
|
||||
))] {
|
||||
pub(super) const RTLD_GLOBAL: c_int = 8;
|
||||
} else if #[cfg(any(
|
||||
target_os = "linux",
|
||||
all(target_os = "android", target_pointer_width = "64"),
|
||||
target_os = "emscripten",
|
||||
|
||||
target_os = "freebsd",
|
||||
target_os = "dragonfly",
|
||||
target_os = "openbsd",
|
||||
target_os = "netbsd",
|
||||
|
||||
target_os = "solaris",
|
||||
target_os = "illumos",
|
||||
|
||||
target_env = "newlib",
|
||||
|
||||
target_os = "fuchsia",
|
||||
target_os = "redox",
|
||||
))] {
|
||||
pub(super) const RTLD_GLOBAL: c_int = 0x100;
|
||||
} else {
|
||||
compile_error!(
|
||||
"Target has no known `RTLD_GLOBAL` value. Please submit an issue or PR adding it."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(target_os = "netbsd")] {
|
||||
pub(super) const RTLD_LOCAL: c_int = 0x200;
|
||||
} else if #[cfg(target_os = "aix")] {
|
||||
pub(super) const RTLD_LOCAL: c_int = 0x80000;
|
||||
} else if #[cfg(any(
|
||||
target_os = "macos",
|
||||
target_os = "ios",
|
||||
))] {
|
||||
pub(super) const RTLD_LOCAL: c_int = 4;
|
||||
} else if #[cfg(any(
|
||||
target_os = "linux",
|
||||
target_os = "android",
|
||||
target_os = "emscripten",
|
||||
|
||||
target_os = "freebsd",
|
||||
target_os = "dragonfly",
|
||||
target_os = "openbsd",
|
||||
|
||||
target_os = "haiku",
|
||||
|
||||
target_os = "solaris",
|
||||
target_os = "illumos",
|
||||
|
||||
target_env = "uclibc",
|
||||
target_env = "newlib",
|
||||
|
||||
target_os = "fuchsia",
|
||||
target_os = "redox",
|
||||
))] {
|
||||
pub(super) const RTLD_LOCAL: c_int = 0;
|
||||
} else {
|
||||
compile_error!(
|
||||
"Target has no known `RTLD_LOCAL` value. Please submit an issue or PR adding it."
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Other constants that exist but are not bound because they are platform-specific (non-posix)
|
||||
// extensions. Some of these constants are only relevant to `dlsym` or `dlmopen` calls.
|
||||
//
|
||||
// RTLD_CONFGEN
|
||||
// RTLD_DEFAULT
|
||||
// RTLD_DI_CONFIGADDR
|
||||
// RTLD_DI_LINKMAP
|
||||
// RTLD_DI_LMID
|
||||
// RTLD_DI_ORIGIN
|
||||
// RTLD_DI_PROFILENAME
|
||||
// RTLD_DI_PROFILEOUT
|
||||
// RTLD_DI_SERINFO
|
||||
// RTLD_DI_SERINFOSIZE
|
||||
// RTLD_DI_TLS_DATA
|
||||
// RTLD_DI_TLS_MODID
|
||||
// RTLD_FIRST
|
||||
// RTLD_GROUP
|
||||
// RTLD_NEXT
|
||||
// RTLD_PARENT
|
||||
// RTLD_PROBE
|
||||
// RTLD_SELF
|
||||
// RTLD_WORLD
|
||||
// RTLD_NODELETE
|
||||
// RTLD_NOLOAD
|
||||
// RTLD_DEEPBIND
|
||||
444
clamav/libclamav_rust/.cargo/vendor/libloading/src/os/unix/mod.rs
vendored
Normal file
444
clamav/libclamav_rust/.cargo/vendor/libloading/src/os/unix/mod.rs
vendored
Normal file
@@ -0,0 +1,444 @@
|
||||
// A hack for docs.rs to build documentation that has both windows and linux documentation in the
|
||||
// same rustdoc build visible.
|
||||
#[cfg(all(libloading_docs, not(unix)))]
|
||||
mod unix_imports {}
|
||||
#[cfg(any(not(libloading_docs), unix))]
|
||||
mod unix_imports {
|
||||
pub(super) use std::os::unix::ffi::OsStrExt;
|
||||
}
|
||||
|
||||
pub use self::consts::*;
|
||||
use self::unix_imports::*;
|
||||
use std::ffi::{CStr, OsStr};
|
||||
use std::os::raw;
|
||||
use std::{fmt, marker, mem, ptr};
|
||||
use util::{cstr_cow_from_bytes, ensure_compatible_types};
|
||||
|
||||
mod consts;
|
||||
|
||||
// dl* family of functions did not have enough thought put into it.
|
||||
//
|
||||
// Whole error handling scheme is done via setting and querying some global state, therefore it is
|
||||
// not safe to use dynamic library loading in MT-capable environment at all. Only in POSIX 2008+TC1
|
||||
// a thread-local state was allowed for `dlerror`, making the dl* family of functions MT-safe.
|
||||
//
|
||||
// In practice (as of 2020-04-01) most of the widely used targets use a thread-local for error
|
||||
// state and have been doing so for a long time. Regardless the comments in this function shall
|
||||
// remain as a documentation for the future generations.
|
||||
fn with_dlerror<T, F>(wrap: fn(crate::error::DlDescription) -> crate::Error, closure: F)
|
||||
-> Result<T, Option<crate::Error>>
|
||||
where F: FnOnce() -> Option<T> {
|
||||
// We used to guard all uses of dl* functions with our own mutex. This made them safe to use in
|
||||
// MT programs provided the only way a program used dl* was via this library. However, it also
|
||||
// had a number of downsides or cases where it failed to handle the problems. For instance,
|
||||
// if any other library called `dlerror` internally concurrently with `libloading` things would
|
||||
// still go awry.
|
||||
//
|
||||
// On platforms where `dlerror` is still MT-unsafe, `dlsym` (`Library::get`) can spuriously
|
||||
// succeed and return a null pointer for a symbol when the actual symbol look-up operation
|
||||
// fails. Instances where the actual symbol _could_ be `NULL` are platform specific. For
|
||||
// instance on GNU glibc based-systems (an excerpt from dlsym(3)):
|
||||
//
|
||||
// > The value of a symbol returned by dlsym() will never be NULL if the shared object is the
|
||||
// > result of normal compilation, since a global symbol is never placed at the NULL
|
||||
// > address. There are nevertheless cases where a lookup using dlsym() may return NULL as the
|
||||
// > value of a symbol. For example, the symbol value may be the result of a GNU indirect
|
||||
// > function (IFUNC) resolver function that returns NULL as the resolved value.
|
||||
|
||||
// While we could could call `dlerror` here to clear the previous error value, only the `dlsym`
|
||||
// call 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 a bug in implementation of dl* family of functions.
|
||||
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 there’re bugs in our bindings or there’s
|
||||
// non-libloading user of libdl; possibly in another thread.
|
||||
None
|
||||
} else {
|
||||
// You can’t even rely on error string being static here; call to subsequent dlerror
|
||||
// may invalidate or overwrite the error message. Why couldn’t they simply give up the
|
||||
// ownership over the message?
|
||||
// TODO: should do locale-aware conversion here. OTOH Rust doesn’t seem to work well in
|
||||
// any system that uses non-utf8 locale, so I doubt there’s a problem here.
|
||||
let message = CStr::from_ptr(error).into();
|
||||
Some(wrap(crate::error::DlDescription(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 counterpart of the cross-platform [`Library`](crate::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 eagerly load a shared library (module).
|
||||
///
|
||||
/// If the `filename` contains a [path separator], the `filename` is interpreted as a `path` to
|
||||
/// a file. Otherwise, platform-specific algorithms are employed to find a library with a
|
||||
/// matching file name.
|
||||
///
|
||||
/// This is equivalent to <code>[Library::open](filename, [RTLD_LAZY] | [RTLD_LOCAL])</code>.
|
||||
///
|
||||
/// [path separator]: std::path::MAIN_SEPARATOR
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// When a library is loaded, initialisation routines contained within the library are executed.
|
||||
/// For the purposes of safety, the execution of these routines is conceptually the same calling an
|
||||
/// unknown foreign function and may impose arbitrary requirements on the caller for the call
|
||||
/// to be sound.
|
||||
///
|
||||
/// Additionally, the callers of this function must also ensure that execution of the
|
||||
/// termination routines contained within the library is safe as well. These routines may be
|
||||
/// executed when the library is unloaded.
|
||||
#[inline]
|
||||
pub unsafe fn new<P: AsRef<OsStr>>(filename: P) -> Result<Library, crate::Error> {
|
||||
Library::open(Some(filename), RTLD_LAZY | RTLD_LOCAL)
|
||||
}
|
||||
|
||||
/// Load the `Library` representing the current executable.
|
||||
///
|
||||
/// [`Library::get`] calls of the returned `Library` will look for symbols in following
|
||||
/// locations in order:
|
||||
///
|
||||
/// 1. The original program image;
|
||||
/// 2. Any executable object files (e.g. shared libraries) loaded at program startup;
|
||||
/// 3. Any executable object files loaded at runtime (e.g. via other `Library::new` calls or via
|
||||
/// calls to the `dlopen` function).
|
||||
///
|
||||
/// Note that the behaviour of a `Library` loaded with this method is different from that of
|
||||
/// Libraries loaded with [`os::windows::Library::this`].
|
||||
///
|
||||
/// This is equivalent to <code>[Library::open](None, [RTLD_LAZY] | [RTLD_LOCAL])</code>.
|
||||
///
|
||||
/// [`os::windows::Library::this`]: crate::os::windows::Library::this
|
||||
#[inline]
|
||||
pub fn this() -> Library {
|
||||
unsafe {
|
||||
// SAFE: this does not load any new shared library images, no danger in it executing
|
||||
// initialiser routines.
|
||||
Library::open(None::<&OsStr>, RTLD_LAZY | RTLD_LOCAL).expect("this should never fail")
|
||||
}
|
||||
}
|
||||
|
||||
/// Find and load an executable object file (shared library).
|
||||
///
|
||||
/// See documentation for [`Library::this`] for further description of the behaviour
|
||||
/// when the `filename` is `None`. Otherwise see [`Library::new`].
|
||||
///
|
||||
/// Corresponds to `dlopen(filename, flags)`.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// When a library is loaded, initialisation routines contained within the library are executed.
|
||||
/// For the purposes of safety, the execution of these routines is conceptually the same calling an
|
||||
/// unknown foreign function and may impose arbitrary requirements on the caller for the call
|
||||
/// to be sound.
|
||||
///
|
||||
/// Additionally, the callers of this function must also ensure that execution of the
|
||||
/// termination routines contained within the library is safe as well. These routines may be
|
||||
/// executed when the library is unloaded.
|
||||
pub unsafe fn open<P>(filename: Option<P>, flags: raw::c_int) -> Result<Library, crate::Error>
|
||||
where P: AsRef<OsStr> {
|
||||
let filename = match filename {
|
||||
None => None,
|
||||
Some(ref f) => Some(cstr_cow_from_bytes(f.as_ref().as_bytes())?),
|
||||
};
|
||||
with_dlerror(|desc| crate::Error::DlOpen { desc }, move || {
|
||||
let result = dlopen(match filename {
|
||||
None => ptr::null(),
|
||||
Some(ref f) => f.as_ptr()
|
||||
}, flags);
|
||||
// ensure filename lives until dlopen completes
|
||||
drop(filename);
|
||||
if result.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(Library {
|
||||
handle: result
|
||||
})
|
||||
}
|
||||
}).map_err(|e| e.unwrap_or(crate::Error::DlOpenUnknown))
|
||||
}
|
||||
|
||||
unsafe fn get_impl<T, F>(&self, symbol: &[u8], on_null: F) -> Result<Symbol<T>, crate::Error>
|
||||
where F: FnOnce() -> Result<Symbol<T>, crate::Error>
|
||||
{
|
||||
ensure_compatible_types::<T, *mut raw::c_void>()?;
|
||||
let symbol = 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 can’t exactly
|
||||
// fully prevent it.
|
||||
match with_dlerror(|desc| crate::Error::DlSym { desc }, || {
|
||||
dlerror();
|
||||
let symbol = dlsym(self.handle, symbol.as_ptr());
|
||||
if symbol.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(Symbol {
|
||||
pointer: symbol,
|
||||
pd: marker::PhantomData
|
||||
})
|
||||
}
|
||||
}) {
|
||||
Err(None) => on_null(),
|
||||
Err(Some(e)) => Err(e),
|
||||
Ok(x) => Ok(x)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// Get a pointer to a function or static variable by symbol name.
|
||||
///
|
||||
/// The `symbol` may not contain any null bytes, with the exception of the last byte. Providing a
|
||||
/// null terminated `symbol` may help to avoid an allocation.
|
||||
///
|
||||
/// Symbol is interpreted as-is; no mangling is done. This means that symbols like `x::y` are
|
||||
/// most likely invalid.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Users of this API must specify the correct type of the function or variable loaded. Using a
|
||||
/// `Symbol` with a wrong type is undefined.
|
||||
///
|
||||
/// # Platform-specific behaviour
|
||||
///
|
||||
/// Implementation of thread local variables is extremely platform specific and uses of such
|
||||
/// variables that work on e.g. Linux may have unintended behaviour on other targets.
|
||||
///
|
||||
/// On POSIX implementations where the `dlerror` function is not confirmed to be MT-safe (such
|
||||
/// as FreeBSD), this function will unconditionally return an error when the underlying `dlsym`
|
||||
/// call returns a null pointer. There are rare situations where `dlsym` returns a genuine null
|
||||
/// pointer without it being an error. If loading a null pointer is something you care about,
|
||||
/// consider using the [`Library::get_singlethreaded`] call.
|
||||
#[inline(always)]
|
||||
pub unsafe fn get<T>(&self, symbol: &[u8]) -> Result<Symbol<T>, crate::Error> {
|
||||
extern crate cfg_if;
|
||||
cfg_if::cfg_if! {
|
||||
// These targets are known to have MT-safe `dlerror`.
|
||||
if #[cfg(any(
|
||||
target_os = "linux",
|
||||
target_os = "android",
|
||||
target_os = "openbsd",
|
||||
target_os = "macos",
|
||||
target_os = "ios",
|
||||
target_os = "solaris",
|
||||
target_os = "illumos",
|
||||
target_os = "redox",
|
||||
target_os = "fuchsia"
|
||||
))] {
|
||||
self.get_singlethreaded(symbol)
|
||||
} else {
|
||||
self.get_impl(symbol, || Err(crate::Error::DlSymUnknown))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Get a pointer to function or static variable by symbol name.
|
||||
///
|
||||
/// The `symbol` may not contain any null bytes, with the exception of the last byte. Providing a
|
||||
/// null terminated `symbol` may help to avoid an allocation.
|
||||
///
|
||||
/// Symbol is interpreted as-is; no mangling is done. This means that symbols like `x::y` are
|
||||
/// most likely invalid.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Users of this API must specify the correct type of the function or variable loaded.
|
||||
///
|
||||
/// It is up to the user of this library to ensure that no other calls to an MT-unsafe
|
||||
/// implementation of `dlerror` occur during the execution of this function. Failing that, the
|
||||
/// behaviour of this function is not defined.
|
||||
///
|
||||
/// # Platform-specific behaviour
|
||||
///
|
||||
/// The implementation of thread-local variables is extremely platform specific and uses of such
|
||||
/// variables that work on e.g. Linux may have unintended behaviour on other targets.
|
||||
#[inline(always)]
|
||||
pub unsafe fn get_singlethreaded<T>(&self, symbol: &[u8]) -> Result<Symbol<T>, crate::Error> {
|
||||
self.get_impl(symbol, || Ok(Symbol {
|
||||
pointer: ptr::null_mut(),
|
||||
pd: marker::PhantomData
|
||||
}))
|
||||
}
|
||||
|
||||
/// 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`.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// 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
|
||||
}
|
||||
}
|
||||
|
||||
/// Unload the library.
|
||||
///
|
||||
/// This method might be a no-op, depending on the flags with which the `Library` was opened,
|
||||
/// what library was opened or other platform specifics.
|
||||
///
|
||||
/// You only need to call this if you are interested in handling any errors that may arise when
|
||||
/// library is unloaded. Otherwise the implementation of `Drop` for `Library` will close the
|
||||
/// library and ignore the errors were they arise.
|
||||
///
|
||||
/// The underlying data structures may still get leaked if an error does occur.
|
||||
pub fn close(self) -> Result<(), crate::Error> {
|
||||
let result = with_dlerror(|desc| crate::Error::DlClose { desc }, || {
|
||||
if unsafe { dlclose(self.handle) } == 0 {
|
||||
Some(())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}).map_err(|e| e.unwrap_or(crate::Error::DlCloseUnknown));
|
||||
// While the library is not free'd yet in case of an error, there is no reason to try
|
||||
// dropping it again, because all that will do is try calling `dlclose` again. only
|
||||
// this time it would ignore the return result, which we already seen failing…
|
||||
std::mem::forget(self);
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Library {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
dlclose(self.handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 that the
|
||||
/// `Symbol` does not outlive the `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 {
|
||||
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.
|
||||
&*(&self.pointer as *const *mut _ as *const T)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> fmt::Debug for Symbol<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
unsafe {
|
||||
let mut info = mem::MaybeUninit::<DlInfo>::uninit();
|
||||
if dladdr(self.pointer, info.as_mut_ptr()) != 0 {
|
||||
let info = info.assume_init();
|
||||
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
|
||||
#[cfg_attr(any(target_os = "linux", target_os = "android"), link(name="dl"))]
|
||||
#[cfg_attr(any(target_os = "freebsd", target_os = "dragonfly"), link(name="c"))]
|
||||
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;
|
||||
}
|
||||
|
||||
#[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
|
||||
}
|
||||
532
clamav/libclamav_rust/.cargo/vendor/libloading/src/os/windows/mod.rs
vendored
Normal file
532
clamav/libclamav_rust/.cargo/vendor/libloading/src/os/windows/mod.rs
vendored
Normal file
@@ -0,0 +1,532 @@
|
||||
// A hack for docs.rs to build documentation that has both windows and linux documentation in the
|
||||
// same rustdoc build visible.
|
||||
#[cfg(all(libloading_docs, not(windows)))]
|
||||
mod windows_imports {
|
||||
pub(super) enum WORD {}
|
||||
pub(super) struct DWORD;
|
||||
pub(super) enum HMODULE {}
|
||||
pub(super) enum FARPROC {}
|
||||
|
||||
pub(super) mod consts {
|
||||
use super::DWORD;
|
||||
pub(crate) const LOAD_IGNORE_CODE_AUTHZ_LEVEL: DWORD = DWORD;
|
||||
pub(crate) const LOAD_LIBRARY_AS_DATAFILE: DWORD = DWORD;
|
||||
pub(crate) const LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE: DWORD = DWORD;
|
||||
pub(crate) const LOAD_LIBRARY_AS_IMAGE_RESOURCE: DWORD = DWORD;
|
||||
pub(crate) const LOAD_LIBRARY_SEARCH_APPLICATION_DIR: DWORD = DWORD;
|
||||
pub(crate) const LOAD_LIBRARY_SEARCH_DEFAULT_DIRS: DWORD = DWORD;
|
||||
pub(crate) const LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR: DWORD = DWORD;
|
||||
pub(crate) const LOAD_LIBRARY_SEARCH_SYSTEM32: DWORD = DWORD;
|
||||
pub(crate) const LOAD_LIBRARY_SEARCH_USER_DIRS: DWORD = DWORD;
|
||||
pub(crate) const LOAD_WITH_ALTERED_SEARCH_PATH: DWORD = DWORD;
|
||||
pub(crate) const LOAD_LIBRARY_REQUIRE_SIGNED_TARGET: DWORD = DWORD;
|
||||
pub(crate) const LOAD_LIBRARY_SAFE_CURRENT_DIRS: DWORD = DWORD;
|
||||
}
|
||||
}
|
||||
#[cfg(any(not(libloading_docs), windows))]
|
||||
mod windows_imports {
|
||||
extern crate winapi;
|
||||
pub(super) use self::winapi::shared::minwindef::{WORD, DWORD, HMODULE, FARPROC};
|
||||
pub(super) use self::winapi::shared::ntdef::WCHAR;
|
||||
pub(super) use self::winapi::um::{errhandlingapi, libloaderapi};
|
||||
pub(super) use std::os::windows::ffi::{OsStrExt, OsStringExt};
|
||||
pub(super) const SEM_FAILCE: DWORD = 1;
|
||||
|
||||
pub(super) mod consts {
|
||||
pub(crate) use super::winapi::um::libloaderapi::{
|
||||
LOAD_IGNORE_CODE_AUTHZ_LEVEL,
|
||||
LOAD_LIBRARY_AS_DATAFILE,
|
||||
LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE,
|
||||
LOAD_LIBRARY_AS_IMAGE_RESOURCE,
|
||||
LOAD_LIBRARY_SEARCH_APPLICATION_DIR,
|
||||
LOAD_LIBRARY_SEARCH_DEFAULT_DIRS,
|
||||
LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR,
|
||||
LOAD_LIBRARY_SEARCH_SYSTEM32,
|
||||
LOAD_LIBRARY_SEARCH_USER_DIRS,
|
||||
LOAD_WITH_ALTERED_SEARCH_PATH,
|
||||
LOAD_LIBRARY_REQUIRE_SIGNED_TARGET,
|
||||
LOAD_LIBRARY_SAFE_CURRENT_DIRS,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
use self::windows_imports::*;
|
||||
use util::{ensure_compatible_types, cstr_cow_from_bytes};
|
||||
use std::ffi::{OsStr, OsString};
|
||||
use std::{fmt, io, marker, mem, ptr};
|
||||
|
||||
/// The platform-specific counterpart of the cross-platform [`Library`](crate::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, couldn’t
|
||||
// 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 of 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 filed at https://connect.microsoft.com/ against Windows Server)
|
||||
unsafe impl Sync for Library {}
|
||||
|
||||
impl Library {
|
||||
/// Find and load a module.
|
||||
///
|
||||
/// If the `filename` specifies a full path, the function only searches that path for the
|
||||
/// module. Otherwise, if the `filename` specifies a relative path or a module name without a
|
||||
/// path, the function uses a Windows-specific search strategy to find the module. For more
|
||||
/// information, see the [Remarks on MSDN][msdn].
|
||||
///
|
||||
/// If the `filename` specifies a library filename without a path and with the extension omitted,
|
||||
/// the `.dll` extension is implicitly added. This behaviour may be suppressed by appending a
|
||||
/// trailing `.` to the `filename`.
|
||||
///
|
||||
/// This is equivalent to <code>[Library::load_with_flags](filename, 0)</code>.
|
||||
///
|
||||
/// [msdn]: https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryw#remarks
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// When a library is loaded, initialisation routines contained within the library are executed.
|
||||
/// For the purposes of safety, the execution of these routines is conceptually the same calling an
|
||||
/// unknown foreign function and may impose arbitrary requirements on the caller for the call
|
||||
/// to be sound.
|
||||
///
|
||||
/// Additionally, the callers of this function must also ensure that execution of the
|
||||
/// termination routines contained within the library is safe as well. These routines may be
|
||||
/// executed when the library is unloaded.
|
||||
#[inline]
|
||||
pub unsafe fn new<P: AsRef<OsStr>>(filename: P) -> Result<Library, crate::Error> {
|
||||
Library::load_with_flags(filename, 0)
|
||||
}
|
||||
|
||||
/// Get the `Library` representing the original program executable.
|
||||
///
|
||||
/// Note that the behaviour of the `Library` loaded with this method is different from
|
||||
/// Libraries loaded with [`os::unix::Library::this`]. For more information refer to [MSDN].
|
||||
///
|
||||
/// Corresponds to `GetModuleHandleExW(0, NULL, _)`.
|
||||
///
|
||||
/// [`os::unix::Library::this`]: crate::os::unix::Library::this
|
||||
/// [MSDN]: https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getmodulehandleexw
|
||||
pub fn this() -> Result<Library, crate::Error> {
|
||||
unsafe {
|
||||
let mut handle: HMODULE = std::ptr::null_mut();
|
||||
with_get_last_error(|source| crate::Error::GetModuleHandleExW { source }, || {
|
||||
let result = libloaderapi::GetModuleHandleExW(0, std::ptr::null_mut(), &mut handle);
|
||||
if result == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(Library(handle))
|
||||
}
|
||||
}).map_err(|e| e.unwrap_or(crate::Error::GetModuleHandleExWUnknown))
|
||||
}
|
||||
}
|
||||
|
||||
/// Get a module that is already loaded by the program.
|
||||
///
|
||||
/// This function returns a `Library` corresponding to a module with the given name that is
|
||||
/// already mapped into the address space of the process. If the module isn't found, an error is
|
||||
/// returned.
|
||||
///
|
||||
/// If the `filename` does not include a full path and there are multiple different loaded
|
||||
/// modules corresponding to the `filename`, it is impossible to predict which module handle
|
||||
/// will be returned. For more information refer to [MSDN].
|
||||
///
|
||||
/// If the `filename` specifies a library filename without a path and with the extension omitted,
|
||||
/// the `.dll` extension is implicitly added. This behaviour may be suppressed by appending a
|
||||
/// trailing `.` to the `filename`.
|
||||
///
|
||||
/// This is equivalent to `GetModuleHandleExW(0, filename, _)`.
|
||||
///
|
||||
/// [MSDN]: https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getmodulehandleexw
|
||||
pub fn open_already_loaded<P: AsRef<OsStr>>(filename: P) -> Result<Library, crate::Error> {
|
||||
let wide_filename: Vec<u16> = filename.as_ref().encode_wide().chain(Some(0)).collect();
|
||||
|
||||
let ret = unsafe {
|
||||
let mut handle: HMODULE = std::ptr::null_mut();
|
||||
with_get_last_error(|source| crate::Error::GetModuleHandleExW { source }, || {
|
||||
// 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 result = libloaderapi::GetModuleHandleExW(0, wide_filename.as_ptr(), &mut handle);
|
||||
if result == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(Library(handle))
|
||||
}
|
||||
}).map_err(|e| e.unwrap_or(crate::Error::GetModuleHandleExWUnknown))
|
||||
};
|
||||
|
||||
drop(wide_filename); // Drop wide_filename here to ensure it doesn’t get moved and dropped
|
||||
// inside the closure by mistake. See comment inside the closure.
|
||||
ret
|
||||
}
|
||||
|
||||
/// Find and load a module, additionally adjusting behaviour with flags.
|
||||
///
|
||||
/// See [`Library::new`] for documentation on the handling of the `filename` argument. See the
|
||||
/// [flag table on MSDN][flags] for information on applicable values for the `flags` argument.
|
||||
///
|
||||
/// Corresponds to `LoadLibraryExW(filename, reserved: NULL, flags)`.
|
||||
///
|
||||
/// [flags]: https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw#parameters
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// When a library is loaded, initialisation routines contained within the library are executed.
|
||||
/// For the purposes of safety, the execution of these routines is conceptually the same calling an
|
||||
/// unknown foreign function and may impose arbitrary requirements on the caller for the call
|
||||
/// to be sound.
|
||||
///
|
||||
/// Additionally, the callers of this function must also ensure that execution of the
|
||||
/// termination routines contained within the library is safe as well. These routines may be
|
||||
/// executed when the library is unloaded.
|
||||
pub unsafe fn load_with_flags<P: AsRef<OsStr>>(filename: P, flags: DWORD) -> Result<Library, crate::Error> {
|
||||
let wide_filename: Vec<u16> = filename.as_ref().encode_wide().chain(Some(0)).collect();
|
||||
let _guard = ErrorModeGuard::new();
|
||||
|
||||
let ret = with_get_last_error(|source| crate::Error::LoadLibraryExW { source }, || {
|
||||
// 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 =
|
||||
libloaderapi::LoadLibraryExW(wide_filename.as_ptr(), std::ptr::null_mut(), flags);
|
||||
if handle.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(Library(handle))
|
||||
}
|
||||
}).map_err(|e| e.unwrap_or(crate::Error::LoadLibraryExWUnknown));
|
||||
drop(wide_filename); // Drop wide_filename here to ensure it doesn’t get moved and dropped
|
||||
// inside the closure by mistake. See comment inside the closure.
|
||||
ret
|
||||
}
|
||||
|
||||
/// Get a pointer to a function or static variable by symbol name.
|
||||
///
|
||||
/// The `symbol` may not contain any null bytes, with the exception of the 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.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Users of this API must specify the correct type of the function or variable loaded.
|
||||
pub unsafe fn get<T>(&self, symbol: &[u8]) -> Result<Symbol<T>, crate::Error> {
|
||||
ensure_compatible_types::<T, FARPROC>()?;
|
||||
let symbol = cstr_cow_from_bytes(symbol)?;
|
||||
with_get_last_error(|source| crate::Error::GetProcAddress { source }, || {
|
||||
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(crate::Error::GetProcAddressUnknown))
|
||||
}
|
||||
|
||||
/// Get a pointer to a function or static variable by ordinal number.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Users of this API must specify the correct type of the function or variable loaded.
|
||||
pub unsafe fn get_ordinal<T>(&self, ordinal: WORD) -> Result<Symbol<T>, crate::Error> {
|
||||
ensure_compatible_types::<T, FARPROC>()?;
|
||||
with_get_last_error(|source| crate::Error::GetProcAddress { source }, || {
|
||||
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(crate::Error::GetProcAddressUnknown))
|
||||
}
|
||||
|
||||
/// 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`.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The handle must be the result of a successful call of `LoadLibraryA`, `LoadLibraryW`,
|
||||
/// `LoadLibraryExW`, or `LoadLibraryExA`, or a handle previously returned by the
|
||||
/// `Library::into_raw` call.
|
||||
pub unsafe fn from_raw(handle: HMODULE) -> Library {
|
||||
Library(handle)
|
||||
}
|
||||
|
||||
/// Unload the library.
|
||||
///
|
||||
/// You only need to call this if you are interested in handling any errors that may arise when
|
||||
/// library is unloaded. Otherwise this will be done when `Library` is dropped.
|
||||
///
|
||||
/// The underlying data structures may still get leaked if an error does occur.
|
||||
pub fn close(self) -> Result<(), crate::Error> {
|
||||
let result = with_get_last_error(|source| crate::Error::FreeLibrary { source }, || {
|
||||
if unsafe { libloaderapi::FreeLibrary(self.0) == 0 } {
|
||||
None
|
||||
} else {
|
||||
Some(())
|
||||
}
|
||||
}).map_err(|e| e.unwrap_or(crate::Error::FreeLibraryUnknown));
|
||||
// While the library is not free'd yet in case of an error, there is no reason to try
|
||||
// dropping it again, because all that will do is try calling `FreeLibrary` again. only
|
||||
// this time it would ignore the return result, which we already seen failing...
|
||||
std::mem::forget(self);
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Library {
|
||||
fn drop(&mut self) {
|
||||
unsafe { libloaderapi::FreeLibrary(self.0); }
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Library {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
unsafe {
|
||||
// FIXME: use Maybeuninit::uninit_array when stable
|
||||
let mut buf =
|
||||
mem::MaybeUninit::<[mem::MaybeUninit::<WCHAR>; 1024]>::uninit().assume_init();
|
||||
let len = libloaderapi::GetModuleFileNameW(self.0,
|
||||
buf[..].as_mut_ptr().cast(), 1024) as usize;
|
||||
if len == 0 {
|
||||
f.write_str(&format!("Library@{:p}", self.0))
|
||||
} else {
|
||||
let string: OsString = OsString::from_wide(
|
||||
// FIXME: use Maybeuninit::slice_get_ref when stable
|
||||
&*(&buf[..len] as *const [_] as *const [WCHAR])
|
||||
);
|
||||
f.write_str(&format!("Library@{:p} from {:?}", self.0, string))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A symbol from a library.
|
||||
///
|
||||
/// A major difference compared to the cross-platform `Symbol` is that this does not ensure that the
|
||||
/// `Symbol` does not outlive the `Library` that 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 {
|
||||
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.
|
||||
&*(&self.pointer as *const *mut _ as *const T)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> fmt::Debug for Symbol<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.write_str(&format!("Symbol@{:p}", self.pointer))
|
||||
}
|
||||
}
|
||||
|
||||
struct ErrorModeGuard(DWORD);
|
||||
|
||||
impl ErrorModeGuard {
|
||||
#[allow(clippy::if_same_then_else)]
|
||||
fn new() -> Option<ErrorModeGuard> {
|
||||
unsafe {
|
||||
let mut previous_mode = 0;
|
||||
if errhandlingapi::SetThreadErrorMode(SEM_FAILCE, &mut previous_mode) == 0 {
|
||||
// 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.
|
||||
None
|
||||
} else if previous_mode == SEM_FAILCE {
|
||||
None
|
||||
} else {
|
||||
Some(ErrorModeGuard(previous_mode))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for ErrorModeGuard {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
errhandlingapi::SetThreadErrorMode(self.0, ptr::null_mut());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn with_get_last_error<T, F>(wrap: fn(crate::error::WindowsError) -> crate::Error, closure: F)
|
||||
-> Result<T, Option<crate::Error>>
|
||||
where F: FnOnce() -> Option<T> {
|
||||
closure().ok_or_else(|| {
|
||||
let error = unsafe { errhandlingapi::GetLastError() };
|
||||
if error == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(wrap(crate::error::WindowsError(io::Error::from_raw_os_error(error as i32))))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Do not check AppLocker rules or apply Software Restriction Policies for the DLL.
|
||||
///
|
||||
/// This action applies only to the DLL being loaded and not to its dependencies. This value is
|
||||
/// recommended for use in setup programs that must run extracted DLLs during installation.
|
||||
///
|
||||
/// See [flag documentation on MSDN](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw#parameters).
|
||||
pub const LOAD_IGNORE_CODE_AUTHZ_LEVEL: DWORD = consts::LOAD_IGNORE_CODE_AUTHZ_LEVEL;
|
||||
|
||||
/// Map the file into the calling process’ virtual address space as if it were a data file.
|
||||
///
|
||||
/// Nothing is done to execute or prepare to execute the mapped file. Therefore, you cannot call
|
||||
/// functions like [`Library::get`] with this DLL. Using this value causes writes to read-only
|
||||
/// memory to raise an access violation. Use this flag when you want to load a DLL only to extract
|
||||
/// messages or resources from it.
|
||||
///
|
||||
/// See [flag documentation on MSDN](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw#parameters).
|
||||
pub const LOAD_LIBRARY_AS_DATAFILE: DWORD = consts::LOAD_LIBRARY_AS_DATAFILE;
|
||||
|
||||
/// Map the file into the calling process’ virtual address space as if it were a data file.
|
||||
///
|
||||
/// Similar to [`LOAD_LIBRARY_AS_DATAFILE`], except that the DLL file is opened with exclusive
|
||||
/// write access for the calling process. Other processes cannot open the DLL file for write access
|
||||
/// while it is in use. However, the DLL can still be opened by other processes.
|
||||
///
|
||||
/// See [flag documentation on MSDN](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw#parameters).
|
||||
pub const LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE: DWORD = consts::LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE;
|
||||
|
||||
/// Map the file into the process’ virtual address space as an image file.
|
||||
///
|
||||
/// The loader does not load the static imports or perform the other usual initialisation steps.
|
||||
/// Use this flag when you want to load a DLL only to extract messages or resources from it.
|
||||
///
|
||||
/// Unless the application depends on the file having the in-memory layout of an image, this value
|
||||
/// should be used with either [`LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE`] or
|
||||
/// [`LOAD_LIBRARY_AS_DATAFILE`].
|
||||
///
|
||||
/// See [flag documentation on MSDN](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw#parameters).
|
||||
pub const LOAD_LIBRARY_AS_IMAGE_RESOURCE: DWORD = consts::LOAD_LIBRARY_AS_IMAGE_RESOURCE;
|
||||
|
||||
/// Search the application's installation directory for the DLL and its dependencies.
|
||||
///
|
||||
/// Directories in the standard search path are not searched. This value cannot be combined with
|
||||
/// [`LOAD_WITH_ALTERED_SEARCH_PATH`].
|
||||
///
|
||||
/// See [flag documentation on MSDN](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw#parameters).
|
||||
pub const LOAD_LIBRARY_SEARCH_APPLICATION_DIR: DWORD = consts::LOAD_LIBRARY_SEARCH_APPLICATION_DIR;
|
||||
|
||||
/// Search default directories when looking for the DLL and its dependencies.
|
||||
///
|
||||
/// This value is a combination of [`LOAD_LIBRARY_SEARCH_APPLICATION_DIR`],
|
||||
/// [`LOAD_LIBRARY_SEARCH_SYSTEM32`], and [`LOAD_LIBRARY_SEARCH_USER_DIRS`]. Directories in the
|
||||
/// standard search path are not searched. This value cannot be combined with
|
||||
/// [`LOAD_WITH_ALTERED_SEARCH_PATH`].
|
||||
///
|
||||
/// See [flag documentation on MSDN](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw#parameters).
|
||||
pub const LOAD_LIBRARY_SEARCH_DEFAULT_DIRS: DWORD = consts::LOAD_LIBRARY_SEARCH_DEFAULT_DIRS;
|
||||
|
||||
/// Directory that contains the DLL is temporarily added to the beginning of the list of
|
||||
/// directories that are searched for the DLL’s dependencies.
|
||||
///
|
||||
/// Directories in the standard search path are not searched.
|
||||
///
|
||||
/// The `filename` parameter must specify a fully qualified path. This value cannot be combined
|
||||
/// with [`LOAD_WITH_ALTERED_SEARCH_PATH`].
|
||||
///
|
||||
/// See [flag documentation on MSDN](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw#parameters).
|
||||
pub const LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR: DWORD = consts::LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR;
|
||||
|
||||
/// Search `%windows%\system32` for the DLL and its dependencies.
|
||||
///
|
||||
/// Directories in the standard search path are not searched. This value cannot be combined with
|
||||
/// [`LOAD_WITH_ALTERED_SEARCH_PATH`].
|
||||
///
|
||||
/// See [flag documentation on MSDN](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw#parameters).
|
||||
pub const LOAD_LIBRARY_SEARCH_SYSTEM32: DWORD = consts::LOAD_LIBRARY_SEARCH_SYSTEM32;
|
||||
|
||||
/// Directories added using the `AddDllDirectory` or the `SetDllDirectory` function are searched
|
||||
/// for the DLL and its dependencies.
|
||||
///
|
||||
/// If more than one directory has been added, the order in which the directories are searched is
|
||||
/// unspecified. Directories in the standard search path are not searched. This value cannot be
|
||||
/// combined with [`LOAD_WITH_ALTERED_SEARCH_PATH`].
|
||||
///
|
||||
/// See [flag documentation on MSDN](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw#parameters).
|
||||
pub const LOAD_LIBRARY_SEARCH_USER_DIRS: DWORD = consts::LOAD_LIBRARY_SEARCH_USER_DIRS;
|
||||
|
||||
/// If `filename` specifies an absolute path, the system uses the alternate file search strategy
|
||||
/// discussed in the [Remarks section] to find associated executable modules that the specified
|
||||
/// module causes to be loaded.
|
||||
///
|
||||
/// If this value is used and `filename` specifies a relative path, the behaviour is undefined.
|
||||
///
|
||||
/// If this value is not used, or if `filename` does not specify a path, the system uses the
|
||||
/// standard search strategy discussed in the [Remarks section] to find associated executable
|
||||
/// modules that the specified module causes to be loaded.
|
||||
///
|
||||
/// See [flag documentation on MSDN](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw#parameters).
|
||||
///
|
||||
/// [Remarks]: https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw#remarks
|
||||
pub const LOAD_WITH_ALTERED_SEARCH_PATH: DWORD = consts::LOAD_WITH_ALTERED_SEARCH_PATH;
|
||||
|
||||
/// Specifies that the digital signature of the binary image must be checked at load time.
|
||||
///
|
||||
/// See [flag documentation on MSDN](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw#parameters).
|
||||
pub const LOAD_LIBRARY_REQUIRE_SIGNED_TARGET: DWORD = consts::LOAD_LIBRARY_REQUIRE_SIGNED_TARGET;
|
||||
|
||||
/// Allow loading a DLL for execution from the current directory only if it is under a directory in
|
||||
/// the Safe load list.
|
||||
///
|
||||
/// See [flag documentation on MSDN](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw#parameters).
|
||||
pub const LOAD_LIBRARY_SAFE_CURRENT_DIRS: DWORD = consts::LOAD_LIBRARY_SAFE_CURRENT_DIRS;
|
||||
299
clamav/libclamav_rust/.cargo/vendor/libloading/src/safe.rs
vendored
Normal file
299
clamav/libclamav_rust/.cargo/vendor/libloading/src/safe.rs
vendored
Normal file
@@ -0,0 +1,299 @@
|
||||
use super::Error;
|
||||
#[cfg(libloading_docs)]
|
||||
use super::os::unix as imp; // the implementation used here doesn't matter particularly much...
|
||||
#[cfg(all(not(libloading_docs), unix))]
|
||||
use super::os::unix as imp;
|
||||
#[cfg(all(not(libloading_docs), windows))]
|
||||
use super::os::windows as imp;
|
||||
use std::ffi::OsStr;
|
||||
use std::fmt;
|
||||
use std::marker;
|
||||
use std::ops;
|
||||
|
||||
/// A loaded dynamic library.
|
||||
#[cfg_attr(libloading_docs, doc(cfg(any(unix, windows))))]
|
||||
pub struct Library(imp::Library);
|
||||
|
||||
impl Library {
|
||||
/// Find and load a dynamic library.
|
||||
///
|
||||
/// The `filename` argument may be either:
|
||||
///
|
||||
/// * A library filename;
|
||||
/// * The absolute path to the library;
|
||||
/// * A relative (to the current working directory) path to the library.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// When a library is loaded, initialisation routines contained within it are executed.
|
||||
/// For the purposes of safety, the execution of these routines is conceptually the same calling an
|
||||
/// unknown foreign function and may impose arbitrary requirements on the caller for the call
|
||||
/// to be sound.
|
||||
///
|
||||
/// Additionally, the callers of this function must also ensure that execution of the
|
||||
/// termination routines contained within the library is safe as well. These routines may be
|
||||
/// executed when the library is unloaded.
|
||||
///
|
||||
/// # Thread-safety
|
||||
///
|
||||
/// The implementation strives to be as MT-safe as sanely possible, however on certain
|
||||
/// platforms the underlying error-handling related APIs not always MT-safe. This library
|
||||
/// shares these limitations on those platforms. In particular, on certain UNIX targets
|
||||
/// `dlerror` is not MT-safe, resulting in garbage error messages in certain MT-scenarios.
|
||||
///
|
||||
/// Calling this function from multiple threads is not MT-safe if used in conjunction with
|
||||
/// library filenames and the 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, the locations in which the library is searched are
|
||||
/// platform specific and cannot be adjusted in a portable manner. See the documentation for
|
||||
/// the platform specific [`os::unix::Library::new`] and [`os::windows::Library::new`] methods
|
||||
/// for further information on library lookup behaviour.
|
||||
///
|
||||
/// If the `filename` specifies a library filename without a path and with the extension omitted,
|
||||
/// the `.dll` extension is implicitly added on Windows.
|
||||
///
|
||||
/// [`os::unix::Library::new`]: crate::os::unix::Library::new
|
||||
/// [`os::windows::Library::new`]: crate::os::windows::Library::new
|
||||
///
|
||||
/// # Tips
|
||||
///
|
||||
/// Distributing your dynamic libraries under a filename common to all platforms (e.g.
|
||||
/// `awesome.module`) allows you to avoid code which has to account for platform’s conventional
|
||||
/// library filenames.
|
||||
///
|
||||
/// Strive to specify an absolute or at least a 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 flakiness in
|
||||
/// programs.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use ::libloading::Library;
|
||||
/// // Any of the following are valid.
|
||||
/// unsafe {
|
||||
/// let _ = Library::new("/path/to/awesome.module").unwrap();
|
||||
/// let _ = Library::new("../awesome.module").unwrap();
|
||||
/// let _ = Library::new("libsomelib.so.1").unwrap();
|
||||
/// }
|
||||
/// ```
|
||||
pub unsafe fn new<P: AsRef<OsStr>>(filename: P) -> Result<Library, Error> {
|
||||
imp::Library::new(filename).map(From::from)
|
||||
}
|
||||
|
||||
/// Get a pointer to a function or static variable by symbol name.
|
||||
///
|
||||
/// The `symbol` may not contain any null bytes, with the exception of the last byte. Providing a
|
||||
/// null-terminated `symbol` may help to avoid an allocation.
|
||||
///
|
||||
/// The symbol is interpreted as-is; no mangling is done. This means that symbols like `x::y` are
|
||||
/// most likely invalid.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Users of this API must specify the correct type of the function or variable loaded.
|
||||
///
|
||||
/// # Platform-specific behaviour
|
||||
///
|
||||
/// The implementation of thread-local variables is extremely platform specific and uses of such
|
||||
/// variables that work on e.g. Linux may have unintended behaviour on other targets.
|
||||
///
|
||||
/// On POSIX implementations where the `dlerror` function is not confirmed to be MT-safe (such
|
||||
/// as FreeBSD), this function will unconditionally return an error when the underlying `dlsym`
|
||||
/// call returns a null pointer. There are rare situations where `dlsym` returns a genuine null
|
||||
/// pointer without it being an error. If loading a null pointer is something you care about,
|
||||
/// consider using the [`os::unix::Library::get_singlethreaded`] call.
|
||||
///
|
||||
/// [`os::unix::Library::get_singlethreaded`]: crate::os::unix::Library::get_singlethreaded
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Given a loaded library:
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use ::libloading::Library;
|
||||
/// let lib = unsafe {
|
||||
/// Library::new("/path/to/awesome.module").unwrap()
|
||||
/// };
|
||||
/// ```
|
||||
///
|
||||
/// Loading and using a function looks like this:
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use ::libloading::{Library, Symbol};
|
||||
/// # let lib = unsafe {
|
||||
/// # 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 = unsafe { 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>, Error> {
|
||||
self.0.get(symbol).map(|from| Symbol::from_raw(from, self))
|
||||
}
|
||||
|
||||
/// Unload the library.
|
||||
///
|
||||
/// This method might be a no-op, depending on the flags with which the `Library` was opened,
|
||||
/// what library was opened or other platform specifics.
|
||||
///
|
||||
/// You only need to call this if you are interested in handling any errors that may arise when
|
||||
/// library is unloaded. Otherwise the implementation of `Drop` for `Library` will close the
|
||||
/// library and ignore the errors were they arise.
|
||||
///
|
||||
/// The underlying data structures may still get leaked if an error does occur.
|
||||
pub fn close(self) -> Result<(), Error> {
|
||||
self.0.close()
|
||||
}
|
||||
}
|
||||
|
||||
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. The primary method to create an instance of a `Symbol` is via [`Library::get`].
|
||||
///
|
||||
/// The `Deref` trait implementation allows the use of `Symbol` as if it was a function or variable
|
||||
/// itself, without taking care to “extract” the function or variable manually most of the time.
|
||||
///
|
||||
/// [`Library::get`]: Library::get
|
||||
#[cfg_attr(libloading_docs, doc(cfg(any(unix, windows))))]
|
||||
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`.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Using this function relinquishes all the lifetime guarantees. It is up to the developer 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};
|
||||
/// unsafe {
|
||||
/// let lib = Library::new("/path/to/awesome.module").unwrap();
|
||||
/// 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 a reference to the library.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The `library` reference must be exactly the library `sym` was loaded from.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use ::libloading::{Library, Symbol};
|
||||
/// unsafe {
|
||||
/// let lib = Library::new("/path/to/awesome.module").unwrap();
|
||||
/// 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>, library: &'lib L) -> Symbol<'lib, T> {
|
||||
let _ = library; // ignore here for documentation purposes.
|
||||
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};
|
||||
/// unsafe {
|
||||
/// let lib = Library::new("/path/to/awesome.module").unwrap();
|
||||
/// 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> {}
|
||||
37
clamav/libclamav_rust/.cargo/vendor/libloading/src/test_helpers.rs
vendored
Normal file
37
clamav/libclamav_rust/.cargo/vendor/libloading/src/test_helpers.rs
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
//! 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="cdylib"]
|
||||
|
||||
#[no_mangle]
|
||||
pub static mut TEST_STATIC_U32: u32 = 0;
|
||||
|
||||
#[no_mangle]
|
||||
pub static mut TEST_STATIC_PTR: *mut () = 0 as *mut _;
|
||||
|
||||
#[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 _)
|
||||
}
|
||||
34
clamav/libclamav_rust/.cargo/vendor/libloading/src/util.rs
vendored
Normal file
34
clamav/libclamav_rust/.cargo/vendor/libloading/src/util.rs
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
use std::borrow::Cow;
|
||||
use std::ffi::{CStr, CString};
|
||||
use std::os::raw;
|
||||
|
||||
use crate::Error;
|
||||
|
||||
/// Checks for the last byte and avoids allocating if it is zero.
|
||||
///
|
||||
/// Non-last null bytes still result in an error.
|
||||
pub(crate) fn cstr_cow_from_bytes(slice: &[u8]) -> Result<Cow<'_, CStr>, Error> {
|
||||
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(
|
||||
CStr::from_bytes_with_nul(slice)
|
||||
.map_err(|source| Error::CreateCStringWithTrailing { source })?,
|
||||
),
|
||||
// Slice with no trailing 0
|
||||
Some(_) => {
|
||||
Cow::Owned(CString::new(slice).map_err(|source| Error::CreateCString { source })?)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn ensure_compatible_types<T, E>() -> Result<(), Error> {
|
||||
if ::std::mem::size_of::<T>() != ::std::mem::size_of::<E>() {
|
||||
Err(Error::IncompatibleSize)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
13
clamav/libclamav_rust/.cargo/vendor/libloading/tests/constants.rs
vendored
Normal file
13
clamav/libclamav_rust/.cargo/vendor/libloading/tests/constants.rs
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
extern crate libc;
|
||||
extern crate libloading;
|
||||
extern crate static_assertions;
|
||||
|
||||
#[cfg(all(test, unix))]
|
||||
mod unix {
|
||||
use super::static_assertions::const_assert_eq;
|
||||
|
||||
const_assert_eq!(libloading::os::unix::RTLD_LOCAL, libc::RTLD_LOCAL);
|
||||
const_assert_eq!(libloading::os::unix::RTLD_GLOBAL, libc::RTLD_GLOBAL);
|
||||
const_assert_eq!(libloading::os::unix::RTLD_NOW, libc::RTLD_NOW);
|
||||
const_assert_eq!(libloading::os::unix::RTLD_LAZY, libc::RTLD_LAZY);
|
||||
}
|
||||
285
clamav/libclamav_rust/.cargo/vendor/libloading/tests/functions.rs
vendored
Normal file
285
clamav/libclamav_rust/.cargo/vendor/libloading/tests/functions.rs
vendored
Normal file
@@ -0,0 +1,285 @@
|
||||
#[cfg(windows)]
|
||||
extern crate winapi;
|
||||
|
||||
extern crate libloading;
|
||||
use libloading::{Library, Symbol};
|
||||
|
||||
const TARGET_DIR: Option<&'static str> = option_env!("CARGO_TARGET_DIR");
|
||||
const TARGET_TMPDIR: Option<&'static str> = option_env!("CARGO_TARGET_TMPDIR");
|
||||
|
||||
fn lib_path() -> std::path::PathBuf {
|
||||
[
|
||||
TARGET_TMPDIR.unwrap_or(TARGET_DIR.unwrap_or("target")),
|
||||
"libtest_helpers.module",
|
||||
]
|
||||
.iter()
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn make_helpers() {
|
||||
static ONCE: ::std::sync::Once = ::std::sync::Once::new();
|
||||
ONCE.call_once(|| {
|
||||
let rustc = std::env::var_os("RUSTC").unwrap_or_else(|| "rustc".into());
|
||||
let mut cmd = ::std::process::Command::new(rustc);
|
||||
cmd.arg("src/test_helpers.rs").arg("-o").arg(lib_path());
|
||||
if let Some(target) = std::env::var_os("TARGET") {
|
||||
cmd.arg("--target").arg(target);
|
||||
} else {
|
||||
eprintln!("WARNING: $TARGET NOT SPECIFIED! BUILDING HELPER MODULE FOR NATIVE TARGET.");
|
||||
}
|
||||
assert!(cmd
|
||||
.status()
|
||||
.expect("could not compile the test helpers!")
|
||||
.success());
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_id_u32() {
|
||||
make_helpers();
|
||||
unsafe {
|
||||
let lib = Library::new(lib_path()).unwrap();
|
||||
let f: Symbol<unsafe extern "C" 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();
|
||||
unsafe {
|
||||
let lib = Library::new(lib_path()).unwrap();
|
||||
let f: Symbol<unsafe extern "C" 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();
|
||||
unsafe {
|
||||
let lib = Library::new(lib_path()).unwrap();
|
||||
let f: Symbol<unsafe extern "C" fn(S) -> S> = lib.get(b"test_identity_struct\0").unwrap();
|
||||
let f2: Symbol<unsafe extern "C" fn(S) -> S> = lib.get(b"test_identity_struct").unwrap();
|
||||
assert_eq!(*f, *f2);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn wrong_name_fails() {
|
||||
unsafe {
|
||||
Library::new("target/this_location_is_definitely_non existent:^~")
|
||||
.err()
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn missing_symbol_fails() {
|
||||
make_helpers();
|
||||
unsafe {
|
||||
let lib = Library::new(lib_path()).unwrap();
|
||||
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();
|
||||
unsafe {
|
||||
let lib = Library::new(lib_path()).unwrap();
|
||||
lib.get::<*mut ()>(b"test_does\0_not_exist").err().unwrap();
|
||||
lib.get::<*mut ()>(b"test\0_does_not_exist\0")
|
||||
.err()
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_incompatible_type() {
|
||||
make_helpers();
|
||||
unsafe {
|
||||
let lib = Library::new(lib_path()).unwrap();
|
||||
assert!(match lib.get::<()>(b"test_identity_u32\0") {
|
||||
Err(libloading::Error::IncompatibleSize) => true,
|
||||
_ => false,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_incompatible_type_named_fn() {
|
||||
make_helpers();
|
||||
unsafe fn get<'a, T>(l: &'a Library, _: T) -> Result<Symbol<'a, T>, libloading::Error> {
|
||||
l.get::<T>(b"test_identity_u32\0")
|
||||
}
|
||||
unsafe {
|
||||
let lib = Library::new(lib_path()).unwrap();
|
||||
assert!(match get(&lib, test_incompatible_type_named_fn) {
|
||||
Err(libloading::Error::IncompatibleSize) => true,
|
||||
_ => false,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_static_u32() {
|
||||
make_helpers();
|
||||
unsafe {
|
||||
let lib = Library::new(lib_path()).unwrap();
|
||||
let var: Symbol<*mut u32> = lib.get(b"TEST_STATIC_U32\0").unwrap();
|
||||
**var = 42;
|
||||
let help: Symbol<unsafe extern "C" fn() -> u32> =
|
||||
lib.get(b"test_get_static_u32\0").unwrap();
|
||||
assert_eq!(42, help());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_static_ptr() {
|
||||
make_helpers();
|
||||
unsafe {
|
||||
let lib = Library::new(lib_path()).unwrap();
|
||||
let var: Symbol<*mut *mut ()> = lib.get(b"TEST_STATIC_PTR\0").unwrap();
|
||||
**var = *var as *mut _;
|
||||
let works: Symbol<unsafe extern "C" fn() -> bool> =
|
||||
lib.get(b"test_check_static_ptr\0").unwrap();
|
||||
assert!(works());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
// Something about i686-pc-windows-gnu, makes dll initialisation code call abort when it is loaded
|
||||
// and unloaded many times. So far it seems like an issue with mingw, not libloading, so ignoring
|
||||
// the target. Especially since it is very unlikely to be fixed given the state of support its
|
||||
// support.
|
||||
#[cfg(not(all(target_arch = "x86", target_os = "windows", target_env = "gnu")))]
|
||||
fn manual_close_many_times() {
|
||||
make_helpers();
|
||||
let join_handles: Vec<_> = (0..16)
|
||||
.map(|_| {
|
||||
std::thread::spawn(|| unsafe {
|
||||
for _ in 0..10000 {
|
||||
let lib = Library::new(lib_path()).expect("open library");
|
||||
let _: Symbol<unsafe extern "C" fn(u32) -> u32> =
|
||||
lib.get(b"test_identity_u32").expect("get fn");
|
||||
lib.close().expect("close is successful");
|
||||
}
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
for handle in join_handles {
|
||||
handle.join().expect("thread should succeed");
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[test]
|
||||
fn library_this_get() {
|
||||
use libloading::os::unix::Library;
|
||||
make_helpers();
|
||||
// SAFE: functions are never called
|
||||
unsafe {
|
||||
let _lib = Library::new(lib_path()).unwrap();
|
||||
let this = Library::this();
|
||||
// Library we loaded in `_lib` (should be RTLD_LOCAL).
|
||||
assert!(this
|
||||
.get::<unsafe extern "C" fn()>(b"test_identity_u32")
|
||||
.is_err());
|
||||
// Something obscure from libc...
|
||||
assert!(this.get::<unsafe extern "C" fn()>(b"freopen").is_ok());
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
#[test]
|
||||
fn library_this() {
|
||||
use libloading::os::windows::Library;
|
||||
make_helpers();
|
||||
unsafe {
|
||||
// SAFE: well-known library without initialisers is loaded.
|
||||
let _lib = Library::new(lib_path()).unwrap();
|
||||
let this = Library::this().expect("this library");
|
||||
// SAFE: functions are never called.
|
||||
// Library we loaded in `_lib`.
|
||||
assert!(this
|
||||
.get::<unsafe extern "C" fn()>(b"test_identity_u32")
|
||||
.is_err());
|
||||
// Something "obscure" from kernel32...
|
||||
assert!(this.get::<unsafe extern "C" fn()>(b"GetLastError").is_err());
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
#[test]
|
||||
fn works_getlasterror() {
|
||||
use libloading::os::windows::{Library, Symbol};
|
||||
use winapi::shared::minwindef::DWORD;
|
||||
use winapi::um::errhandlingapi;
|
||||
|
||||
unsafe {
|
||||
let lib = Library::new("kernel32.dll").unwrap();
|
||||
let gle: Symbol<unsafe extern "system" fn() -> DWORD> = lib.get(b"GetLastError").unwrap();
|
||||
errhandlingapi::SetLastError(42);
|
||||
assert_eq!(errhandlingapi::GetLastError(), gle())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
#[test]
|
||||
fn works_getlasterror0() {
|
||||
use libloading::os::windows::{Library, Symbol};
|
||||
use winapi::shared::minwindef::DWORD;
|
||||
use winapi::um::errhandlingapi;
|
||||
|
||||
unsafe {
|
||||
let lib = Library::new("kernel32.dll").unwrap();
|
||||
let gle: Symbol<unsafe extern "system" fn() -> DWORD> = lib.get(b"GetLastError\0").unwrap();
|
||||
errhandlingapi::SetLastError(42);
|
||||
assert_eq!(errhandlingapi::GetLastError(), gle())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
#[test]
|
||||
fn library_open_already_loaded() {
|
||||
use libloading::os::windows::Library;
|
||||
|
||||
// Present on Windows systems and NOT used by any other tests to prevent races.
|
||||
const LIBPATH: &str = "Msftedit.dll";
|
||||
|
||||
// Not loaded yet.
|
||||
assert!(match Library::open_already_loaded(LIBPATH) {
|
||||
Err(libloading::Error::GetModuleHandleExW { .. }) => true,
|
||||
_ => false,
|
||||
});
|
||||
|
||||
unsafe {
|
||||
let _lib = Library::new(LIBPATH).unwrap();
|
||||
// Loaded now.
|
||||
assert!(Library::open_already_loaded(LIBPATH).is_ok());
|
||||
}
|
||||
}
|
||||
17
clamav/libclamav_rust/.cargo/vendor/libloading/tests/library_filename.rs
vendored
Normal file
17
clamav/libclamav_rust/.cargo/vendor/libloading/tests/library_filename.rs
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
extern crate libloading;
|
||||
use libloading::library_filename;
|
||||
use std::path::Path;
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
const EXPECTED: &str = "audioengine.dll";
|
||||
#[cfg(target_os = "linux")]
|
||||
const EXPECTED: &str = "libaudioengine.so";
|
||||
#[cfg(target_os = "macos")]
|
||||
const EXPECTED: &str = "libaudioengine.dylib";
|
||||
|
||||
#[test]
|
||||
fn test_library_filename() {
|
||||
let name = "audioengine";
|
||||
let resolved = library_filename(name);
|
||||
assert!(Path::new(&resolved).ends_with(EXPECTED));
|
||||
}
|
||||
96
clamav/libclamav_rust/.cargo/vendor/libloading/tests/markers.rs
vendored
Normal file
96
clamav/libclamav_rust/.cargo/vendor/libloading/tests/markers.rs
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
extern crate libloading;
|
||||
|
||||
#[cfg(test)]
|
||||
fn assert_send<T: Send>() {}
|
||||
#[cfg(test)]
|
||||
fn assert_sync<T: Sync>() {}
|
||||
#[cfg(test)]
|
||||
fn assert_display<T: std::fmt::Display>() {}
|
||||
|
||||
#[test]
|
||||
fn check_error_send() {
|
||||
assert_send::<libloading::Error>();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_error_sync() {
|
||||
assert_sync::<libloading::Error>();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_error_display() {
|
||||
assert_display::<libloading::Error>();
|
||||
}
|
||||
|
||||
#[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 ()>>();
|
||||
}
|
||||
BIN
clamav/libclamav_rust/.cargo/vendor/libloading/tests/nagisa32.dll
vendored
Normal file
BIN
clamav/libclamav_rust/.cargo/vendor/libloading/tests/nagisa32.dll
vendored
Normal file
Binary file not shown.
BIN
clamav/libclamav_rust/.cargo/vendor/libloading/tests/nagisa64.dll
vendored
Normal file
BIN
clamav/libclamav_rust/.cargo/vendor/libloading/tests/nagisa64.dll
vendored
Normal file
Binary file not shown.
64
clamav/libclamav_rust/.cargo/vendor/libloading/tests/windows.rs
vendored
Normal file
64
clamav/libclamav_rust/.cargo/vendor/libloading/tests/windows.rs
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
#![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 {
|
||||
unsafe {
|
||||
Library::new("tests/nagisa32.dll").expect("nagisa32.dll")
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch="x86_64")]
|
||||
fn load_ordinal_lib() -> Library {
|
||||
unsafe {
|
||||
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() {
|
||||
unsafe {
|
||||
Library::new("kernel23").err().unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_new_kernel32_no_ext() {
|
||||
unsafe {
|
||||
Library::new("kernel32").unwrap();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user