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

types: ParseCoinNormalized may panic for very large values #11732

Closed
2 of 4 tasks
elias-orijtech opened this issue Apr 22, 2022 · 4 comments · Fixed by #11772
Closed
2 of 4 tasks

types: ParseCoinNormalized may panic for very large values #11732

elias-orijtech opened this issue Apr 22, 2022 · 4 comments · Fixed by #11772

Comments

@elias-orijtech
Copy link
Contributor

elias-orijtech commented Apr 22, 2022

Adding this testcase found by OSS-Fuzz,

diff --git types/coin_test.go types/coin_test.go
index 8252b0f1b..787c7c85d 100644
--- types/coin_test.go
+++ types/coin_test.go
@@ -777,6 +777,7 @@ func (s *coinTestSuite) TestParseCoins() {
                {"10atom10", true, sdk.Coins{{"atom10", sdk.NewInt(10)}}},
                {"200transfer/channelToA/uatom", true, sdk.Coins{{"transfer/channelToA/uatom", sdk.NewInt(200)}}},
                {"50ibc/7F1D3FCF4AE79E1554D670D1AD949A9BA4E4A3C76C63093E17E446A46061A7A2", true, sdk.Coins{{"ibc/7F1D3FCF4AE79E1554D670D1AD949A9BA4E4A3C76C63093E17E446A46061A7A2", sdk.NewInt(50)}}},
+               {"120000000000000000000000000000000000000000000000000000000000000000000000000000btc", false, nil},
        }

        for tcIndex, tc := range cases {

results in a panic:

$ go test -trimpath
starting test
--- FAIL: TestCoinTestSuite (0.01s)
    --- FAIL: TestCoinTestSuite/TestParseCoins (0.00s)
        suite.go:63: test panicked: NewIntFromBigInt() out of bound
            goroutine 324 [running]:
            runtime/debug.Stack()
            	runtime/debug/stack.go:24 +0x65
            github.com/stretchr/testify/suite.failOnPanic(0xc0004d8680)
            	github.com/stretchr/testify@v1.7.1/suite/suite.go:63 +0x3e
            panic({0xf4d280, 0x1384a60})
            	runtime/panic.go:838 +0x207
            github.com/cosmos/cosmos-sdk/types.NewIntFromBigInt(...)
            	github.com/cosmos/cosmos-sdk/types/int.go:112
            github.com/cosmos/cosmos-sdk/types.Dec.TruncateInt({0xbe86c5?})
            	github.com/cosmos/cosmos-sdk/types/decimal.go:686 +0x7d
            github.com/cosmos/cosmos-sdk/types.DecCoin.TruncateDecimal({{0x111be34?, 0xbe1827?}, {0xc0002974a0?}})
            	github.com/cosmos/cosmos-sdk/types/dec_coin.go:113 +0x39
            github.com/cosmos/cosmos-sdk/types.NormalizeCoins({0xc000564ba0?, 0x1, 0x2?})
            	github.com/cosmos/cosmos-sdk/types/denom.go:142 +0xe5
            github.com/cosmos/cosmos-sdk/types.ParseCoinsNormalized({0x111bde6?, 0x109d540?})
            	github.com/cosmos/cosmos-sdk/types/coin.go:840 +0x45
            github.com/cosmos/cosmos-sdk/types_test.(*coinTestSuite).TestParseCoins(0xc000142370)
            	github.com/cosmos/cosmos-sdk/types/coin_test.go:784 +0x8ae
            reflect.Value.call({0xc00032a8a0?, 0xc000732400?, 0x13?}, {0x10d470f, 0x4}, {0xc000095e70, 0x1, 0x1?})
            	reflect/value.go:556 +0x845
            reflect.Value.Call({0xc00032a8a0?, 0xc000732400?, 0xc000142370?}, {0xc0004ce670, 0x1, 0x1})
            	reflect/value.go:339 +0xbf
            github.com/stretchr/testify/suite.Run.func1(0xc0004d8680)
            	github.com/stretchr/testify@v1.7.1/suite/suite.go:158 +0x4b6
            testing.tRunner(0xc0004d8680, 0xc00056b170)
            	testing/testing.go:1439 +0x102
            created by testing.(*T).Run
            	testing/testing.go:1486 +0x35f
FAIL
exit status 1

The issue is that the maxDecBitLen limit assumes that chopping the decimal part of a maxDecBitLen-long types.Dec number will always result in a 60 (DecimalPrecisionBits) bits shorter integer, which fits in 256 bits (maxBitLen). However, because 10^18 (Precision) is less than 2^60, this is not true.

An obvious fix is to limit maxDecBitLen:

diff --git types/decimal.go types/decimal.go
index f7d7ad9ff..1cbea27a1 100644
--- types/decimal.go
+++ types/decimal.go
@@ -26,7 +26,12 @@ const (
        // Ceiling[Log2[999 999 999 999 999 999]]
        DecimalPrecisionBits = 60

-       maxDecBitLen = maxBitLen + DecimalPrecisionBits
+       // decimalTruncateBits is the minimum number of bits removed
+       // by a truncate operation. It is equal to
+       // Floor[Log2[10^Precision]].
+       decimalTruncateBits = DecimalPrecisionBits - 1
+
+       maxDecBitLen = maxBitLen + decimalTruncateBits

        // max number of iterations in ApproxRoot function
        maxApproxRootIterations = 100

However, that results in test failures because some large values no longer fit into a types.Dec:

$ go test
--- FAIL: TestDecimalTestSuite (0.00s)
    --- FAIL: TestDecimalTestSuite/TestDecEncoding (0.00s)
        decimal_test.go:544:
            	Error Trace:	decimal_test.go:544
            	Error:      	Received unexpected error:
            	            	decimal out of range; got: 316, max: 315
            	Test:       	TestDecimalTestSuite/TestDecEncoding
    --- FAIL: TestDecimalTestSuite/TestNewDecFromStr (0.00s)
        decimal_test.go:100:
            	Error Trace:	decimal_test.go:100
            	Error:      	Expected nil, but got: &errors.errorString{s:"decimal out of range; bitLen: got 316, max 315"}
            	Test:       	TestDecimalTestSuite/TestNewDecFromStr
            	Messages:   	unexpected error, decimalStr 88888888888888888888888888888888888888888888888888888888888888888888844444440, tc 17
starting test
FAIL
exit status 1
FAIL	github.com/cosmos/cosmos-sdk/types	0.372s

Version

git revision b518c84

CC @odeke-em.


For Admin Use

  • Not duplicate issue
  • Appropriate labels applied
  • Appropriate contributors tagged
  • Contributor assigned/self-assigned
elias-orijtech added a commit to elias-orijtech/cosmos-sdk that referenced this issue Apr 22, 2022
The testcase triggers a panic, "NewIntFromBigInt() out of bound", in
types.Dec.TruncateInt as detailed in cosmos#11732.
odeke-em pushed a commit that referenced this issue Apr 22, 2022
The testcase triggers a panic, "NewIntFromBigInt() out of bound", in
types.Dec.TruncateInt as detailed in #11732.
@alexanderbez
Copy link
Contributor

@elias-orijtech since we have a diff posted, would you be open to opening a PR?

cc @ValarDragon for decimal types visibility.

@elias-orijtech
Copy link
Contributor Author

@elias-orijtech since we have a diff posted, would you be open to opening a PR?

Sure, but I'm waiting for someone with more knowledge before posting a PR that deletes or updates the two test cases my suggested fix break.

cc @ValarDragon for decimal types visibility.

@ValarDragon
Copy link
Contributor

I'm fine w/ changing the behavior to force parsing of ints to be one minus the perceived logical maximum bit length!

Doesn't break anything Osmosis depends upon, I'd be a bit surprised if it broke things for other folks.

@alexanderbez
Copy link
Contributor

@elias-orijtech I think the change is OK.

elias-orijtech added a commit to elias-orijtech/cosmos-sdk that referenced this issue Apr 27, 2022
…ecisionBits

As found by OSS-Fuzz, large numbers may overflow the current maxDecBitLen because
it assumes that DecimalPrecisionBits (60) can always be represented by Precision (18)
base-10 digits. Since 2^60 is larger than 2^18, this assumption is false.

This change fixes cosmos#11732 by only allowing 59 bits of precision on top of the 256
maxBitLen allowed for the integer part.
@mergify mergify bot closed this as completed in #11772 Apr 27, 2022
mergify bot pushed a commit that referenced this issue Apr 27, 2022
…ecisionBits (#11772)

## Description

Closes: #11732

As found by OSS-Fuzz, large numbers may overflow the current maxDecBitLen because
it assumes that DecimalPrecisionBits (60) can always be represented by Precision (18)
base-10 digits. Since 2^60 is larger than 2^18, this assumption is false.

This change fixes #11732 by only allowing 59 bits of precision on top of the 256
maxBitLen allowed for the integer part.

---

### Author Checklist

*All items are required. Please add a note to the item if the item is not applicable and
please add links to any relevant follow up issues.*

I have...

- [x] included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [x] added `!` to the type prefix if API or client breaking change
- [x] targeted the correct branch (see [PR Targeting](https://github.com/cosmos/cosmos-sdk/blob/main/CONTRIBUTING.md#pr-targeting))
- [x] provided a link to the relevant issue or specification
- [ ] followed the guidelines for [building modules](https://github.com/cosmos/cosmos-sdk/blob/main/docs/building-modules)
- [x] included the necessary unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/main/CONTRIBUTING.md#testing)
- [ ] added a changelog entry to `CHANGELOG.md`
- [ ] included comments for [documenting Go code](https://blog.golang.org/godoc)
- [x] updated the relevant documentation or specification
- [x] reviewed "Files changed" and left comments if necessary
- [ ] confirmed all CI checks have passed

### Reviewers Checklist

*All items are required. Please add a note if the item is not applicable and please add
your handle next to the items reviewed if you only reviewed selected items.*

I have...

- [ ] confirmed the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [ ] confirmed `!` in the type prefix if API or client breaking change
- [ ] confirmed all author checklist items have been addressed 
- [ ] reviewed state machine logic
- [ ] reviewed API design and naming
- [ ] reviewed documentation is accurate
- [ ] reviewed tests and test coverage
- [ ] manually tested (if applicable)
mergify bot pushed a commit that referenced this issue Apr 27, 2022
…ecisionBits (#11772)

## Description

Closes: #11732

As found by OSS-Fuzz, large numbers may overflow the current maxDecBitLen because
it assumes that DecimalPrecisionBits (60) can always be represented by Precision (18)
base-10 digits. Since 2^60 is larger than 2^18, this assumption is false.

This change fixes #11732 by only allowing 59 bits of precision on top of the 256
maxBitLen allowed for the integer part.

---

### Author Checklist

*All items are required. Please add a note to the item if the item is not applicable and
please add links to any relevant follow up issues.*

I have...

- [x] included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [x] added `!` to the type prefix if API or client breaking change
- [x] targeted the correct branch (see [PR Targeting](https://github.com/cosmos/cosmos-sdk/blob/main/CONTRIBUTING.md#pr-targeting))
- [x] provided a link to the relevant issue or specification
- [ ] followed the guidelines for [building modules](https://github.com/cosmos/cosmos-sdk/blob/main/docs/building-modules)
- [x] included the necessary unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/main/CONTRIBUTING.md#testing)
- [ ] added a changelog entry to `CHANGELOG.md`
- [ ] included comments for [documenting Go code](https://blog.golang.org/godoc)
- [x] updated the relevant documentation or specification
- [x] reviewed "Files changed" and left comments if necessary
- [ ] confirmed all CI checks have passed

### Reviewers Checklist

*All items are required. Please add a note if the item is not applicable and please add
your handle next to the items reviewed if you only reviewed selected items.*

I have...

- [ ] confirmed the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [ ] confirmed `!` in the type prefix if API or client breaking change
- [ ] confirmed all author checklist items have been addressed
- [ ] reviewed state machine logic
- [ ] reviewed API design and naming
- [ ] reviewed documentation is accurate
- [ ] reviewed tests and test coverage
- [ ] manually tested (if applicable)

(cherry picked from commit f9913c1)

# Conflicts:
#	CHANGELOG.md
mergify bot pushed a commit that referenced this issue Apr 27, 2022
…ecisionBits (#11772)

## Description

Closes: #11732

As found by OSS-Fuzz, large numbers may overflow the current maxDecBitLen because
it assumes that DecimalPrecisionBits (60) can always be represented by Precision (18)
base-10 digits. Since 2^60 is larger than 2^18, this assumption is false.

This change fixes #11732 by only allowing 59 bits of precision on top of the 256
maxBitLen allowed for the integer part.

---

### Author Checklist

*All items are required. Please add a note to the item if the item is not applicable and
please add links to any relevant follow up issues.*

I have...

- [x] included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [x] added `!` to the type prefix if API or client breaking change
- [x] targeted the correct branch (see [PR Targeting](https://github.com/cosmos/cosmos-sdk/blob/main/CONTRIBUTING.md#pr-targeting))
- [x] provided a link to the relevant issue or specification
- [ ] followed the guidelines for [building modules](https://github.com/cosmos/cosmos-sdk/blob/main/docs/building-modules)
- [x] included the necessary unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/main/CONTRIBUTING.md#testing)
- [ ] added a changelog entry to `CHANGELOG.md`
- [ ] included comments for [documenting Go code](https://blog.golang.org/godoc)
- [x] updated the relevant documentation or specification
- [x] reviewed "Files changed" and left comments if necessary
- [ ] confirmed all CI checks have passed

### Reviewers Checklist

*All items are required. Please add a note if the item is not applicable and please add
your handle next to the items reviewed if you only reviewed selected items.*

I have...

- [ ] confirmed the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [ ] confirmed `!` in the type prefix if API or client breaking change
- [ ] confirmed all author checklist items have been addressed
- [ ] reviewed state machine logic
- [ ] reviewed API design and naming
- [ ] reviewed documentation is accurate
- [ ] reviewed tests and test coverage
- [ ] manually tested (if applicable)

(cherry picked from commit f9913c1)

# Conflicts:
#	CHANGELOG.md
elias-orijtech added a commit to elias-orijtech/cosmos-sdk that referenced this issue May 6, 2022
The testcase triggers a panic, "NewIntFromBigInt() out of bound", in
types.Dec.TruncateInt as detailed in cosmos#11732.
odeke-em pushed a commit that referenced this issue Jun 4, 2022
The testcase triggers a panic, "NewIntFromBigInt() out of bound", in
types.Dec.TruncateInt as detailed in #11732.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants