#![forbid(unsafe_code)] #![cfg_attr(doc, feature(doc_auto_cfg))]
#[inline(always)]
#[cfg(any(feature = "test-borrow", doc))]
pub fn extend<'a, T>(input: &'a T) -> &'static T {
struct Bounded<'a, 'b: 'static, T>(&'a T, [&'b (); 0]);
let n: Box<dyn FnOnce(&T) -> Bounded<'static, '_, T>> = Box::new(|x| Bounded(x, []));
n(input).0
}
#[inline(always)]
#[cfg(any(feature = "test-borrow-mut", doc))]
pub fn extend_mut<'a, T>(input: &'a mut T) -> &'static mut T {
struct Bounded<'a, 'b: 'static, T>(&'a mut T, [&'b (); 0]);
let mut n: Box<dyn FnMut(&mut T) -> Bounded<'static, '_, T>> = Box::new(|x| Bounded(x, []));
n(input).0
}
#[inline(always)]
#[cfg(any(feature = "test-fake-static-borrow", doc))]
pub fn make_static<'a, T>(input: &'a T) -> &'static T {
fn helper<'a, T>(_: [&'static &'a (); 0], v: &'a T) -> &'static T {
v
}
let f: fn([&'static &(); 0], &T) -> &'static T = helper;
f([], input) }
#[inline(always)]
#[cfg(any(feature = "test-fake-static-borrow-mut", doc))]
pub fn make_static_mut<'a, T>(input: &'a mut T) -> &'static mut T {
fn helper_mut<'a, T>(_: [&'static &'a (); 0], v: &'a mut T) -> &'static mut T {
v
}
let f: fn([&'static &'static (); 0], &'a mut T) -> &'static mut T = helper_mut;
f([], input)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
#[should_panic]
#[cfg(feature = "test-borrow-mut")]
fn it_panics() {
let mut a = vec![1, 2, 3, 4, 5, 6, 7, 8];
let b = extend_mut(&mut a);
drop(a);
panic!("{b:?} is still readable!");
}
#[test]
#[should_panic]
#[cfg(feature = "test-borrow")]
fn uaf() {
let a = vec![1, 2, 3, 4];
let b = extend(&a);
drop(a);
assert_eq!(b, &[1, 2, 3, 4]);
}
#[test]
#[should_panic]
#[cfg(feature = "test-fake-static-borrow-mut")]
fn it_panics_2() {
let mut a = vec![1, 2, 3, 4, 5, 6, 7, 8];
let b = make_static_mut(&mut a);
drop(a);
panic!("{b:?} is still readable!");
}
#[test]
#[should_panic]
#[cfg(feature = "test-fake-static-borrow")]
fn uaf_2() {
let a = vec![1, 2, 3, 4];
let b = make_static(&a);
drop(a);
assert_eq!(b, &[1, 2, 3, 4]);
}
}