This commit is contained in:
Murphy 2023-06-08 02:10:57 -04:00
parent 665e500fe7
commit 346bac811d
6 changed files with 134 additions and 51 deletions

14
Cargo.lock generated
View file

@ -2,15 +2,15 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "leak_memory"
version = "0.1.0"
dependencies = [
"libc",
]
[[package]]
name = "libc"
version = "0.2.146"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b"
[[package]]
name = "urine"
version = "0.1.0"
dependencies = [
"libc",
]

View file

@ -1,7 +1,13 @@
[package]
name = "urine"
name = "leak_memory"
version = "0.1.0"
authors = ["Tyler Murphy <tylerm@tylerm.dev>"]
edition = "2021"
description = "The enterprise way to leak memory"
license = "MIT++"
exclude = [".git", ".gitignore", "target"]
rust-version = "1.69" # hehe funny
readme = "README.md"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

7
LICENSE Normal file
View file

@ -0,0 +1,7 @@
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
The Software shall be used for Evil, not Good.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

31
README.md Normal file
View file

@ -0,0 +1,31 @@
# Leak Memory
leaks memory uwu
## Examples
Leak 1337 bytes of memory
```rs
use leak_memory::{leak, LeakMethod};
fn main() {
leak(1337, LeakMethod::Lazy);
}
```
Leak 69 kibibytes
```rs
use leak_memory::{leak, LeakMethod, LeakAmount};
fn main() {
leak("69kib".parse::<LeakAmount>().unwrap(), LeakMethod::Rust);
}
```
## Compilation
dont

View file

@ -1,33 +1,35 @@
use std::cell::RefCell;
use libc::malloc;
use std::fmt::{Result, Display, Formatter};
use std::fmt::{self, Display, Formatter};
pub mod parse;
mod parse;
#[derive(Clone, Debug)]
pub enum PissError {
pub enum LeakError {
Unexpected(char),
InvalidSuffix(String),
InvalidNumber(String),
NumberNotPositive
}
impl Display for PissError {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
impl Display for LeakError {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
Self::InvalidSuffix(s) => write!(f, "I cannot piss the suffix {s:?}"),
Self::InvalidNumber(s) => write!(f, "I cannot piss the invalid number {s:?}"),
Self::NumberNotPositive => write!(f, "I cannot piss nonexistent memory")
Self::Unexpected(c) => write!(f, "Unexpected character: '{c}'"),
Self::InvalidSuffix(s) => write!(f, "Invalid file size suffix: '{s}'"),
Self::InvalidNumber(s) => write!(f, "Invalid number: '{s}'"),
Self::NumberNotPositive => write!(f, "Cannot leak negative memory")
}
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
pub struct PissAmount {
to_piss: u128
pub struct LeakAmount {
to_leak: u128
}
#[derive(Copy, Clone, Debug)]
pub enum Toliet {
pub enum LeakMethod {
Rust,
Lazy,
Unsafe
@ -42,7 +44,7 @@ thread_local!(static TOLIET: RefCell<Vec<Vec<u8>>> = RefCell::new(Vec::new()));
fn leak_lazy(amount: usize) {
TOLIET.with(|t| {
t.borrow_mut().push(Vec::<u8>::with_capacity(amount));
})
});
}
fn leak_unsafe(amount: usize) {
@ -51,16 +53,21 @@ fn leak_unsafe(amount: usize) {
}
}
fn leak_match(amount: usize, method: Toliet) {
fn leak_match(amount: usize, method: LeakMethod) {
match method {
Toliet::Rust => leak_rust(amount),
Toliet::Lazy => leak_lazy(amount),
Toliet::Unsafe => leak_unsafe(amount),
LeakMethod::Rust => leak_rust(amount),
LeakMethod::Lazy => leak_lazy(amount),
LeakMethod::Unsafe => leak_unsafe(amount),
}
}
pub fn leak<T: Into<PissAmount>>(amount: T, method: Toliet) {
let num: u128 = amount.into().to_piss;
pub fn leak<T: Into<LeakAmount>>(amount: T, method: LeakMethod) -> Result<(), LeakError> {
let num: u128 = amount.into().to_leak;
if num <= 0 {
return Err(LeakError::NumberNotPositive)
}
let count = num / usize::MAX as u128;
for _ in 0..count {
@ -68,8 +75,10 @@ pub fn leak<T: Into<PissAmount>>(amount: T, method: Toliet) {
}
leak_match((num % usize::MAX as u128) as usize, method);
Ok(())
}
pub async fn leak_async<T: Into<PissAmount>>(amount: T, method: Toliet) {
leak(amount, method);
pub async fn leak_async<T: Into<LeakAmount> + Send>(amount: T, method: LeakMethod) -> Result<(), LeakError> {
leak(amount, method)
}

View file

@ -1,16 +1,45 @@
use std::str::FromStr;
use crate::{PissError, PissAmount};
use crate::{LeakError, LeakAmount};
impl<T> From<T> for PissAmount
where T: Into<u128> {
fn from(num: T) -> Self {
Self {
to_piss: num.into()
}
}
macro_rules! from_num {
($t:ty) => {
impl From<$t> for LeakAmount {
fn from(num: $t) -> Self {
Self {
to_leak: num as u128
}
}
}
impl From<Vec<$t>> for LeakAmount {
fn from(vec: Vec<$t>) -> Self {
let mut amount = 0;
for i in vec {
amount += i as u128;
}
Self {
to_leak: amount
}
}
}
};
}
fn parse_suffix(s: &str) -> Result<u128, PissError> {
from_num!(u128);
from_num!(u64);
from_num!(u32);
from_num!(u16);
from_num!(u8);
from_num!(i128);
from_num!(i64);
from_num!(i32);
from_num!(i16);
from_num!(i8);
from_num!(f32);
from_num!(f64);
from_num!(bool);
fn parse_suffix(s: &str) -> Result<u128, LeakError> {
Ok(match s { // nepal
"k" | "kb" => 1_000,
"m" | "mb" => 1_000_000,
@ -33,39 +62,40 @@ fn parse_suffix(s: &str) -> Result<u128, PissError> {
"ri" | "rib" => 0x0400_0000_0000_0000_0000_0000,
"qi" | "qib" => 0x0010_0000_0000_0000_0000_0000_0000,
"" | "b" => 1, // uwu
_ => return Err(PissError::InvalidSuffix(s.into())) // such nepal
_ => return Err(LeakError::InvalidSuffix(s.into())) // such nepal
})
}
fn parse_file_size(s: &str) -> Result<PissAmount, PissError> {
fn parse_file_size(s: &str) -> Result<LeakAmount, LeakError> {
let mut end = 0;
for (i, c) in s.char_indices() {
if c.is_ascii_digit() || c == '.' { continue; }
end = i;
break;
if !c.is_ascii_digit() && c != '.' { break; }
}
if end == 0 {
if let Some(c) = s.chars().nth(0) {
return Err(LeakError::Unexpected(c))
}
}
let num_text = &s[..end];
let suffix_text = &s[end..];
let Ok(num) = num_text.parse::<f64>() else {
return Err(PissError::InvalidNumber(num_text.into()))
return Err(LeakError::InvalidNumber(num_text.into()))
};
if num <= 0f64 {
return Err(PissError::NumberNotPositive)
}
let multiplier = parse_suffix(suffix_text)?;
Ok(PissAmount {
to_piss: (num * multiplier as f64) as u128
Ok(LeakAmount {
to_leak: (num * multiplier as f64) as u128
})
}
impl FromStr for PissAmount {
type Err = PissError;
impl FromStr for LeakAmount {
type Err = LeakError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
parse_file_size(s)
parse_file_size(s.to_lowercase().as_str())
}
}