Search code examples
rusthjson

How to handle "attempted to leave type linked_hash_map::Node uninitialized" when using the hjson crate?


I want to use the hjson format with my program. However, it seems the crate is pretty old. An updated fork is at https://github.com/shi-yan/hjson-rust, which is what I used in my program. Below is my testing program.

# Cargo.toml
[dependencies]
hjson = { git = "https://github.com/shi-yan/hjson-rust", branch = "master" }
serde = "1.0.102"
serde-hjson = "0.9.1"
//! src/main.rs
use serde_hjson::{Value, Map};

fn main() {
    let data = r###"
{
    name: test3
    tag : username, password
}
"###;

    let mut xx: Map<String, Value> = serde_hjson::from_str(&data).unwrap();
}

When I run it, I got the following error:

thread 'main' panicked at 'attempted to leave type `linked_hash_map::Node<alloc::string::String, value::Value>` uninitialized, which is invalid', C:\Users\user1\.cargo\registry\src\github.com-1ecc6299db9ec823\linked-hash-map-0.3.0\src\lib.rs:203:52
stack backtrace:
   0: std::panicking::begin_panic_handler
             at /rustc/4b91a6ea7258a947e59c6522cd5898e7c0a6a88f/library\std\src\panicking.rs:584
   1: core::panicking::panic_fmt
             at /rustc/4b91a6ea7258a947e59c6522cd5898e7c0a6a88f/library\core\src\panicking.rs:142
   2: core::panicking::panic
             at /rustc/4b91a6ea7258a947e59c6522cd5898e7c0a6a88f/library\core\src\panicking.rs:48
   3: core::mem::uninitialized
             at /rustc/4b91a6ea7258a947e59c6522cd5898e7c0a6a88f\library\core\src\mem\mod.rs:685
   4: linked_hash_map::LinkedHashMap<alloc::string::String,enum$<serde_hjson::value::Value>,std::collections::hash::map::RandomState>::insert<alloc::string::String,enum$<serde_hjson::value::Value>,std::collections::hash::map::RandomState>
             at C:\Users\user1\.cargo\registry\src\github.com-1ecc6299db9ec823\linked-hash-map-0.3.0\src\lib.rs:203
   5: linked_hash_map::serde::impl$2::visit_map<alloc::string::String,enum$<serde_hjson::value::Value>,serde_hjson::de::MapVisitor<core::iter::adapters::map::Map<core::slice::iter::Iter<u8>,serde_hjson::de::from_iter::closure_env$2<core::iter::adapters::map::Ma
             at C:\Users\user1\.cargo\registry\src\github.com-1ecc6299db9ec823\linked-hash-map-0.3.0\src\serde.rs:72
   6: serde_hjson::de::Deserializer<core::iter::adapters::map::Map<core::slice::iter::Iter<u8>,serde_hjson::de::from_iter::closure_env$2<core::iter::adapters::map::Map<core::slice::iter::Iter<u8>,serde_hjson::de::from_slice::closure_env$0<linked_hash_map::Linke
             at C:\Users\user1\.cargo\registry\src\github.com-1ecc6299db9ec823\serde-hjson-0.9.1\src\de.rs:151
   7: serde_hjson::de::impl$1::deserialize<core::iter::adapters::map::Map<core::slice::iter::Iter<u8>,serde_hjson::de::from_iter::closure_env$2<core::iter::adapters::map::Map<core::slice::iter::Iter<u8>,serde_hjson::de::from_slice::closure_env$0<linked_hash_map
             at C:\Users\user1\.cargo\registry\src\github.com-1ecc6299db9ec823\serde-hjson-0.9.1\src\de.rs:443
   8: serde_hjson::de::impl$1::deserialize_map<core::iter::adapters::map::Map<core::slice::iter::Iter<u8>,serde_hjson::de::from_iter::closure_env$2<core::iter::adapters::map::Map<core::slice::iter::Iter<u8>,serde_hjson::de::from_slice::closure_env$0<linked_hash
             at C:\Users\user1\.cargo\registry\src\github.com-1ecc6299db9ec823\serde-hjson-0.9.1\src\forward.rs:35
   9: linked_hash_map::serde::impl$3::deserialize<alloc::string::String,enum$<serde_hjson::value::Value>,serde_hjson::de::Deserializer<core::iter::adapters::map::Map<core::slice::iter::Iter<u8>,serde_hjson::de::from_iter::closure_env$2<core::iter::adapters::map
             at C:\Users\user1\.cargo\registry\src\github.com-1ecc6299db9ec823\linked-hash-map-0.3.0\src\serde.rs:88
  10: serde_hjson::de::from_iter<core::iter::adapters::map::Map<core::slice::iter::Iter<u8>,serde_hjson::de::from_slice::closure_env$0<linked_hash_map::LinkedHashMap<alloc::string::String,enum$<serde_hjson::value::Value>,std::collections::hash::map::RandomState
             at C:\Users\user1\.cargo\registry\src\github.com-1ecc6299db9ec823\serde-hjson-0.9.1\src\de.rs:813
  11: serde_hjson::de::from_slice<linked_hash_map::LinkedHashMap<alloc::string::String,enum$<serde_hjson::value::Value>,std::collections::hash::map::RandomState> >
             at C:\Users\user1\.cargo\registry\src\github.com-1ecc6299db9ec823\serde-hjson-0.9.1\src\de.rs:846
  12: serde_hjson::de::from_str<linked_hash_map::LinkedHashMap<alloc::string::String,enum$<serde_hjson::value::Value>,std::collections::hash::map::RandomState> >
             at C:\Users\user1\.cargo\registry\src\github.com-1ecc6299db9ec823\serde-hjson-0.9.1\src\de.rs:853
  13: test3::main
             at .\src\main.rs:13
  14: core::ops::function::FnOnce::call_once<void (*)(),tuple$<> >
             at /rustc/4b91a6ea7258a947e59c6522cd5898e7c0a6a88f\library\core\src\ops\function.rs:248
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
error: process didn't exit successfully: `target\debug\test3.exe` (exit code: 101)

Process finished with exit code 101

I have no idea what's happening here. Could anyone give me some help?


Solution

  • In short: the version you're using is unsound, and std converted this unsoundness to panic.

    You can see that the panic originates inside std::mem::uninitialized. This panic shows that the type it was trying to create has invalid bit patterns (since it contains the corresponding key, which in your case is String, and String has a non-null pointer field), therefore having an uninitialized value of this type is UB, which panic prevents. There's nothing you can do while remaining on the same versions of dependencies - that's the bug in linked_hash_map.

    Now, what you can do?

    • You can disable the preserve-order feature of serde_hjson, which is the reason for pulling in linked_hash_map. This is done by using the following line in your Cargo.toml:
    serde-hjson = { version = "0.9.1", default-features = false }
    

    In this case you, obviously, will lose the order of keys in your maps, but I assume that they're not so important.

    • Or you can move to the fork of serde_hjson, used by nushell - that is, to nu-json; it uses the updated version of linked_hash_map, which doesn't have this unsoundness.