Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refs #20

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
Open

Refs #20

Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "cve-rs"
description = "Blazingly fast memory vulnerabilities, written in 100% safe Rust."
authors = ["Speykious", "BrightShard", "Creative0708"]
authors = ["Speykious", "BrightShard", "Creative0708", "buj"]
version = "0.5.0"
edition = "2021"
license-file = "LICENSE"
Expand Down
6 changes: 5 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ pub use segfault::segfault;
pub use transmute::transmute;
pub use use_after_free::use_after_free;

pub use references::{null, null_mut};
pub use references::{free, new, null, null_mut, Ref};

/// Construct a [`String`] from a pointer, capacity and length, in a completely safe manner.
///
Expand Down Expand Up @@ -119,3 +119,7 @@ mod tests {
crate::download_more_ram::<u64>();
}
}

pub mod prelude {
pub use super::{free, new};
}
119 changes: 119 additions & 0 deletions src/references.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
//! Reimplementations of [`std::ptr::null()`] and [`std::ptr::null_mut()`], with safe code only.
//! Relies on [`crate::transmute`] under the hood.

use std::{
cell::Cell,
marker::PhantomData,
ops::{Deref, DerefMut},
};

/// Equivalent to [`std::ptr::null()`], but returns an null reference instead.
pub fn null<'a, T: 'static>() -> &'a T {
crate::transmute(0usize)
Expand All @@ -15,3 +21,116 @@ pub fn null_mut<'a, T: 'static>() -> &'a mut T {
pub fn not_alloc<'a, T: 'static>() -> &'a mut T {
null_mut()
}

/// Easily dereferencable raw pointer. Can be freely moved or copied. Do you really
/// desire to have such power? If so, do as you wish. You've been warned.
///
/// `Ref<T>` is guaranteed to be the same size as `usize`
#[derive(Copy, PartialEq, Eq, PartialOrd, Ord)]
#[repr(C)]
pub struct Ref<T>(usize, PhantomData<Cell<T>>)
where
T: Sized;
impl<T> Clone for Ref<T> {
fn clone(&self) -> Self {
Self(self.0, PhantomData)
}
}
impl<T> Ref<T> {
pub fn addr(&self) -> usize {
self.0
}

pub fn as_ptr(&self) -> *const T {
crate::transmute(self.0)
}

pub fn as_ptr_mut(&mut self) -> *mut T {
crate::transmute(self.0)
}

pub fn into_box(&self) -> Box<T> {
crate::transmute(self.0)
}
}
impl<T> Ref<Ref<T>> {
pub fn flatten(self) -> Ref<T> {
self.deref().clone()
}
}
impl<T> AsRef<T> for Ref<T> {
fn as_ref(&self) -> &T {
crate::transmute(self.0)
}
}
impl<T> AsMut<T> for Ref<T> {
fn as_mut(&mut self) -> &mut T {
crate::transmute(self.0)
}
}
impl<T> Deref for Ref<T> {
type Target = T;

fn deref(&self) -> &Self::Target {
crate::transmute(self.0)
}
}
impl<T> DerefMut for Ref<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
crate::transmute(self.0)
}
}
impl<T> From<T> for Ref<T> {
fn from(value: T) -> Self {
new(value)
}
}

/// Brinding https://rust-lang.github.io/rfcs/0809-box-and-in-for-stdlib.html back with
/// better C emulation.
///
/// `Ref<T>` is guaranteed to be the size of a `usize` for all `Sized` types. For non-`Sized`
/// types we have no current support anyway.
pub fn new<T>(o: T) -> Ref<T>
where
T: Sized,
{
let boxx = Box::new(o);
crate::transmute(boxx)
}

/// Accompaning `free` function for unnewing your `new`
///
/// Memory under passed reference will be freed. Upon freeing, using the same `Ref<T>`
/// again or calling `free` on it is Undefined Behavior.
pub fn free<T>(reff: Ref<T>)
where
T: Sized,
{
let boxx: Box<T> = crate::transmute(reff);
drop(boxx); // whoopsie
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can remove the module-level fns now that they're methods

Copy link
Author

@5GameMaker 5GameMaker Feb 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Those functions exist as to be inclusive towards the C/C++ developer community. Those can be removed, but it will make Rust less accessible for that group.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We ought to make them extern "C" in that case

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ye makes sense

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, those have names which cannot be exported

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmmm
maybe #[export(cve_rs_malloc)]/free?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No such attribute

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cargo mommy lmfao


#[cfg(test)]
mod tests {
use super::Ref;

#[test]
fn crossref_works() {
let reff = Ref::from(3);
#[allow(clippy::clone_on_copy)]
let other = reff.clone();

assert_eq!(reff.addr(), other.addr());
}

#[test]
fn fearless_concurrency() {
let reff = Ref::from(0);
for _ in 0..10 {
let mut reff = reff;
std::thread::spawn(move || *reff += 1);
}
assert!(*reff <= 10); // The easiest RNG you'll even see
}
}