#![allow(clippy::empty_line_after_doc_comments)]
#![allow(clippy::mixed_attributes_style)]
#![allow(dead_code)]
#![allow(clippy::vec_init_then_push)]
#![allow(clippy::approx_constant)]
#![allow(clippy::useless_vec)]
pub mod buffer_overflow_prevention;
pub mod data_race_prevention;
pub mod use_after_free_prevention;
pub mod buffer_overflow {
pub fn safe_array_access() {
let data = vec![1, 2, 3, 4, 5];
if let Some(&value) = data.get(10) {
println!("Value: {}", value);
} else {
println!("Index out of bounds - safely handled!");
}
}
pub fn safe_string_handling() {
let mut buffer = String::new();
for i in 0..1000 {
buffer.push_str(&format!("Item {}, ", i));
}
println!("Buffer safely holds {} bytes", buffer.len());
}
pub fn compare_c_vs_rust() {
let buffer = "This is way too long".to_string();
let truncated: String = buffer.chars().take(10).collect();
println!("C: Buffer overflow vulnerability");
println!("Rust: Safe truncation - {}", truncated);
}
}
pub mod use_after_free {
pub fn ownership_prevents_uaf() {
let data = vec![1, 2, 3, 4, 5];
let owned_data = data;
println!("Rust prevents use-after-free at compile time");
println!("Data safely owned: {:?}", owned_data);
}
pub fn borrowing_prevents_dangling() {
let data = vec![1, 2, 3, 4, 5];
let reference = &data;
println!("Reference is valid: {:?}", reference);
}
pub fn compare_c_vs_rust() {
println!("C: Use-after-free vulnerability");
println!("Rust: Compile-time prevention of dangling pointers");
}
}
pub mod data_race {
use std::sync::{Arc, Mutex};
use std::thread;
pub fn safe_concurrent_access() {
let counter = Arc::new(Mutex::new(0));
let mut handles = vec![];
for _ in 0..10 {
let counter_clone = Arc::clone(&counter);
let handle = thread::spawn(move || {
let mut num = counter_clone.lock().unwrap();
*num += 1;
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
println!("Final count (safe): {}", *counter.lock().unwrap());
println!("No data races possible!");
}
pub fn type_system_prevents_races() {
println!("Rust's type system prevents data races at compile time");
}
pub fn compare_c_vs_rust() {
safe_concurrent_access();
println!("\nC: Data races cause undefined behavior");
println!("Rust: Compile-time prevention of data races");
}
}
pub mod integer_overflow {
pub fn checked_arithmetic() {
let a: u32 = 4_000_000_000;
let b: u32 = 1_000_000_000;
match a.checked_add(b) {
Some(result) => println!("Result: {}", result),
None => println!("Overflow detected and handled safely!"),
}
}
pub fn saturating_arithmetic() {
let balance: u32 = 1000;
let withdrawal: u32 = 2000;
let new_balance = balance.saturating_sub(withdrawal);
println!("Balance after withdrawal: {} (saturated)", new_balance);
}
}
pub mod null_pointer {
pub fn option_prevents_null() {
fn find_user(id: u32) -> Option<String> {
if id == 1 {
Some("Alice".to_string())
} else {
None
}
}
match find_user(1) {
Some(name) => println!("Found user: {}", name),
None => println!("User not found"),
}
}
pub fn compare_c_vs_rust() {
option_prevents_null();
println!("\nC: Null pointer dereferences cause crashes");
println!("Rust: Option<T> forces handling of null cases");
}
}
pub mod double_free {
pub fn ownership_prevents_double_free() {
let data = vec![1, 2, 3, 4, 5];
println!("Rust prevents double-free through ownership");
println!("Data will be freed exactly once: {:?}", data);
}
pub fn box_single_ownership() {
let boxed_value = Box::new(42);
let moved_box = boxed_value;
println!("Boxed value freed exactly once: {}", moved_box);
}
pub fn compare_c_vs_rust() {
ownership_prevents_double_free();
println!("\nC: Double-free vulnerabilities");
println!("Rust: Compile-time prevention of double-free");
}
}
pub mod uninitialized_memory {
pub fn initialization_required() {
let x: i32 = 42;
println!("Value is always initialized: {}", x);
}
pub fn array_initialization() {
let arr = vec![0; 100]; println!("Array element (initialized): {}", arr[0]);
let arr2: Vec<i32> = (0..100).map(|i| i * 2).collect();
println!("Array with values: {} elements", arr2.len());
}
pub fn struct_initialization() {
struct User {
id: u32,
name: String,
email: String,
}
let user = User {
id: 1,
name: "Alice".to_string(),
email: "alice@example.com".to_string(),
};
println!("User struct fully initialized: {}", user.name);
}
pub fn compare_c_vs_rust() {
println!("C: Uninitialized memory contains garbage values");
println!("Rust: Compiler enforces initialization before use");
initialization_required();
array_initialization();
struct_initialization();
}
}
pub mod memory_leak {
use std::fs::File;
use std::io::Write;
pub fn raii_file_handling() {
{
let mut file = File::create("/tmp/test.txt").ok();
if let Some(ref mut f) = file {
let _ = f.write_all(b"Hello, RAII!");
}
}
println!("File handle automatically closed (RAII)");
}
pub fn drop_trait_cleanup() {
struct DatabaseConnection {
id: u32,
}
impl Drop for DatabaseConnection {
fn drop(&mut self) {
println!("Closing database connection: {}", self.id);
}
}
{
let _conn = DatabaseConnection { id: 1 };
println!("Database connection open");
}
println!("Connection automatically closed via Drop trait");
}
pub fn compare_c_vs_rust() {
raii_file_handling();
println!("\nC: Easy to forget resource cleanup (leaks)");
println!("Rust: RAII ensures automatic cleanup");
}
}
pub mod type_confusion {
pub fn strong_typing_prevents_confusion() {
let integer: i32 = 42;
let float: f64 = 3.14;
let result = integer as f64 + float;
println!("Explicit conversion required: {}", result);
}
pub fn newtype_pattern() {
struct UserId(u32);
struct ProductId(u32);
let user = UserId(123);
let product = ProductId(456);
println!("NewType pattern prevents mixing different ID types");
println!("User ID: {}, Product ID: {}", user.0, product.0);
}
pub fn enum_prevents_invalid_states() {
enum ConnectionState {
Disconnected,
Connecting,
Connected { session_id: String },
Error { message: String },
}
let state = ConnectionState::Connected {
session_id: "abc123".to_string(),
};
match state {
ConnectionState::Connected { session_id } => {
println!("Connected with session: {}", session_id);
}
_ => println!("Not connected"),
}
}
pub fn compare_c_vs_rust() {
println!("C: Type confusion through casting and unions");
println!("Rust: Strong type system prevents confusion at compile time");
strong_typing_prevents_confusion();
newtype_pattern();
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_buffer_overflow_examples() {
buffer_overflow::safe_array_access();
buffer_overflow::safe_string_handling();
buffer_overflow::compare_c_vs_rust();
}
#[test]
fn test_use_after_free_examples() {
use_after_free::ownership_prevents_uaf();
use_after_free::borrowing_prevents_dangling();
use_after_free::compare_c_vs_rust();
}
#[test]
fn test_data_race_examples() {
data_race::safe_concurrent_access();
data_race::type_system_prevents_races();
data_race::compare_c_vs_rust();
}
#[test]
fn test_integer_overflow_examples() {
integer_overflow::checked_arithmetic();
integer_overflow::saturating_arithmetic();
}
#[test]
fn test_null_pointer_examples() {
null_pointer::option_prevents_null();
null_pointer::compare_c_vs_rust();
}
#[test]
fn test_double_free_examples() {
double_free::ownership_prevents_double_free();
double_free::box_single_ownership();
double_free::compare_c_vs_rust();
}
#[test]
fn test_uninitialized_memory_examples() {
uninitialized_memory::initialization_required();
uninitialized_memory::array_initialization();
uninitialized_memory::struct_initialization();
uninitialized_memory::compare_c_vs_rust();
}
#[test]
fn test_memory_leak_examples() {
memory_leak::raii_file_handling();
memory_leak::drop_trait_cleanup();
memory_leak::compare_c_vs_rust();
}
#[test]
fn test_type_confusion_examples() {
type_confusion::strong_typing_prevents_confusion();
type_confusion::newtype_pattern();
type_confusion::enum_prevents_invalid_states();
type_confusion::compare_c_vs_rust();
}
}