Skip to content

Commit 6053952

Browse files
authored
Switch from bincode to postcard for serializing (#8476)
Wasmtime and Cranelift have a few miscellaenous use cases for "just take this Rust type and make it bytes", for example Wasmtime's serialization of internal metadata into a compiled module. Previously Wasmtime used the `bincode` crate for performing these tasks as the format was generally optimized to be small and fast, not general purpose (e.g. JSON). The `bincode` crate on crates.io doesn't work on `no_std`, however, and with the work in #8341 that's an issue now for Wasmtime. This crate switches instead to the `postcard` crate. This crate is listed in Serde's documentation as: > Postcard, a no_std and embedded-systems friendly compact binary > format. While I've not personally used it before it checks all the boxes we relied on `bincode` for and additionally works with `no_std`. After auditing the crate this commit then switches out Wasmtime's usage of `bincode` for `postcard` throughout the repository.
1 parent b6e7cc3 commit 6053952

File tree

13 files changed

+68
-33
lines changed

13 files changed

+68
-33
lines changed

Cargo.lock

Lines changed: 27 additions & 13 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ test-log = { version = "0.2", default-features = false, features = ["trace"] }
290290
tracing-subscriber = { version = "0.3.1", default-features = false, features = ['fmt', 'env-filter', 'ansi', 'tracing-log'] }
291291
url = "2.3.1"
292292
humantime = "2.0.0"
293-
bincode = "1.2.1"
293+
postcard = { version = "1.0.8", default-features = false, features = ['alloc'] }
294294

295295
# =============================================================================
296296
#

cranelift/codegen/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ target-lexicon = { workspace = true }
2828
log = { workspace = true }
2929
serde = { workspace = true, optional = true }
3030
serde_derive = { workspace = true, optional = true }
31-
bincode = { workspace = true, optional = true }
31+
postcard = { workspace = true, optional = true }
3232
gimli = { workspace = true, features = ["write"], optional = true }
3333
smallvec = { workspace = true }
3434
regalloc2 = { workspace = true, features = ["checker", "trace-log"] }
@@ -100,7 +100,7 @@ enable-serde = [
100100
# Enable the incremental compilation cache for hot-reload use cases.
101101
incremental-cache = [
102102
"enable-serde",
103-
"bincode",
103+
"postcard",
104104
"sha2"
105105
]
106106

cranelift/codegen/src/incremental_cache.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -208,12 +208,12 @@ pub fn compute_cache_key(isa: &dyn TargetIsa, func: &Function) -> CacheKeyHash {
208208
/// of the function call. The value is left untouched.
209209
pub fn serialize_compiled(
210210
result: CompiledCodeStencil,
211-
) -> (CompiledCodeStencil, Result<Vec<u8>, bincode::Error>) {
211+
) -> (CompiledCodeStencil, Result<Vec<u8>, postcard::Error>) {
212212
let cached = CachedFunc {
213213
version_marker: VersionMarker,
214214
stencil: result,
215215
};
216-
let result = bincode::serialize(&cached);
216+
let result = postcard::to_allocvec(&cached);
217217
(cached.stencil, result)
218218
}
219219

@@ -223,15 +223,15 @@ pub enum RecompileError {
223223
/// The version embedded in the cache entry isn't the same as cranelift's current version.
224224
VersionMismatch,
225225
/// An error occurred while deserializing the cache entry.
226-
Deserialize(bincode::Error),
226+
Deserialize(postcard::Error),
227227
}
228228

229229
impl fmt::Display for RecompileError {
230230
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
231231
match self {
232232
RecompileError::VersionMismatch => write!(f, "cranelift version mismatch",),
233233
RecompileError::Deserialize(err) => {
234-
write!(f, "bincode failed during deserialization: {err}")
234+
write!(f, "postcard failed during deserialization: {err}")
235235
}
236236
}
237237
}
@@ -243,7 +243,7 @@ impl fmt::Display for RecompileError {
243243
/// Precondition: the bytes must have retrieved from a cache store entry which hash value
244244
/// is strictly the same as the `Function`'s computed hash retrieved from `compute_cache_key`.
245245
pub fn try_finish_recompile(func: &Function, bytes: &[u8]) -> Result<CompiledCode, RecompileError> {
246-
match bincode::deserialize::<CachedFunc>(bytes) {
246+
match postcard::from_bytes::<CachedFunc>(bytes) {
247247
Ok(result) => {
248248
if result.version_marker != func.stencil.version_marker {
249249
Err(RecompileError::VersionMismatch)

crates/cache/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ workspace = true
1414
[dependencies]
1515
anyhow = { workspace = true }
1616
base64 = "0.21.0"
17-
bincode = { workspace = true }
17+
postcard = { workspace = true }
1818
directories-next = "2.0"
1919
log = { workspace = true }
2020
serde = { workspace = true }

crates/cache/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@ impl<'config> ModuleCacheEntry<'config> {
5454
self.get_data_raw(
5555
&state,
5656
compute,
57-
|_state, data| bincode::serialize(data).ok(),
58-
|_state, data| bincode::deserialize(&data).ok(),
57+
|_state, data| postcard::to_allocvec(data).ok(),
58+
|_state, data| postcard::from_bytes(&data).ok(),
5959
)
6060
}
6161

crates/environ/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ workspace = true
1515

1616
[dependencies]
1717
anyhow = { workspace = true }
18-
bincode = { workspace = true }
18+
postcard = { workspace = true }
1919
cpp_demangle = { version = "0.4.3", optional = true }
2020
cranelift-entity = { workspace = true }
2121
wasmtime-types = { workspace = true }

crates/environ/src/compile/module_artifacts.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//! Definitions of runtime structures and metadata which are serialized into ELF
2-
//! with `bincode` as part of a module's compilation process.
2+
//! with `postcard` as part of a module's compilation process.
33
44
use crate::{
55
obj, CompiledFunctionInfo, CompiledModuleInfo, DebugInfoData, DefinedFuncIndex, FunctionLoc,
@@ -261,7 +261,7 @@ impl<'a> ObjectBuilder<'a> {
261261
obj::ELF_WASMTIME_INFO.as_bytes().to_vec(),
262262
SectionKind::ReadOnlyData,
263263
);
264-
let data = bincode::serialize(info).unwrap();
264+
let data = postcard::to_allocvec(info).unwrap();
265265
self.obj.set_section_data(section, data, 1);
266266
}
267267

crates/wasmtime/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ wat = { workspace = true, optional = true }
4444
serde = { workspace = true }
4545
serde_derive = { workspace = true }
4646
serde_json = { workspace = true }
47-
bincode = { workspace = true }
47+
postcard = { workspace = true }
4848
indexmap = { workspace = true }
4949
paste = "1.0.3"
5050
once_cell = { workspace = true }

crates/wasmtime/src/engine/serialization.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
//! 1. A version byte, currently `VERSION`.
1616
//! 2. A byte indicating how long the next field is.
1717
//! 3. A version string of the length of the previous byte value.
18-
//! 4. A `bincode`-encoded `Metadata` structure.
18+
//! 4. A `postcard`-encoded `Metadata` structure.
1919
//!
2020
//! This is hoped to help distinguish easily Wasmtime-based ELF files from
2121
//! other random ELF files, as well as provide better error messages for
@@ -110,7 +110,7 @@ pub fn check_compatible(engine: &Engine, mmap: &[u8], expected: ObjectKind) -> R
110110
}
111111
ModuleVersionStrategy::None => { /* ignore the version info, accept all */ }
112112
}
113-
bincode::deserialize::<Metadata<'_>>(data)?.check_compatible(engine)
113+
postcard::from_bytes::<Metadata<'_>>(data)?.check_compatible(engine)
114114
}
115115

116116
#[cfg(any(feature = "cranelift", feature = "winch"))]
@@ -134,7 +134,7 @@ pub fn append_compiler_info(engine: &Engine, obj: &mut Object<'_>, metadata: &Me
134134
);
135135
data.push(version.len() as u8);
136136
data.extend_from_slice(version.as_bytes());
137-
bincode::serialize_into(&mut data, metadata).unwrap();
137+
data.extend(postcard::to_allocvec(metadata).unwrap());
138138
obj.set_section_data(section, data, 1);
139139
}
140140

crates/wasmtime/src/runtime/component/component.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,7 @@ impl Component {
375375
static_modules,
376376
} = match artifacts {
377377
Some(artifacts) => artifacts,
378-
None => bincode::deserialize(code_memory.wasmtime_info())?,
378+
None => postcard::from_bytes(code_memory.wasmtime_info())?,
379379
};
380380

381381
// Validate that the component can be used with the current instance

crates/wasmtime/src/runtime/module.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -445,7 +445,7 @@ impl Module {
445445
// already.
446446
let (info, types) = match info_and_types {
447447
Some((info, types)) => (info, types),
448-
None => bincode::deserialize(code_memory.wasmtime_info())?,
448+
None => postcard::from_bytes(code_memory.wasmtime_info())?,
449449
};
450450

451451
// Register function type signatures into the engine for the lifetime

supply-chain/audits.toml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1062,6 +1062,12 @@ who = "Pat Hickey <[email protected]>"
10621062
criteria = "safe-to-deploy"
10631063
version = "0.2.0"
10641064

1065+
[[audits.cobs]]
1066+
who = "Alex Crichton <[email protected]>"
1067+
criteria = "safe-to-deploy"
1068+
version = "0.2.3"
1069+
notes = "No `unsafe` code in the crate and no usage of `std`"
1070+
10651071
[[audits.codespan-reporting]]
10661072
who = "Jamey Sharp <[email protected]>"
10671073
criteria = "safe-to-deploy"
@@ -1197,6 +1203,12 @@ This diff brings in a number of minor updates of which none are related to
11971203
`unsafe` code or anything system-related like filesystems.
11981204
"""
11991205

1206+
[[audits.embedded-io]]
1207+
who = "Alex Crichton <[email protected]>"
1208+
criteria = "safe-to-deploy"
1209+
version = "0.4.0"
1210+
notes = "No `unsafe` code and only uses `std` in ways one would expect the crate to do so."
1211+
12001212
[[audits.errno]]
12011213
who = "Dan Gohman <[email protected]>"
12021214
criteria = "safe-to-deploy"
@@ -2007,6 +2019,15 @@ No `unsafe` additions or anything outside of the purview of the crate in this
20072019
change.
20082020
"""
20092021

2022+
[[audits.postcard]]
2023+
who = "Alex Crichton <[email protected]>"
2024+
criteria = "safe-to-deploy"
2025+
version = "1.0.8"
2026+
notes = """
2027+
I've audited the unsafe code to do what it looks like it's doing. Otherwise the
2028+
crate is a standard serializer/deserializer crate.
2029+
"""
2030+
20102031
[[audits.pretty_env_logger]]
20112032
who = "Alex Crichton <[email protected]>"
20122033
criteria = "safe-to-deploy"

0 commit comments

Comments
 (0)