Skip to content

Commit

Permalink
extract limited-deserialize crate
Browse files Browse the repository at this point in the history
  • Loading branch information
kevinheavey committed Oct 1, 2024
1 parent 489f483 commit 65ccdeb
Show file tree
Hide file tree
Showing 7 changed files with 99 additions and 48 deletions.
11 changes: 11 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ members = [
"sdk/gen-headers",
"sdk/hash",
"sdk/instruction",
"sdk/limited-deserialize",
"sdk/macro",
"sdk/msg",
"sdk/package-metadata-macro",
Expand Down Expand Up @@ -409,6 +410,7 @@ solana-inline-spl = { path = "inline-spl", version = "=2.1.0" }
solana-instruction = { path = "sdk/instruction", version = "=2.1.0", default-features = false }
solana-lattice-hash = { path = "lattice-hash", version = "=2.1.0" }
solana-ledger = { path = "ledger", version = "=2.1.0" }
solana-limited-deserialize = { path = "sdk/limited-deserialize", version = "=2.1.0" }
solana-loader-v4-program = { path = "programs/loader-v4", version = "=2.1.0" }
solana-local-cluster = { path = "local-cluster", version = "=2.1.0" }
solana-log-collector = { path = "log-collector", version = "=2.1.0" }
Expand Down
10 changes: 10 additions & 0 deletions programs/sbf/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 26 additions & 0 deletions sdk/limited-deserialize/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
[package]
name = "solana-limited-deserialize"
description = "Solana function for deserializing with a limit"
documentation = "https://docs.rs/solana-limited-deserialize"
version = { workspace = true }
authors = { workspace = true }
repository = { workspace = true }
homepage = { workspace = true }
license = { workspace = true }
edition = { workspace = true }

[dependencies]
bincode = { workspace = true }
serde = { workspace = true }
solana-instruction = { workspace = true, default-features = false, features = [
"std",
] }

[dev-dependencies]
solana-program = { path = "../program" }

[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

[lints]
workspace = true
48 changes: 48 additions & 0 deletions sdk/limited-deserialize/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
//! Contains a single utility function for deserializing from [bincode].
//!
//! [bincode]: https://docs.rs/bincode
use {bincode::config::Options, solana_instruction::error::InstructionError};

/// Deserialize with a limit based the maximum amount of data a program can expect to get.
/// This function should be used in place of direct deserialization to help prevent OOM errors
pub fn limited_deserialize<T>(instruction_data: &[u8], limit: u64) -> Result<T, InstructionError>
where
T: serde::de::DeserializeOwned,
{
bincode::options()
.with_limit(limit)
.with_fixint_encoding() // As per https://github.com/servo/bincode/issues/333, these two options are needed
.allow_trailing_bytes() // to retain the behavior of bincode::deserialize with the new `options()` method
.deserialize_from(instruction_data)
.map_err(|_| InstructionError::InvalidInstructionData)
}

#[cfg(test)]
pub mod tests {
use {super::*, solana_program::system_instruction::SystemInstruction};

#[test]
fn test_limited_deserialize_advance_nonce_account() {
let item = SystemInstruction::AdvanceNonceAccount;
let mut serialized = bincode::serialize(&item).unwrap();

assert_eq!(
serialized.len(),
4,
"`SanitizedMessage::get_durable_nonce()` may need a change"
);

assert_eq!(
limited_deserialize::<SystemInstruction>(&serialized, 4).as_ref(),
Ok(&item)
);
assert!(limited_deserialize::<SystemInstruction>(&serialized, 3).is_err());

serialized.push(0);
assert_eq!(
limited_deserialize::<SystemInstruction>(&serialized, 4).as_ref(),
Ok(&item)
);
}
}
1 change: 1 addition & 0 deletions sdk/program/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ solana-instruction = { workspace = true, default-features = false, features = [
"serde",
"std",
] }
solana-limited-deserialize = { workspace = true }
solana-msg = { workspace = true }
solana-program-error = { workspace = true, features = ["serde"] }
solana-program-memory = { workspace = true }
Expand Down
49 changes: 1 addition & 48 deletions sdk/program/src/program_utils.rs
Original file line number Diff line number Diff line change
@@ -1,48 +1 @@
//! Contains a single utility function for deserializing from [bincode].
//!
//! [bincode]: https://docs.rs/bincode
use {crate::instruction::InstructionError, bincode::config::Options};

/// Deserialize with a limit based the maximum amount of data a program can expect to get.
/// This function should be used in place of direct deserialization to help prevent OOM errors
pub fn limited_deserialize<T>(instruction_data: &[u8], limit: u64) -> Result<T, InstructionError>
where
T: serde::de::DeserializeOwned,
{
bincode::options()
.with_limit(limit)
.with_fixint_encoding() // As per https://github.com/servo/bincode/issues/333, these two options are needed
.allow_trailing_bytes() // to retain the behavior of bincode::deserialize with the new `options()` method
.deserialize_from(instruction_data)
.map_err(|_| InstructionError::InvalidInstructionData)
}

#[cfg(test)]
pub mod tests {
use {super::*, solana_program::system_instruction::SystemInstruction};

#[test]
fn test_limited_deserialize_advance_nonce_account() {
let item = SystemInstruction::AdvanceNonceAccount;
let mut serialized = bincode::serialize(&item).unwrap();

assert_eq!(
serialized.len(),
4,
"`SanitizedMessage::get_durable_nonce()` may need a change"
);

assert_eq!(
limited_deserialize::<SystemInstruction>(&serialized, 4).as_ref(),
Ok(&item)
);
assert!(limited_deserialize::<SystemInstruction>(&serialized, 3).is_err());

serialized.push(0);
assert_eq!(
limited_deserialize::<SystemInstruction>(&serialized, 4).as_ref(),
Ok(&item)
);
}
}
pub use solana_limited_deserialize::limited_deserialize;

0 comments on commit 65ccdeb

Please sign in to comment.