Skip to content
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

Add a decompression limit #729

Merged
merged 2 commits into from
Feb 28, 2020
Merged

Add a decompression limit #729

merged 2 commits into from
Feb 28, 2020

Conversation

glbrntt
Copy link
Collaborator

@glbrntt glbrntt commented Feb 27, 2020

Motivation:

Compression can be an attack vector for maclicious users. Specifically,
bad actors may send 'zip-bombs' which have very high compression
ratios which may consume a large amount of memory when decompressed.

Modifications:

  • Intoruce a DecompressionLimit which has two options, an absolute
    (an absolute size limit for a decompressed message), and ratio
    (based on the compression ratio of the message).
  • Add decompression limits to server and client compression
    configuration
  • Explicitly make compression enabled or disabled

Result:

Easier to protect against zip-bombs

Motivation:

Compression can be an attack vector for maclicious users. Specifically,
bad actors may send 'zip-bombs' which have very high compression
ratios which may consume a large amount of memory when decompressed.

Modifications:

- Intoruce a `DecompressionLimit` which has two options, an `absolute`
  (an absolute size limit for a decompressed message), and `ratio`
  (based on the compression ratio of the message).
- Add decompression limits to server and client compression
  configuration
- Explicitly make compression `enabled` or `disabled`

Result:

Easier to protect against zip-bombs
@glbrntt glbrntt requested a review from MrMage February 27, 2020 16:33
@glbrntt glbrntt added nio ⚠️ semver/major Breaks existing public API. labels Feb 27, 2020
Copy link
Collaborator

@MrMage MrMage left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good overall.

However, I am starting to get a bit concerned about the amount of changes our recent PRs required throughout the entire codebase.

Part of this might be technically unrelated refactorings that could just fit well with the PR itself, of course. But in some cases, the amount of changes needed for a particular addition simply feels surprising. That amount of "code churn" also makes it a bit harder to recognize the "essence" of the PR in a few cases. To counter that, though, I have been trying to put that "churn" aside and focus on the parts of the PR where actual stuff happens.

Also, I am starting to feel that I "lose track" of the overall codebase and the ability to fully evaluate changes (which could also explain the recent decline in comments from me). I guess that can't be fully avoided if one mostly reviews the code without actually working inside the codebase, though.

public init(
forRequests outbound: CompressionAlgorithm?,
acceptableForResponses inbound: [CompressionAlgorithm] = CompressionAlgorithm.all
acceptableForResponses inbound: [CompressionAlgorithm] = CompressionAlgorithm.all,
decompressionLimit: DecompressionLimit
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be provide a "reasonable" default here?

@@ -118,6 +118,23 @@ public enum GRPCError {
}
}

/// The decompression limit was exceeded while decompressing a message.
public struct DecompressionLimitExceeded: GRPCErrorProtocol {
var compressedSize: Int
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

public let? I guess we could allow this to be part of the public API.

case supported(CompressionAlgorithm)
enum ValidationResult {
/// The requested compression is supported.
case supported(CompressionAlgorithm, DecompressionLimit, acceptEncoding: [String])
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how about naming all these associated values? :-) (Up to you, given that the types are already very telling.)

@@ -172,4 +174,77 @@ class MessageCompressionTests: GRPCTestCase {

self.wait(for: [response, trailers, status], timeout: self.defaultTimeout)
}

func testDecompressionLimitIsRespectedByServerForUnaryCall() throws {
try self.setupServer(encoding: .enabled(.init(decompressionLimit: .absolute(1))))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we also test a ratio limit?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, I guess that is covered by ZlibTests...

@glbrntt
Copy link
Collaborator Author

glbrntt commented Feb 28, 2020

Part of this might be technically unrelated refactorings that could just fit well with the PR itself, of course.

There's definitely been some of that. I'll try to avoid that in the future to make the PRs smaller.

But in some cases, the amount of changes needed for a particular addition simply feels surprising. That amount of "code churn" also makes it a bit harder to recognize the "essence" of the PR in a few cases. To counter that, though, I have been trying to put that "churn" aside and focus on the parts of the PR where actual stuff happens.

I noticed this too; but I think the changes in functionality have been fairly substantial (compression, support for non-protobuf payloads and support for different channels). We didn't plan on doing these at all (apart from compression) so I'm not too worried about how large they were.

Also, I am starting to feel that I "lose track" of the overall codebase and the ability to fully evaluate changes (which could also explain the recent decline in comments from me). I guess that can't be fully avoided if one mostly reviews the code without actually working inside the codebase, though.

Totally fair; we need to find another core dev :)

@glbrntt glbrntt merged commit acdd3b4 into grpc:nio Feb 28, 2020
@glbrntt glbrntt deleted the gb-compression-limit branch February 28, 2020 13:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
⚠️ semver/major Breaks existing public API.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants