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

codec/types: avoid unnecessary allocations for NewAnyWithCustomTypeURL on error #8605

Merged
merged 1 commit into from
Feb 17, 2021

Conversation

odeke-em
Copy link
Collaborator

Avoids a bleed out attack in which a node can be made to allocate
memory slowly or very fast in small strides, by sending bad data
to code that invokes NewAnyWithCustomTypeURL, in which we
unconditionally returned a new Any object. On a 64-bit machine,
this would waste 96 bytes per invocation even on error.

Added a test to ensure zero allocations with a fixed error returned.
Also added a benchmark which shows reduction in wasted allocations and
wasted CPU time:

$ benchstat before.txt after.txt
name                                            old time/op    new time/op    delta
NewAnyWithCustomTypeURLWithErrorReturned-8      142ns ± 6%      55ns ±12%   -61.65%  (p=0.000 n=9+10)

name                                            old alloc/op   new alloc/op   delta
NewAnyWithCustomTypeURLWithErrorReturned-8      96.0B ± 0%      0.0B       -100.00%  (p=0.000 n=10+10)

name                                            old allocs/op  new allocs/op  delta
NewAnyWithCustomTypeURLWithErrorReturned-8      1.00 ± 0%      0.00       -100.00%  (p=0.000 n=10+10)

Fixes #8537


Before we can merge this PR, please make sure that all the following items have been
checked off. If any of the checklist items are not applicable, please leave them but
write a little note why.

  • Targeted PR against correct branch (see CONTRIBUTING.md)
  • Linked to Github issue with discussion and accepted design OR link to spec that describes this work.
  • Code follows the module structure standards.
  • Wrote unit and integration tests
  • Updated relevant documentation (docs/) or specification (x/<module>/spec/)
  • Added relevant godoc comments.
  • Added a relevant changelog entry to the Unreleased section in CHANGELOG.md
  • Re-reviewed Files changed in the Github PR explorer
  • Review Codecov Report in the comment section below once CI passes

…L on error

Avoids a bleed out attack in which a node can be made to allocate
memory slowly or very fast in small strides, by sending bad data
to code that invokes NewAnyWithCustomTypeURL, in which we
unconditionally returned a new Any object. On a 64-bit machine,
this would waste 96 bytes per invocation even on error.

Added a test to ensure zero allocations with a fixed error returned.
Also added a benchmark which shows reduction in wasted allocations and
wasted CPU time:

```shell
$ benchstat before.txt after.txt
name                                            old time/op    new time/op    delta
NewAnyWithCustomTypeURLWithErrorReturned-8      142ns ± 6%      55ns ±12%   -61.65%  (p=0.000 n=9+10)

name                                            old alloc/op   new alloc/op   delta
NewAnyWithCustomTypeURLWithErrorReturned-8      96.0B ± 0%      0.0B       -100.00%  (p=0.000 n=10+10)

name                                            old allocs/op  new allocs/op  delta
NewAnyWithCustomTypeURLWithErrorReturned-8      1.00 ± 0%      0.00       -100.00%  (p=0.000 n=10+10)
```

Fixes #8537
@odeke-em
Copy link
Collaborator Author

I kindly request that we backport this change too.

Copy link
Member

@tac0turtle tac0turtle left a comment

Choose a reason for hiding this comment

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

LGTM

@tac0turtle
Copy link
Member

@Mergifyio backport release/v0.41.x

@mergify
Copy link
Contributor

mergify bot commented Feb 17, 2021

Command backport release/v0.41.x: pending

Waiting for the pull request to get merged

@tac0turtle
Copy link
Member

I kindly request that we backport this change too.

on merge the backport should be handled unless conflicts arise.

@odeke-em
Copy link
Collaborator Author

odeke-em commented Feb 17, 2021 via email

@codecov
Copy link

codecov bot commented Feb 17, 2021

Codecov Report

Merging #8605 (4ff4fcb) into master (47dd07d) will increase coverage by 0.00%.
The diff coverage is 100.00%.

Impacted file tree graph

@@           Coverage Diff           @@
##           master    #8605   +/-   ##
=======================================
  Coverage   61.47%   61.47%           
=======================================
  Files         658      658           
  Lines       37583    37585    +2     
=======================================
+ Hits        23104    23106    +2     
  Misses      12067    12067           
  Partials     2412     2412           
Impacted Files Coverage Δ
codec/types/any.go 62.50% <100.00%> (+3.40%) ⬆️

@alessio alessio merged commit 56fc3fc into master Feb 17, 2021
@alessio alessio deleted the codec-types-avoid-wasting-Any-allocations-on-error branch February 17, 2021 10:13
@mergify
Copy link
Contributor

mergify bot commented Feb 17, 2021

Command backport release/v0.41.x: success

Backports have been created

mergify bot pushed a commit that referenced this pull request Feb 17, 2021
…L on error (#8605)

Avoids a bleed out attack in which a node can be made to allocate
memory slowly or very fast in small strides, by sending bad data
to code that invokes NewAnyWithCustomTypeURL, in which we
unconditionally returned a new Any object. On a 64-bit machine,
this would waste 96 bytes per invocation even on error.

Added a test to ensure zero allocations with a fixed error returned.
Also added a benchmark which shows reduction in wasted allocations and
wasted CPU time:

```shell
$ benchstat before.txt after.txt
name                                            old time/op    new time/op    delta
NewAnyWithCustomTypeURLWithErrorReturned-8      142ns ± 6%      55ns ±12%   -61.65%  (p=0.000 n=9+10)

name                                            old alloc/op   new alloc/op   delta
NewAnyWithCustomTypeURLWithErrorReturned-8      96.0B ± 0%      0.0B       -100.00%  (p=0.000 n=10+10)

name                                            old allocs/op  new allocs/op  delta
NewAnyWithCustomTypeURLWithErrorReturned-8      1.00 ± 0%      0.00       -100.00%  (p=0.000 n=10+10)
```

Fixes #8537

(cherry picked from commit 56fc3fc)
alessio pushed a commit that referenced this pull request Feb 17, 2021
…L on error (#8605) (#8606)

Avoids a bleed out attack in which a node can be made to allocate
memory slowly or very fast in small strides, by sending bad data
to code that invokes NewAnyWithCustomTypeURL, in which we
unconditionally returned a new Any object. On a 64-bit machine,
this would waste 96 bytes per invocation even on error.

Added a test to ensure zero allocations with a fixed error returned.
Also added a benchmark which shows reduction in wasted allocations and
wasted CPU time:

```shell
$ benchstat before.txt after.txt
name                                            old time/op    new time/op    delta
NewAnyWithCustomTypeURLWithErrorReturned-8      142ns ± 6%      55ns ±12%   -61.65%  (p=0.000 n=9+10)

name                                            old alloc/op   new alloc/op   delta
NewAnyWithCustomTypeURLWithErrorReturned-8      96.0B ± 0%      0.0B       -100.00%  (p=0.000 n=10+10)

name                                            old allocs/op  new allocs/op  delta
NewAnyWithCustomTypeURLWithErrorReturned-8      1.00 ± 0%      0.00       -100.00%  (p=0.000 n=10+10)
```

Fixes #8537

(cherry picked from commit 56fc3fc)

Co-authored-by: Emmanuel T Odeke <[email protected]>
@robert-zaremba
Copy link
Collaborator

Good job.

PS: I thought we backport only fixes and significant changes? This is a micro optimization of an unhappy path
PS2: All optimizations are always good 👏

@odeke-em
Copy link
Collaborator Author

odeke-em commented Feb 17, 2021 via email

@alessio
Copy link
Contributor

alessio commented Feb 17, 2021

Stable release updates are for improvements and bugfixes that don't break user code. And no, not all optimizations are always welcome. Only low risk optimizations are welcome, e.g. this one ;-)

@robert-zaremba
Copy link
Collaborator

if someone could trivially send unmarshallable data in a fast loop

How that can happen? Is there a way a user could exploit it? I think any TX will go out of gas and other allocations would be way more significant before something here will happen.

@odeke-em
Copy link
Collaborator Author

odeke-em commented Feb 17, 2021 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

codec/types: NewAnyWithCustomTypeURL wastes memory if proto.Marshal returns a non-nil error
4 participants