#Simple append-only storage of bytes

10 messages · Page 1 of 1 (latest)

runic cave
#

Miri doesn't complain when I use this code even if the HashMap gets reallocated, but there might be some caveat that I missed.
Is this safe ?

use std::collections::HashMap;
use std::sync::LazyLock;
use std::sync::Mutex;

static MAP: LazyLock<Mutex<HashMap<u64, Vec<u8>>>> = LazyLock::new(|| {
    Mutex::new(HashMap::new())
});

pub fn insert(code: u64, bytes: Vec<u8>) -> bool {
    let mut map = MAP.lock().unwrap();
    if map.contains_key(&code) {
        return false;
    }
    map.insert(code, bytes);
    true
}

pub fn get(code: u64) -> Option<&'static [u8]> {
    let map = MAP.lock().unwrap();
    let val = map.get(&code)?.as_slice();
    let val: &[u8] = val;
    let val: &'static [u8] = unsafe {
        // SAFETY: MAP is static and append-only,
        // so this value lives until the end of the program.
        &*(val as *const [u8])
    };
    Some(val)
}
crystal lodge
#

Yes that's pretty obvious ub because HashMap isn't append-only

#

How did you test it?

runic cave
#

Well the deletion is not accessible to the user.
I ran Miri+SB on

fn main() {
    assert!(insert(1, vec![1, 2, 3]));
    assert!(insert(2, vec![0]));
    let r1 = get(1).unwrap();
    dbg!(r1);
    dbg!(MAP.lock().unwrap().capacity());
    // Capacity is only 3, so this will probably force a reallocation
    for i in 3..100 {
        assert!(insert(i, vec![0, 1]));
    }
    dbg!(r1);
}
#

I'm open to alternatives if there's a much better way of doing something that has the same API.

crystal lodge
#

Ah right, the Vecs provide a second level of boxing which is stable across rehashes

runic cave
#

That's the idea.
Initially I had it in a Pin<Box<Vec<u8>>> but I thought that was probably redundant.

crystal lodge
#

Then I don't see anything obviously wrong, though perhaps you should clarify that part in the comment

#

Or you can leak the vecs and avoid unsafe altogether

runic cave
#

Oh that's neat. Yeah this is supposed to live forever so I don't mind leaking memory.