Skip to content

Commit 33e22bb

Browse files
authoredNov 10, 2022
fix: do not panic while encoding oversized bodies (#1142)
Fixes #1141.
1 parent 3a54270 commit 33e22bb

File tree

2 files changed

+44
-4
lines changed

2 files changed

+44
-4
lines changed
 

‎tonic/src/codec/encode.rs

+11-4
Original file line numberDiff line numberDiff line change
@@ -119,19 +119,26 @@ where
119119
}
120120

121121
// now that we know length, we can write the header
122-
Ok(finish_encoding(compression_encoding, buf))
122+
finish_encoding(compression_encoding, buf)
123123
}
124124

125-
fn finish_encoding(compression_encoding: Option<CompressionEncoding>, buf: &mut BytesMut) -> Bytes {
125+
fn finish_encoding(
126+
compression_encoding: Option<CompressionEncoding>,
127+
buf: &mut BytesMut,
128+
) -> Result<Bytes, Status> {
126129
let len = buf.len() - HEADER_SIZE;
127-
assert!(len <= std::u32::MAX as usize);
130+
if len > std::u32::MAX as usize {
131+
return Err(Status::resource_exhausted(format!(
132+
"Cannot return body with more than 4GB of data but got {len} bytes"
133+
)));
134+
}
128135
{
129136
let mut buf = &mut buf[..HEADER_SIZE];
130137
buf.put_u8(compression_encoding.is_some() as u8);
131138
buf.put_u32(len as u32);
132139
}
133140

134-
buf.split_to(len + HEADER_SIZE).freeze()
141+
Ok(buf.split_to(len + HEADER_SIZE).freeze())
135142
}
136143

137144
#[derive(Debug)]

‎tonic/src/codec/prost.rs

+33
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,39 @@ mod tests {
136136
}
137137
}
138138

139+
// skip on windows because CI stumbles over our 4GB allocation
140+
#[cfg(not(target_family = "windows"))]
141+
#[tokio::test]
142+
async fn encode_too_big() {
143+
let encoder = MockEncoder::default();
144+
145+
let msg = vec![0u8; u32::MAX as usize + 1];
146+
147+
let messages = std::iter::once(Ok::<_, Status>(msg));
148+
let source = futures_util::stream::iter(messages);
149+
150+
let body = encode_server(
151+
encoder,
152+
source,
153+
None,
154+
SingleMessageCompressionOverride::default(),
155+
);
156+
157+
futures_util::pin_mut!(body);
158+
159+
assert!(body.data().await.is_none());
160+
assert_eq!(
161+
body.trailers()
162+
.await
163+
.expect("no error polling trailers")
164+
.expect("some trailers")
165+
.get("grpc-status")
166+
.expect("grpc-status header"),
167+
"8"
168+
);
169+
assert!(body.is_end_stream());
170+
}
171+
139172
#[derive(Debug, Clone, Default)]
140173
struct MockEncoder;
141174

0 commit comments

Comments
 (0)
Please sign in to comment.