Skip to content

Commit f17070c

Browse files
authored
fix: Limit decompression of UE4 crashes (#1121)
Applies the maximum Envelope size to limit decompression of UE4 crash archives. This a potential unbounded buffer allocation during decompression.
1 parent 1773151 commit f17070c

File tree

5 files changed

+40
-26
lines changed

5 files changed

+40
-26
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
**Bug Fixes**:
1111

1212
- Avoid unbounded decompression of encoded requests. A particular request crafted to inflate to large amounts of memory, such as a zip bomb, could put Relay out of memory. ([#1117](https://github.com/getsentry/relay/pull/1117))
13+
- Avoid unbounded decompression of UE4 crash reports. Some crash reports could inflate to large amounts of memory before being checked for size, which could put Relay out of memory. ([#1121](https://github.com/getsentry/relay/pull/1121))
14+
1315

1416
**Internal**:
1517

Cargo.lock

+16-16
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

relay-server/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ serde = { version = "1.0.114", features = ["derive"] }
6464
serde_json = "1.0.55"
6565
serde_urlencoded = "0.7.0"
6666
smallvec = { version = "1.4.0", features = ["serde"] }
67-
symbolic = { version = "8.0.4", optional = true, default-features=false, features=["unreal-serde"] }
67+
symbolic = { version = "8.4.0", optional = true, default-features=false, features=["unreal-serde"] }
6868
take_mut = "0.2.2"
6969
tokio = { version = "1.0", features = ["rt-multi-thread"] } # in sync with reqwest
7070
tokio-timer = "0.2.13"

relay-server/src/actors/envelopes.rs

+13-7
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ use {
6464
relay_filter::FilterStatKey,
6565
relay_general::store::{GeoIpLookup, StoreConfig, StoreProcessor},
6666
relay_quotas::{RateLimitingError, RedisRateLimiter},
67+
symbolic::unreal::{Unreal4Error, Unreal4ErrorKind},
6768
};
6869

6970
/// The minimum clock drift for correction to apply.
@@ -85,7 +86,7 @@ enum ProcessingError {
8586

8687
#[cfg(feature = "processing")]
8788
#[fail(display = "invalid unreal crash report")]
88-
InvalidUnrealReport(#[cause] symbolic::unreal::Unreal4Error),
89+
InvalidUnrealReport(#[cause] Unreal4Error),
8990

9091
#[fail(display = "event payload too large")]
9192
PayloadTooLarge,
@@ -202,6 +203,16 @@ impl ProcessingError {
202203
}
203204
}
204205

206+
#[cfg(feature = "processing")]
207+
impl From<Unreal4Error> for ProcessingError {
208+
fn from(err: Unreal4Error) -> Self {
209+
match err.kind() {
210+
Unreal4ErrorKind::TooLarge => Self::PayloadTooLarge,
211+
_ => ProcessingError::InvalidUnrealReport(err),
212+
}
213+
}
214+
}
215+
205216
/// Contains the required envelope related information to create an outcome.
206217
#[derive(Clone, Copy, Debug)]
207218
pub struct EnvelopeContext {
@@ -959,12 +970,7 @@ impl EnvelopeProcessor {
959970
let envelope = &mut state.envelope;
960971

961972
if let Some(item) = envelope.take_item_by(|item| item.ty() == ItemType::UnrealReport) {
962-
utils::expand_unreal_envelope(item, envelope)
963-
.map_err(ProcessingError::InvalidUnrealReport)?;
964-
965-
if !utils::check_envelope_size_limits(&self.config, envelope) {
966-
return Err(ProcessingError::PayloadTooLarge);
967-
}
973+
utils::expand_unreal_envelope(item, envelope, &self.config)?;
968974
}
969975

970976
Ok(())

relay-server/src/utils/unreal.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1+
use relay_config::Config;
12
use symbolic::unreal::{
2-
Unreal4Context, Unreal4Crash, Unreal4Error, Unreal4FileType, Unreal4LogEntry,
3+
Unreal4Context, Unreal4Crash, Unreal4Error, Unreal4ErrorKind, Unreal4FileType, Unreal4LogEntry,
34
};
45

56
use relay_general::protocol::{
@@ -47,9 +48,10 @@ fn get_event_item(data: &[u8]) -> Result<Option<Item>, Unreal4Error> {
4748
pub fn expand_unreal_envelope(
4849
unreal_item: Item,
4950
envelope: &mut Envelope,
51+
config: &Config,
5052
) -> Result<(), Unreal4Error> {
5153
let payload = unreal_item.payload();
52-
let crash = Unreal4Crash::parse(&payload)?;
54+
let crash = Unreal4Crash::parse_with_limit(&payload, config.max_envelope_size())?;
5355

5456
let mut has_event = envelope
5557
.get_item_by(|item| item.ty() == ItemType::Event)
@@ -86,6 +88,10 @@ pub fn expand_unreal_envelope(
8688
envelope.add_item(item);
8789
}
8890

91+
if !super::check_envelope_size_limits(config, envelope) {
92+
return Err(Unreal4ErrorKind::TooLarge.into());
93+
}
94+
8995
Ok(())
9096
}
9197

0 commit comments

Comments
 (0)