-
Notifications
You must be signed in to change notification settings - Fork 4.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Get empty response when compress enabled and maxReceiveMessageSize be maxInt64 #4552
Comments
the question seems to be caused by https://github.com/grpc/grpc-go/blob/master/rpc_util.go#L744-L745
will make but I'm not sure how to fix those bound condition, PTAL thx |
Thanks @lysu for reporting the problem and providing a way to reproduce it. I was able to reproduce it with the the helloworld example as suggested by you. Also, I can confirm that the following ways of creating the conn, err := grpc.Dial(address,
grpc.WithInsecure(),
grpc.WithBlock(),
grpc.WithDefaultCallOptions(grpc.UseCompressor("gzip"))) conn, err := grpc.Dial(address,
grpc.WithInsecure(),
grpc.WithBlock(),
grpc.WithDefaultCallOptions(grpc.UseCompressor("gzip"), grpc.MaxCallRecvMsgSize(math.MaxInt64-1))) It's only when conn, err := grpc.Dial(address,
grpc.WithInsecure(),
grpc.WithBlock(),
grpc.WithDefaultCallOptions(grpc.UseCompressor("gzip"), grpc.MaxCallRecvMsgSize(math.MaxInt64-1))) This clearly looks like a bug on our side. We will look into this shortly. I tried this on master and the issue still exists. |
I also verified that getting rid of the |
The following fix would make it work: // MaxCallRecvMsgSize returns a CallOption which sets the maximum message size
// in bytes the client can receive.
func MaxCallRecvMsgSize(bytes int) CallOption {
if bytes == math.MaxInt64 {
bytes--
}
return MaxRecvMsgSizeCallOption{MaxRecvMsgSize: bytes}
} But, I'm a little concerned that the call options |
We could address that via:
Note that Theoretically we should allow Line 743 in 52cea24
|
Hmm ... guess I was blind. I didn't spot the |
@Aditya-Sood : Sure, go for it. Thank you very much for your contributions and your continued interest in our repo. Just FYI: I'm going to be out for a few months. @dfawley will be back in a couple of weeks. This issue has been open for a while. So, please talk to @dfawley to make sure that you understand exactly what is required here, so that you don't waste your time going down the wrong path. |
@Aditya-Sood -- ping.. Are you still actively tracking this issue? |
hi @arvindbr8 |
hi @dfawley, Line 743 in 52cea24
I think a best-effort solution like this should work:
one query - is the reasoning behind the reduction of message size by 1 in multiple places aimed at accommodating an EOF marker which is added to the messages? |
hi @dfawley @arvindbr8
|
The question is: if we limit the reader from the decompressor to the exact size of the limit the user set, then how do we know if the message is bigger than the limit? So instead we limit the reader to So the
Another way of writing the same thing would be to do the math with uint64s to ensure overflow doesn't happen: bufferSize := uint64(size) + bytes.MinRead
if bufferSize > math.MaxInt {
bufferSize = math.MaxInt
}
buf := bytes.NewBuffer(make([]byte, 0, int(bufferSize)))
I don't like that as much, as we're applying something very different from what the user was intending. How about this? func decompress() {
// make buffer
bytesRead, err := buf.ReadFrom(io.LimitReader(dcReader, maxReceiveMessageSize))
if bytesRead == maxReceiveMessageSize {
b := make([]byte,1)
if n, err := dcReader.Read(b); n > 0 || err != io.EOF {
// Overflow; return error
}
... |
@Aditya-Sood are you still working on this issue? If not, I'll pick it up. |
yes arjan |
@purnesh42H please assign this issue to me |
@arjan-bal kindly assign the issue to Vivek, I keep getting side-tracked with other work so will not be able to commit as of now @infovivek2020 there's an incomplete PR for this issue (#6999) which you can reference |
@purnesh42H raised PR #7468 my question in PR itself can suggest what i need do |
The The mentioned bug, however, still exist: when the maximum receive message size (maxReceiveMessageSize) is very large (greater than or equal to To fix this, we can use the Approach 1
Approach 2
@dfawley @easwars let me know what you think? @infovivek2020 fyi |
NOTE: if you are reporting is a potential security vulnerability or a crash,
please follow our CVE process at
https://github.com/grpc/proposal/blob/master/P4-grpc-cve-process.md instead of
filing an issue here.
Please see the FAQ in our main README.md, then answer the questions below
before submitting your issue.
What version of gRPC are you using?
v1.27.1
What version of Go are you using (
go version
)?go.1.16
What operating system (Linux, Windows, …) and version?
Linux
What did you do?
If possible, provide a recipe for reproducing the error.
grpc.DialContext
with two callOptions:grpc.UseCompressor("gzip")
to enable gzipgrpc.MaxCallRecvMsgSize(math.MaxInt64)
to setmaxReceiveMessageSize
as maxInt64call remote service and wait for its response
it can be simple reproduce by https://github.com/lysu/grpc-go/blob/b93ee57c403c18340a91a6c718c0a647af23c1ad/examples/helloworld/greeter_client/main.go#L42
What did you expect to see?
remote service will give a compressed response, we should get the right decompressed response.
What did you see instead?
get empty response
The text was updated successfully, but these errors were encountered: