diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..76ed523 --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,65 @@ +on: [push, pull_request] + +name: CI + +jobs: + check: + name: Check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + override: true + - uses: actions-rs/cargo@v1 + with: + command: check + + test: + name: Test Suite + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + override: true + - uses: actions-rs/cargo@v1 + with: + command: test + args: -- --test-threads 1 + + fmt: + name: Rustfmt + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + override: true + - run: rustup component add rustfmt + - uses: actions-rs/cargo@v1 + with: + command: fmt + args: --all -- --check + + clippy: + name: Clippy + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + override: true + - run: rustup component add clippy + - uses: actions-rs/cargo@v1 + with: + command: clippy + args: -- -D warnings \ No newline at end of file diff --git a/src/map.rs b/src/map.rs index 23e0b0c..9a4b2a7 100644 --- a/src/map.rs +++ b/src/map.rs @@ -138,8 +138,14 @@ impl Shmap { // If an encryption key was provided, decrypt the value let bytes = if let Some(cipher) = &self.cipher { - let nonce = Nonce::from_slice(&mmap[..12]); - cipher.decrypt(nonce, &mmap[12..])? + // Check length of data - must be at least 12 bytes for nonce + // otherwise it's not a valid nonce. + if mmap.len() < 12 { + return Ok(None); + } else { + let nonce = Nonce::from_slice(&mmap[..12]); + cipher.decrypt(nonce, &mmap[12..])? + } } else { mmap.to_vec() }; @@ -262,8 +268,7 @@ impl Shmap { if let Ok(dir_entry) = dir_entry_res { let filename = dir_entry.file_name().to_string_lossy().to_string(); if filename.starts_with(SHMAP_PREFIX) && !filename.ends_with(METADATA_SUFFIX) { - let metadata_filename = - format!("{}.{}", dir_entry.path().to_string_lossy(), METADATA_SUFFIX); + let metadata_filename = format!("{}.{}", filename, METADATA_SUFFIX); match self.get_deserialize::(&metadata_filename) { Ok(Some(metadata)) => match metadata.expiration { Some(expiration) => { diff --git a/src/shm.rs b/src/shm.rs index 83f8514..ca293d8 100644 --- a/src/shm.rs +++ b/src/shm.rs @@ -8,6 +8,7 @@ use std::os::unix::io::RawFd; pub const SHM_DIR: &str = "/dev/shm"; /// File descriptor struct, allowing to close fd on Drop +#[derive(Debug)] pub struct Fd(RawFd); impl From for Fd { diff --git a/src/tests/map.rs b/src/tests/map.rs index ae4017f..fefa6a2 100644 --- a/src/tests/map.rs +++ b/src/tests/map.rs @@ -1,7 +1,7 @@ use crate::{map::sanitize_key, shm::shm_open_read, Shmap}; use memmap2::Mmap; use rand::{distributions::Alphanumeric, prelude::SliceRandom, thread_rng, Rng}; -use std::time::Duration; +use std::{collections::HashSet, time::Duration}; pub fn rand_string(len: usize) -> String { rand::thread_rng() @@ -320,3 +320,23 @@ fn test_metadatas_concurrency() { t1.join().unwrap(); t2.join().unwrap(); } + +// test key listing +#[test] +fn test_list_keys() { + const NUM: usize = 5; + let shmap = Shmap::new(); + + let keys = (0..NUM).map(|i| rand_string(i)).collect::>(); + keys.iter().for_each(|key| { + let value = rand_string(50); + shmap.insert(&key, value).unwrap(); + }); + + // Other tests may run in parallel. Ensure that at least NUM keys are present. + assert!(shmap.keys().unwrap().len() >= NUM); + + // At least all inserted keys must be present. + let current_keys = shmap.keys().unwrap().into_iter().collect(); + assert!(keys.is_subset(¤t_keys)); +}