Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: hyperium/tonic
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v0.10.1
Choose a base ref
...
head repository: hyperium/tonic
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v0.10.2
Choose a head ref
  • 2 commits
  • 16 files changed
  • 1 contributor

Commits on Sep 28, 2023

  1. fix(web): Client decoding incomplete buffer bug (#1540)

    When the server returns a buffer that contains the message and a few
    more bytes we previously did not return the end of the message and thus
    tossed the begining of the bytes of the next message causing the
    following ones to report incorrect length and triggering eof errors.
    LucioFranco authored Sep 28, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    83e363a View commit details
  2. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    b3fca19 View commit details
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
# [0.10.2](https://github.com/hyperium/tonic/compare/v0.10.1...v0.10.2) (2023-09-28)


### Bug Fixes

* **web:** Client decoding incomplete buffer bug ([#1540](https://github.com/hyperium/tonic/issues/1540)) ([83e363a](https://github.com/hyperium/tonic/commit/83e363ace6cbe20ccc2efbe1eb10a4236e4b8065))


# [0.10.1](https://github.com/hyperium/tonic/compare/v0.10.0...v0.10.1) (2023-09-21)

### Bug Fixes
4 changes: 2 additions & 2 deletions tonic-build/Cargo.toml
Original file line number Diff line number Diff line change
@@ -4,15 +4,15 @@ categories = ["network-programming", "asynchronous"]
description = """
Codegen module of `tonic` gRPC implementation.
"""
documentation = "https://docs.rs/tonic-build/0.10.1"
documentation = "https://docs.rs/tonic-build/0.10.2"
edition = "2021"
homepage = "https://github.com/hyperium/tonic"
keywords = ["rpc", "grpc", "async", "codegen", "protobuf"]
license = "MIT"
name = "tonic-build"
readme = "README.md"
repository = "https://github.com/hyperium/tonic"
version = "0.10.1"
version = "0.10.2"

[dependencies]
prettyplease = { version = "0.2" }
2 changes: 1 addition & 1 deletion tonic-build/src/lib.rs
Original file line number Diff line number Diff line change
@@ -70,7 +70,7 @@
html_logo_url = "https://raw.githubusercontent.com/tokio-rs/website/master/public/img/icons/tonic.svg"
)]
#![deny(rustdoc::broken_intra_doc_links)]
#![doc(html_root_url = "https://docs.rs/tonic-build/0.10.1")]
#![doc(html_root_url = "https://docs.rs/tonic-build/0.10.2")]
#![doc(issue_tracker_base_url = "https://github.com/hyperium/tonic/issues/")]
#![doc(test(no_crate_inject, attr(deny(rust_2018_idioms))))]
#![cfg_attr(docsrs, feature(doc_cfg))]
4 changes: 2 additions & 2 deletions tonic-health/Cargo.toml
Original file line number Diff line number Diff line change
@@ -4,15 +4,15 @@ categories = ["network-programming", "asynchronous"]
description = """
Health Checking module of `tonic` gRPC implementation.
"""
documentation = "https://docs.rs/tonic-health/0.10.1"
documentation = "https://docs.rs/tonic-health/0.10.2"
edition = "2021"
homepage = "https://github.com/hyperium/tonic"
keywords = ["rpc", "grpc", "async", "healthcheck"]
license = "MIT"
name = "tonic-health"
readme = "README.md"
repository = "https://github.com/hyperium/tonic"
version = "0.10.1"
version = "0.10.2"

[features]
default = ["transport"]
2 changes: 1 addition & 1 deletion tonic-health/src/lib.rs
Original file line number Diff line number Diff line change
@@ -16,7 +16,7 @@
html_logo_url = "https://raw.githubusercontent.com/tokio-rs/website/master/public/img/icons/tonic.svg"
)]
#![deny(rustdoc::broken_intra_doc_links)]
#![doc(html_root_url = "https://docs.rs/tonic-health/0.10.1")]
#![doc(html_root_url = "https://docs.rs/tonic-health/0.10.2")]
#![doc(issue_tracker_base_url = "https://github.com/hyperium/tonic/issues/")]
#![doc(test(no_crate_inject, attr(deny(rust_2018_idioms))))]
#![cfg_attr(docsrs, feature(doc_cfg))]
4 changes: 2 additions & 2 deletions tonic-reflection/Cargo.toml
Original file line number Diff line number Diff line change
@@ -9,13 +9,13 @@ Server Reflection module of `tonic` gRPC implementation.
"""
edition = "2021"
homepage = "https://github.com/hyperium/tonic"
documentation = "https://docs.rs/tonic-reflection/0.10.1"
documentation = "https://docs.rs/tonic-reflection/0.10.2"
keywords = ["rpc", "grpc", "async", "reflection"]
license = "MIT"
name = "tonic-reflection"
readme = "README.md"
repository = "https://github.com/hyperium/tonic"
version = "0.10.1"
version = "0.10.2"

[dependencies]
prost = "0.12"
2 changes: 1 addition & 1 deletion tonic-reflection/src/lib.rs
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@
html_logo_url = "https://github.com/hyperium/tonic/raw/master/.github/assets/tonic-docs.png"
)]
#![deny(rustdoc::broken_intra_doc_links)]
#![doc(html_root_url = "https://docs.rs/tonic-reflection/0.10.1")]
#![doc(html_root_url = "https://docs.rs/tonic-reflection/0.10.2")]
#![doc(issue_tracker_base_url = "https://github.com/hyperium/tonic/issues/")]
#![doc(test(no_crate_inject, attr(deny(rust_2018_idioms))))]
#![cfg_attr(docsrs, feature(doc_cfg))]
4 changes: 2 additions & 2 deletions tonic-types/Cargo.toml
Original file line number Diff line number Diff line change
@@ -7,15 +7,15 @@ categories = ["web-programming", "network-programming", "asynchronous"]
description = """
A collection of useful protobuf types that can be used with `tonic`.
"""
documentation = "https://docs.rs/tonic-types/0.10.1"
documentation = "https://docs.rs/tonic-types/0.10.2"
edition = "2021"
homepage = "https://github.com/hyperium/tonic"
keywords = ["rpc", "grpc", "protobuf"]
license = "MIT"
name = "tonic-types"
readme = "README.md"
repository = "https://github.com/hyperium/tonic"
version = "0.10.1"
version = "0.10.2"

[dependencies]
prost = "0.12"
2 changes: 1 addition & 1 deletion tonic-types/src/lib.rs
Original file line number Diff line number Diff line change
@@ -150,7 +150,7 @@
html_logo_url = "https://raw.githubusercontent.com/tokio-rs/website/master/public/img/icons/tonic.svg"
)]
#![deny(rustdoc::broken_intra_doc_links)]
#![doc(html_root_url = "https://docs.rs/tonic-types/0.10.1")]
#![doc(html_root_url = "https://docs.rs/tonic-types/0.10.2")]
#![doc(issue_tracker_base_url = "https://github.com/hyperium/tonic/issues/")]

mod generated {
4 changes: 2 additions & 2 deletions tonic-web/Cargo.toml
Original file line number Diff line number Diff line change
@@ -4,15 +4,15 @@ categories = ["network-programming", "asynchronous"]
description = """
grpc-web protocol translation for tonic services.
"""
documentation = "https://docs.rs/tonic-web/0.10.1"
documentation = "https://docs.rs/tonic-web/0.10.2"
edition = "2021"
homepage = "https://github.com/hyperium/tonic"
keywords = ["rpc", "grpc", "grpc-web"]
license = "MIT"
name = "tonic-web"
readme = "README.md"
repository = "https://github.com/hyperium/tonic"
version = "0.10.1"
version = "0.10.2"

[dependencies]
base64 = "0.21"
88 changes: 54 additions & 34 deletions tonic-web/src/call.rs
Original file line number Diff line number Diff line change
@@ -245,36 +245,41 @@ where
let mut me = self.as_mut();

loop {
let buf = ready!(me.as_mut().poll_decode(cx));

return if let Some(Ok(incoming_buf)) = buf {
let buf = &mut me.as_mut().project().buf;

buf.put(incoming_buf);

match find_trailers(&buf[..]) {
FindTrailers::Trailer(len) => {
// Extract up to len of where the trailers are at
let msg_buf = buf.copy_to_bytes(len);
match decode_trailers_frame(buf.split().freeze()) {
Ok(Some(trailers)) => {
self.project().trailers.replace(trailers);
}
Err(e) => return Poll::Ready(Some(Err(e))),
_ => {}
}
let incoming_buf = match ready!(me.as_mut().poll_decode(cx)) {
Some(Ok(incoming_buf)) => incoming_buf,
None => {
// TODO: Consider eofing here?
// Even if the buffer has more data, this will hit the eof branch
// of decode in tonic
return Poll::Ready(None);
}
Some(Err(e)) => return Poll::Ready(Some(Err(e))),
};

let buf = &mut me.as_mut().project().buf;

if msg_buf.has_remaining() {
return Poll::Ready(Some(Ok(msg_buf)));
} else {
return Poll::Ready(None);
buf.put(incoming_buf);

return match find_trailers(&buf[..])? {
FindTrailers::Trailer(len) => {
// Extract up to len of where the trailers are at
let msg_buf = buf.copy_to_bytes(len);
match decode_trailers_frame(buf.split().freeze()) {
Ok(Some(trailers)) => {
self.project().trailers.replace(trailers);
}
Err(e) => return Poll::Ready(Some(Err(e))),
_ => {}
}

if msg_buf.has_remaining() {
Poll::Ready(Some(Ok(msg_buf)))
} else {
Poll::Ready(None)
}
FindTrailers::IncompleteBuf => continue,
FindTrailers::Done => Poll::Ready(Some(Ok(buf.split().freeze()))),
}
} else {
Poll::Ready(buf)
FindTrailers::IncompleteBuf => continue,
FindTrailers::Done(len) => Poll::Ready(Some(Ok(buf.split_to(len).freeze()))),
};
}
}
@@ -421,21 +426,25 @@ fn make_trailers_frame(trailers: HeaderMap) -> Vec<u8> {
/// its location in the original buf. If `None` is returned we did
/// not find a trailers in this buffer either because its incomplete
/// or the buffer jsut contained grpc message frames.
fn find_trailers(buf: &[u8]) -> FindTrailers {
fn find_trailers(buf: &[u8]) -> Result<FindTrailers, Status> {
let mut len = 0;
let mut temp_buf = &buf[..];

loop {
// To check each frame, there must be at least GRPC_HEADER_SIZE
// amount of bytes available otherwise the buffer is incomplete.
if temp_buf.is_empty() || temp_buf.len() < GRPC_HEADER_SIZE {
return FindTrailers::Done;
return Ok(FindTrailers::Done(len));
}

let header = temp_buf.get_u8();

if header == GRPC_WEB_TRAILERS_BIT {
return FindTrailers::Trailer(len);
return Ok(FindTrailers::Trailer(len));
}

if !(header == 0 || header == 1) {
return Err(Status::internal("Invalid header bit {} expected 0 or 1"));
}

let msg_len = temp_buf.get_u32();
@@ -445,7 +454,7 @@ fn find_trailers(buf: &[u8]) -> FindTrailers {
// If the msg len of a non-grpc-web trailer frame is larger than
// the overall buffer we know within that buffer there are no trailers.
if len > buf.len() {
return FindTrailers::IncompleteBuf;
return Ok(FindTrailers::IncompleteBuf);
}

temp_buf = &buf[len as usize..];
@@ -456,11 +465,13 @@ fn find_trailers(buf: &[u8]) -> FindTrailers {
enum FindTrailers {
Trailer(usize),
IncompleteBuf,
Done,
Done(usize),
}

#[cfg(test)]
mod tests {
use tonic::Code;

use super::*;

#[test]
@@ -507,7 +518,7 @@ mod tests {
128, 0, 0, 0, 15, 103, 114, 112, 99, 45, 115, 116, 97, 116, 117, 115, 58, 48, 13, 10,
];

let out = find_trailers(&buf[..]);
let out = find_trailers(&buf[..]).unwrap();

assert_eq!(out, FindTrailers::Trailer(0));
}
@@ -524,7 +535,7 @@ mod tests {
15, 103, 114, 112, 99, 45, 115, 116, 97, 116, 117, 115, 58, 48, 13, 10,
];

let out = find_trailers(&buf[..]);
let out = find_trailers(&buf[..]).unwrap();

assert_eq!(out, FindTrailers::Trailer(81));

@@ -566,8 +577,17 @@ mod tests {
105, 116, 116, 101, 110, 32, 98, 121, 32,
];

let out = find_trailers(&buf[..]);
let out = find_trailers(&buf[..]).unwrap();

assert_eq!(out, FindTrailers::IncompleteBuf);
}

#[test]
#[ignore]
fn find_trailers_buffered_incomplete_buf_bug() {
let buf = std::fs::read("tests/incomplete-buf-bug.bin").unwrap();
let out = find_trailers(&buf[..]).unwrap_err();

assert_eq!(out.code(), Code::Internal);
}
}
2 changes: 1 addition & 1 deletion tonic-web/src/lib.rs
Original file line number Diff line number Diff line change
@@ -94,7 +94,7 @@
rust_2018_idioms,
unreachable_pub
)]
#![doc(html_root_url = "https://docs.rs/tonic-web/0.10.1")]
#![doc(html_root_url = "https://docs.rs/tonic-web/0.10.2")]
#![doc(issue_tracker_base_url = "https://github.com/hyperium/tonic/issues/")]

pub use call::GrpcWebCall;
Binary file added tonic-web/tests/incomplete-buf-bug.bin
Binary file not shown.
4 changes: 2 additions & 2 deletions tonic/Cargo.toml
Original file line number Diff line number Diff line change
@@ -13,14 +13,14 @@ categories = ["web-programming", "network-programming", "asynchronous"]
description = """
A gRPC over HTTP/2 implementation focused on high performance, interoperability, and flexibility.
"""
documentation = "https://docs.rs/tonic/0.10.1"
documentation = "https://docs.rs/tonic/0.10.2"
edition = "2021"
homepage = "https://github.com/hyperium/tonic"
keywords = ["rpc", "grpc", "async", "futures", "protobuf"]
license = "MIT"
readme = "../README.md"
repository = "https://github.com/hyperium/tonic"
version = "0.10.1"
version = "0.10.2"

[features]
codegen = ["dep:async-trait"]
2 changes: 1 addition & 1 deletion tonic/src/codec/decode.rs
Original file line number Diff line number Diff line change
@@ -253,7 +253,7 @@ impl StreamingInner {
} else {
// FIXME: improve buf usage.
if self.buf.has_remaining() {
trace!("unexpected EOF decoding stream");
trace!("unexpected EOF decoding stream, state: {:?}", self.state);
Err(Status::new(
Code::Internal,
"Unexpected EOF decoding stream.".to_string(),
2 changes: 1 addition & 1 deletion tonic/src/lib.rs
Original file line number Diff line number Diff line change
@@ -89,7 +89,7 @@
#![doc(
html_logo_url = "https://raw.githubusercontent.com/tokio-rs/website/master/public/img/icons/tonic.svg"
)]
#![doc(html_root_url = "https://docs.rs/tonic/0.10.1")]
#![doc(html_root_url = "https://docs.rs/tonic/0.10.2")]
#![doc(issue_tracker_base_url = "https://github.com/hyperium/tonic/issues/")]
#![doc(test(no_crate_inject, attr(deny(rust_2018_idioms))))]
#![cfg_attr(docsrs, feature(doc_cfg))]