SafeManuallyDrop
A safe version of ManuallyDrop with various features and options to track undefined behavior when working with ManuallyDrop.
Use
1. easy
use SafeManuallyDrop::ManuallyDrop;
use std::ops::Deref;
fn main() {
/*
ManuallyDrop - Depending on the build flag, a protected version of ManuallyDrop
or an unprotected version of ManuallyDrop with a default trigger.
*/
if ManuallyDrop::is_safe_mode() {
// ManuallyDrop is protected, let's do the standard behavior ManuallyDrop
// but at the end we'll make the undefined behavior ManuallyDrop.
//
let mut data = ManuallyDrop::new(vec![1, 2, 3, 4]);
println!("data: {:?}", data.deref());
#[allow(unused_unsafe)] // to avoid warning if the always_compatible_stdapi flag is not used (can be removed)
unsafe {
assert_eq!(data.is_next_trig(), false); // VALID
ManuallyDrop::drop(&mut data); // VALID
assert_eq!(data.is_next_trig(), true); // VALID
// <<-- PANIC
/*
thread 'main' panicked at 'Undefined behavior when using
ManuallyDrop(combo_replace_manudropstate), instead of the expected default
state, the current state: DropModeTrig.', src/core/trig/hook.rs:14:5
*/
ManuallyDrop::drop(&mut data); // INVALID, COMBO DROP
}
}else {
println!("#[0] ManuallyDrop is an alias for AutoSafeManuallyDrop, ");
println!("#[1] ManuallyDrop in the release build has no protection by default,");
println!("#[2] if ManuallyDrop is not protected it will be the same as in std.");
println!("#[3] To run the protected version, use `cargo run --example easy` or ");
println!("`CARGO_PROFILE_RELEASE_DEBUG_ASSERTIONS=\"true\" cargo run --example easy --release`");
println!();
println!("Or use concrete types instead of auto (AutoSafeManuallyDrop, AutoSafePanicManuallyDrop, AutoSafeHookManuallyDrop, AutoSafeCounterManuallyDrop, AlwaysSafeManuallyDrop, AlwaysSafePanicManuallyDrop, AlwaysSafeHookManuallyDrop, AlwaysSafeCounterManuallyDrop) specific data types with specific behavior.");
}
}
2. EasyStruct
// 1. In production code, it is recommended to use AutoSafe instead of AlwaysSafe,
// this will eliminate unnecessary checks in the release build, but leave
// them in the test build.
//
// 2. It is generally recommended to use Panic or Abort as a trigger for undefined behavior.
//
use AlwaysSafePanicManuallyDrop as ManuallyDrop;
;
// Properly created and validated MyLogicData structure.
3. hook
use Deref;
// For better performance, we recommend using AutoSafeHookManuallyDrop instead
// of AlwaysSafeHookManuallyDrop. The AutoSafeHookManuallyDrop type depends on
// the type of build, debug or release will be with the safe or insecure version
// of ManuallyDrop.
use AlwaysSafeHookManuallyDrop as ManuallyDrop;
4. counter
// Let me remind you that CounterManuallyDrop by behavior allows undefined
// behavior in the same way as ManuallyDrop, but, unlike ManuallyDrop,
// Counter keeps a counter of the number of undefined behavior triggers.
// !!!!
// CounterManuallyDrop is experimental and changes the behavior of
// the trigger trait for all types.
use AutoSafeCounterManuallyDrop as ManuallyDrop;
use ManuallyDrop;
use Deref;
1. PlugAndPlay (Minimal, Panic)
= "1.0.3"
default-features = false
features =
version
2. PlugAndPlay (Minimal, Abort)
= "1.0.3"
default-features = false
features =
version
3. PlugAndPlay (Minimal, Hook)
= "1.0.3"
default-features = false
features =
version
cargo.toml -> features
// Flags:
//
// ManuallyDrop and AutoManuallyDrop are always type safe and are automatically
// checked on use if the debug_assertions flag is enabled (the flag is automatically
// enabled if test build, debug build, or env: CARGO_PROFILE_RELEASE_DEBUG_ASSERTIONS=true).
//
// (Also, AlwaysSafeManuallyDrop is always checked for safety when it is used, regardless of the flags.)
"always_check_in_case_debug_assertions",
// ManuallyDrop and AutoManuallyDrop are always checked when used,
// regardless of external flags.
//
// (Also, AlwaysSafeManuallyDrop is always checked for safety when it is used, regardless of the flags.)
//"always_safe_manuallydrop",
// Enable additional internal checks of the SafeManuallyDrop library when
// the debug_assertions flag is enabled (does not depend on the always_check_in_case_debug_assertions
// and always_safe_manuallydrop options). This flag type only applies to internal
// library function checks, it is independent of ManuallyDrop and its valid or invalid usage.
//
// "allow_fullinternal_debug_assertions",
# Preserve unsafe even if functions are safe
#
"always_compatible_stdapi",
// Always create a modular table of library flags used in the build.
// (crate::core::flags)
"always_build_flagstable",
// Trigs:
//
// Ability to determine if an empty loop trigger has been executed.
"support_istrig_loop",
// Support for PanicManuallyDrop, in case of undefined behavior
// of ManuallyDrop there will be a panic.
"support_panic_trig",
// Support for AbortManuallyDrop, in case of undefined behavior
// of ManuallyDrop there will be a abort. (Note that this feature requires std.)
//"support_abort_trig",
// HookManuallyDrop support, in case of undefined HookManuallyDrop behavior,
// the hook function will be called.
"support_hookfn_trig",
// Support for CounterManuallyDrop, in case of undefined behavior,
// CounterManuallyDrop will add +1 to the counter.
//"support_count_trig",
// The behavior for the simple AutoSafeManuallyDrop/AlwaysSafeManuallyDrop/ManuallyDrop type will always
// cause a panic in case of undefined behavior.
//"always_deftrig_panic",
// The behavior for the simple AutoSafeManuallyDrop/AlwaysSafeManuallyDrop/ManuallyDrop type will always
// cause a abort in case of undefined behavior.
//"always_deftrig_abort",
// The behavior for the simple AutoSafeManuallyDrop/AlwaysSafeManuallyDrop/ManuallyDrop type will always
// call the hook function in case of undefined behavior.
"always_deftrig_hookfn",
// The behavior for the simple AutoSafeManuallyDrop/AlwaysSafeManuallyDrop/ManuallyDrop type will always call
// the +1 counter function in case of undefined behavior.
//"always_deftrig_count",
// The behavior for the simple type AutoSafeManuallyDrop/AlwaysSafeManuallyDrop/ManuallyDrop will always call
// the eternal loop function in case of undefined behavior.
//"always_deftrig_loop"
License
Copyright 2022 #UlinProject Denis Kotlyarov (Денис Котляров)
Licensed under the Apache License, Version 2.0