Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 31 additions & 1 deletion Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -772,6 +772,15 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e"

[[package]]
name = "convert_case"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "affbf0190ed2caf063e3def54ff444b449371d55c58e513a95ab98eca50adb49"
dependencies = [
"unicode-segmentation",
]

[[package]]
name = "cookie"
version = "0.18.1"
Expand Down Expand Up @@ -1140,7 +1149,7 @@ version = "0.99.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6edb4b64a43d977b8e99788fe3a04d483834fba1215a7e02caa415b626497f7f"
dependencies = [
"convert_case",
"convert_case 0.4.0",
"proc-macro2",
"quote",
"rustc_version",
Expand Down Expand Up @@ -2505,6 +2514,12 @@ dependencies = [
"spin",
]

[[package]]
name = "leb128"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c83bff1d572d6b9aeef67ddfc8448e4a3737909cb28e81f97c791b9018703e52"

[[package]]
name = "libbz2-rs-sys"
version = "0.2.5"
Expand Down Expand Up @@ -4038,6 +4053,18 @@ dependencies = [
"prost 0.14.4",
]

[[package]]
name = "proto-descriptors"
version = "0.1.0"
dependencies = [
"anyhow",
"clap",
"convert_case 0.11.0",
"prost 0.14.4",
"prost-types",
"relay-serialization",
]

[[package]]
name = "psl"
version = "2.1.216"
Expand Down Expand Up @@ -4986,6 +5013,8 @@ dependencies = [
name = "relay-serialization"
version = "26.7.2"
dependencies = [
"leb128",
"prost 0.14.4",
"serde",
"serde_json",
]
Expand Down Expand Up @@ -5060,6 +5089,7 @@ dependencies = [
"relay-redis",
"relay-replays",
"relay-sampling",
"relay-serialization",
"relay-spans",
"relay-statsd",
"relay-system",
Expand Down
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ insta = { version = "1", features = ["json", "redactions", "ron"] }
ipnetwork = "0.21"
itertools = "0.14"
json-forensics = "0.1"
leb128 = "0.2.7"
libc = "0.2"
liblzma = "0.4"
lru = "0.16"
Expand Down
2 changes: 2 additions & 0 deletions relay-serialization/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ publish = false
workspace = true

[dependencies]
prost = { workspace = true }
serde = { workspace = true }
leb128 = { workspace = true }

[dev-dependencies]
serde_json = { workspace = true }
3 changes: 3 additions & 0 deletions relay-serialization/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,7 @@

#![warn(missing_docs)]

mod meter;

pub mod prost;
pub mod serde;
56 changes: 56 additions & 0 deletions relay-serialization/src/meter.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
//! The operation budget shared by every bounded deserializer in this crate.

use std::fmt;

/// A budget for the ops a single deserialization is allowed to spend.
pub(crate) struct Meter {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We avoid pub(...), this can be public as long as the module isn't (which it isn't).

limit: usize,
remaining: usize,
exceeded: bool,
}

impl Meter {
/// Creates a meter which allows spending at most `limit` operations.
pub fn new(limit: usize) -> Self {
Self {
limit,
remaining: limit,
exceeded: false,
}
}

/// Returns the number of ops spent.
pub fn spent(&self) -> usize {
self.limit - self.remaining
}

/// Returns true if we've exceeded our budget.
pub fn exceeded(&self) -> bool {
self.exceeded
}

/// Tries to charge `amount` operations to the budget. If we exceed, we return an error,
/// set the remaining budget to 0, and mark the budget as exceeded.
pub fn spend(&mut self, amount: usize) -> Result<(), LimitExceeded> {
match self.remaining.checked_sub(amount) {
Some(remaining) => {
self.remaining = remaining;
Ok(())
}
None => {
self.remaining = 0;
self.exceeded = true;
Err(LimitExceeded)
}
}
}
}

/// The error produced when a [`Meter`] runs out of budget.
pub(crate) struct LimitExceeded;

impl fmt::Display for LimitExceeded {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "deserialization exceeds the operation budget")
}
}
9 changes: 9 additions & 0 deletions relay-serialization/src/prost/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
//! Deserialization routines for prost.
//! This implements a scanner to record the number of "operations" needed to decode a proto,
//! allowing a caller to enforce a hard limit on how much work to be done.
mod scan;

pub use scan::Error;
pub use scan::MessageDesc;
pub use scan::decode;
pub use scan::scan;
Loading
Loading