MCPcopy
hub / github.com/grpc/grpc-go / decompress

Function decompress

rpc_util.go:985–1044  ·  view source on GitHub ↗

decompress processes the given data by decompressing it using either a custom decompressor or a standard compressor. If a custom decompressor is provided, it takes precedence. The function validates that the decompressed data does not exceed the specified maximum size and returns an error if this li

(compressor encoding.Compressor, d mem.BufferSlice, dc Decompressor, maxReceiveMessageSize int, pool mem.BufferPool)

Source from the content-addressed store, hash-verified

983// data. Otherwise, it returns an error if decompression fails or the data
984// exceeds the size limit.
985func decompress(compressor encoding.Compressor, d mem.BufferSlice, dc Decompressor, maxReceiveMessageSize int, pool mem.BufferPool) (mem.BufferSlice, error) {
986 if dc != nil {
987 r := d.Reader()
988 // For the built-in gzip decompressor, bound the decompressed output
989 // at maxReceiveMessageSize+1 so that a small but highly compressed
990 // payload (a "zip bomb") cannot expand to gigabytes in memory before
991 // the post-decompression size check below has a chance to fire. The
992 // Decompressor interface does not accept an extra size parameter,
993 // so we type-assert to invoke a size-aware helper. Third-party
994 // Decompressor implementations keep the original Do behavior.
995 var uncompressed []byte
996 var err error
997 if gd, ok := dc.(*gzipDecompressor); ok {
998 uncompressed, err = gd.doWithMaxSize(r, int64(maxReceiveMessageSize))
999 } else {
1000 uncompressed, err = dc.Do(r)
1001 }
1002 if err != nil {
1003 r.Close() // ensure buffers are reused
1004 return nil, status.Errorf(codes.Internal, "grpc: failed to decompress the received message: %v", err)
1005 }
1006 if len(uncompressed) > maxReceiveMessageSize {
1007 r.Close() // ensure buffers are reused
1008 return nil, status.Errorf(codes.ResourceExhausted, "grpc: message after decompression larger than max (%d vs. %d)", len(uncompressed), maxReceiveMessageSize)
1009 }
1010 return mem.BufferSlice{mem.SliceBuffer(uncompressed)}, nil
1011 }
1012 if compressor != nil {
1013 r := d.Reader()
1014 dcReader, err := compressor.Decompress(r)
1015 if err != nil {
1016 r.Close() // ensure buffers are reused
1017 return nil, status.Errorf(codes.Internal, "grpc: failed to decompress the message: %v", err)
1018 }
1019 if closer, ok := dcReader.(io.Closer); ok {
1020 defer closer.Close()
1021 }
1022
1023 // Read at most one byte more than the limit from the decompressor.
1024 // Unless the limit is MaxInt64, in which case, that's impossible, so
1025 // apply no limit.
1026 if limit := int64(maxReceiveMessageSize); limit < math.MaxInt64 {
1027 dcReader = io.LimitReader(dcReader, limit+1)
1028 }
1029 out, err := mem.ReadAll(dcReader, pool)
1030 if err != nil {
1031 r.Close() // ensure buffers are reused
1032 out.Free()
1033 return nil, status.Errorf(codes.Internal, "grpc: failed to read decompressed data: %v", err)
1034 }
1035
1036 if out.Len() > maxReceiveMessageSize {
1037 r.Close() // ensure buffers are reused
1038 out.Free()
1039 return nil, status.Errorf(codes.ResourceExhausted, "grpc: received message after decompression larger than max %d", maxReceiveMessageSize)
1040 }
1041 return out, nil
1042 }

Callers 4

recvAndDecompressFunction · 0.85
TestDecompressMethod · 0.85

Calls 10

ErrorfFunction · 0.92
SliceBufferTypeAlias · 0.92
ReadAllFunction · 0.92
ReaderMethod · 0.80
doWithMaxSizeMethod · 0.80
DoMethod · 0.65
CloseMethod · 0.65
DecompressMethod · 0.65
FreeMethod · 0.65
LenMethod · 0.65

Tested by 3

TestDecompressMethod · 0.68