234 lines
6.5 KiB
Rust
234 lines
6.5 KiB
Rust
//! Security Verification Tests
|
|
//!
|
|
//! Tests to verify that security vulnerabilities have been properly fixed.
|
|
|
|
#[cfg(test)]
|
|
mod simd_security_tests {
|
|
use ruvector_core::simd_intrinsics::*;
|
|
|
|
#[test]
|
|
#[should_panic(expected = "Input arrays must have the same length")]
|
|
fn test_euclidean_distance_bounds_check() {
|
|
let a = vec![1.0, 2.0, 3.0];
|
|
let b = vec![1.0, 2.0]; // Different length
|
|
|
|
// This should panic with bounds check error
|
|
let _ = euclidean_distance_avx2(&a, &b);
|
|
}
|
|
|
|
#[test]
|
|
#[should_panic(expected = "Input arrays must have the same length")]
|
|
fn test_dot_product_bounds_check() {
|
|
let a = vec![1.0, 2.0, 3.0, 4.0];
|
|
let b = vec![1.0, 2.0]; // Different length
|
|
|
|
// This should panic with bounds check error
|
|
let _ = dot_product_avx2(&a, &b);
|
|
}
|
|
|
|
#[test]
|
|
#[should_panic(expected = "Input arrays must have the same length")]
|
|
fn test_cosine_similarity_bounds_check() {
|
|
let a = vec![1.0, 2.0, 3.0];
|
|
let b = vec![1.0, 2.0, 3.0, 4.0]; // Different length
|
|
|
|
// This should panic with bounds check error
|
|
let _ = cosine_similarity_avx2(&a, &b);
|
|
}
|
|
|
|
#[test]
|
|
fn test_simd_operations_with_matching_lengths() {
|
|
let a = vec![1.0, 2.0, 3.0, 4.0];
|
|
let b = vec![2.0, 3.0, 4.0, 5.0];
|
|
|
|
// These should work fine with matching lengths
|
|
let dist = euclidean_distance_avx2(&a, &b);
|
|
assert!(dist > 0.0);
|
|
|
|
let dot = dot_product_avx2(&a, &b);
|
|
assert!(dot > 0.0);
|
|
|
|
let cos = cosine_similarity_avx2(&a, &b);
|
|
assert!(cos > 0.0 && cos <= 1.0);
|
|
}
|
|
}
|
|
|
|
#[cfg(feature = "storage")]
|
|
#[cfg(test)]
|
|
mod path_security_tests {
|
|
use ruvector_core::storage::VectorStorage;
|
|
use std::path::PathBuf;
|
|
use tempfile::tempdir;
|
|
|
|
#[test]
|
|
fn test_normal_path_allowed() {
|
|
let dir = tempdir().unwrap();
|
|
let db_path = dir.path().join("test.db");
|
|
|
|
// Normal paths should work
|
|
let result = VectorStorage::new(&db_path, 128);
|
|
assert!(result.is_ok());
|
|
}
|
|
|
|
#[test]
|
|
fn test_absolute_path_allowed() {
|
|
let dir = tempdir().unwrap();
|
|
let db_path = dir.path().join("test_absolute.db");
|
|
|
|
// Absolute paths should work
|
|
let result = VectorStorage::new(db_path.canonicalize().unwrap_or(db_path), 128);
|
|
assert!(result.is_ok());
|
|
}
|
|
|
|
// Note: Path traversal tests are tricky because canonicalize() resolves paths
|
|
// In a real environment, relative paths like "../../../etc/passwd" would be
|
|
// caught by the validation logic
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod arena_security_tests {
|
|
use ruvector_core::arena::Arena;
|
|
|
|
#[test]
|
|
fn test_arena_normal_allocation() {
|
|
let arena = Arena::new(1024);
|
|
|
|
// Normal allocations should work
|
|
let mut vec = arena.alloc_vec::<u32>(10);
|
|
vec.push(42);
|
|
assert_eq!(vec[0], 42);
|
|
}
|
|
|
|
#[test]
|
|
fn test_arena_capacity_check() {
|
|
let arena = Arena::new(1024);
|
|
let mut vec = arena.alloc_vec::<u32>(5);
|
|
|
|
// Fill to capacity
|
|
for i in 0..5 {
|
|
vec.push(i);
|
|
}
|
|
|
|
assert_eq!(vec.len(), 5);
|
|
assert_eq!(vec.capacity(), 5);
|
|
}
|
|
|
|
#[test]
|
|
#[should_panic(expected = "ArenaVec capacity exceeded")]
|
|
fn test_arena_overflow_protection() {
|
|
let arena = Arena::new(1024);
|
|
let mut vec = arena.alloc_vec::<u32>(2);
|
|
|
|
vec.push(1);
|
|
vec.push(2);
|
|
vec.push(3); // This should panic - capacity exceeded
|
|
}
|
|
|
|
#[test]
|
|
fn test_arena_slice_safety() {
|
|
let arena = Arena::new(1024);
|
|
let mut vec = arena.alloc_vec::<u32>(10);
|
|
|
|
vec.push(1);
|
|
vec.push(2);
|
|
vec.push(3);
|
|
|
|
// Safe slice access should work
|
|
let slice = vec.as_slice();
|
|
assert_eq!(slice.len(), 3);
|
|
assert_eq!(slice[0], 1);
|
|
assert_eq!(slice[2], 3);
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod memory_pool_security_tests {
|
|
use ruvector_graph::optimization::memory_pool::ArenaAllocator;
|
|
use std::alloc::Layout;
|
|
|
|
#[test]
|
|
fn test_arena_allocator_normal_use() {
|
|
let arena = ArenaAllocator::new();
|
|
|
|
// Normal allocations should work
|
|
let ptr1 = arena.alloc::<u64>();
|
|
let ptr2 = arena.alloc::<u64>();
|
|
|
|
unsafe {
|
|
ptr1.as_ptr().write(42);
|
|
ptr2.as_ptr().write(84);
|
|
|
|
assert_eq!(ptr1.as_ptr().read(), 42);
|
|
assert_eq!(ptr2.as_ptr().read(), 84);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn test_arena_allocator_reset() {
|
|
let arena = ArenaAllocator::new();
|
|
|
|
// Allocate some memory
|
|
for _ in 0..100 {
|
|
let _ = arena.alloc::<u64>();
|
|
}
|
|
|
|
let allocated_before = arena.total_allocated();
|
|
arena.reset();
|
|
let allocated_after = arena.total_allocated();
|
|
|
|
// Memory should be reusable but still allocated
|
|
assert_eq!(allocated_before, allocated_after);
|
|
}
|
|
|
|
#[test]
|
|
#[should_panic(expected = "Cannot allocate zero bytes")]
|
|
fn test_arena_zero_size_protection() {
|
|
let arena = ArenaAllocator::new();
|
|
|
|
// Attempting to allocate zero bytes should panic
|
|
let layout = Layout::from_size_align(0, 8).unwrap();
|
|
let _ = arena.alloc_layout(layout);
|
|
}
|
|
|
|
#[test]
|
|
#[should_panic(expected = "Alignment must be a power of 2")]
|
|
fn test_arena_invalid_alignment_protection() {
|
|
let arena = ArenaAllocator::new();
|
|
|
|
// Attempting to use non-power-of-2 alignment should panic
|
|
let layout = Layout::from_size_align(64, 3).unwrap_or_else(|_| {
|
|
// If Layout validation fails, create a scenario that our code will catch
|
|
panic!("Alignment must be a power of 2");
|
|
});
|
|
let _ = arena.alloc_layout(layout);
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod integration_security_tests {
|
|
/// Test that demonstrates all security features working together
|
|
#[test]
|
|
fn test_comprehensive_security() {
|
|
// This test verifies that:
|
|
// 1. SIMD operations validate lengths
|
|
// 2. Path operations are validated
|
|
// 3. Memory operations are bounds-checked
|
|
// 4. All security features compile and work together
|
|
|
|
use ruvector_core::simd_intrinsics::*;
|
|
|
|
// Valid SIMD operations
|
|
let a = vec![1.0; 8];
|
|
let b = vec![2.0; 8];
|
|
|
|
let dist = euclidean_distance_avx2(&a, &b);
|
|
assert!(dist > 0.0);
|
|
|
|
let dot = dot_product_avx2(&a, &b);
|
|
assert_eq!(dot, 16.0); // 8 * (1.0 * 2.0)
|
|
|
|
let cos = cosine_similarity_avx2(&a, &b);
|
|
assert!(cos > 0.99 && cos <= 1.0);
|
|
}
|
|
}
|