lleeaakk
This commit is contained in:
parent
665e500fe7
commit
346bac811d
6 changed files with 134 additions and 51 deletions
14
Cargo.lock
generated
14
Cargo.lock
generated
|
@ -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",
|
||||
]
|
||||
|
|
|
@ -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
7
LICENSE
Normal 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
31
README.md
Normal 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
|
49
src/lib.rs
49
src/lib.rs
|
@ -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)
|
||||
}
|
||||
|
|
70
src/parse.rs
70
src/parse.rs
|
@ -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 {
|
||||
macro_rules! from_num {
|
||||
($t:ty) => {
|
||||
impl From<$t> for LeakAmount {
|
||||
fn from(num: $t) -> Self {
|
||||
Self {
|
||||
to_piss: num.into()
|
||||
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())
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue