From 25c796ee867ee7ec6b5388c4ba6ff3921a4e9c3b Mon Sep 17 00:00:00 2001 From: elias-orijtech <103319121+elias-orijtech@users.noreply.github.com> Date: Wed, 27 Apr 2022 18:46:13 +0200 Subject: [PATCH] fix: decrement types.Dec max length to keep decimal bits in DecimalPrecisionBits (#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 f9913c139daad0b04b0251e48b8fb26914ffca73) # Conflicts: # CHANGELOG.md --- CHANGELOG.md | 8 ++++++++ types/coin_test.go | 1 + types/decimal.go | 11 ++++++++--- types/decimal_test.go | 35 +++++++++++++++++++++++------------ 4 files changed, 40 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f43644352f2c..14a6e0859932 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -213,7 +213,15 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Bug Fixes +<<<<<<< HEAD * [\#11724](https://github.com/cosmos/cosmos-sdk/pull/11724) Fix data race issues with `api.Server`. +======= +* [\#11772](https://github.com/cosmos/cosmos-sdk/pull/11772) Limit types.Dec length to avoid overflow. +* [\#11724](https://github.com/cosmos/cosmos-sdk/pull/11724) Fix data race issues with api.Server +* [\#11693](https://github.com/cosmos/cosmos-sdk/pull/11693) Add validation for gentx cmd. +* [\#11645](https://github.com/cosmos/cosmos-sdk/pull/11645) Fix `--home` flag ignored when running help. +* [\#11558](https://github.com/cosmos/cosmos-sdk/pull/11558) Fix `--dry-run` not working when using tx command. +>>>>>>> f9913c139 (fix: decrement types.Dec max length to keep decimal bits in DecimalPrecisionBits (#11772)) * [\#11354](https://github.com/cosmos/cosmos-sdk/pull/11355) Added missing pagination flag for `bank q total` query. * [\#11197](https://github.com/cosmos/cosmos-sdk/pull/11197) Signing with multisig now works with multisig address which is not in the keyring. * (makefile) [\#11285](https://github.com/cosmos/cosmos-sdk/pull/11285) Fix lint-fix make target. diff --git a/types/coin_test.go b/types/coin_test.go index 8252b0f1b462..787c7c85d275 100644 --- a/types/coin_test.go +++ b/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 { diff --git a/types/decimal.go b/types/decimal.go index f7d7ad9ffe66..3be55863c068 100644 --- a/types/decimal.go +++ b/types/decimal.go @@ -22,11 +22,16 @@ const ( // number of decimal places Precision = 18 - // bytes required to represent the above precision - // Ceiling[Log2[999 999 999 999 999 999]] + // bits required to represent the above precision + // Ceiling[Log2[10^Precision - 1]] 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 - 1]]. + decimalTruncateBits = DecimalPrecisionBits - 1 + + maxDecBitLen = maxBitLen + decimalTruncateBits // max number of iterations in ApproxRoot function maxApproxRootIterations = 100 diff --git a/types/decimal_test.go b/types/decimal_test.go index 742edb60c1e0..684888b49363 100644 --- a/types/decimal_test.go +++ b/types/decimal_test.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" "math/big" + "strings" "testing" "github.com/stretchr/testify/require" @@ -57,10 +58,10 @@ func (s *decimalTestSuite) TestNewDecFromStr() { largeBigInt, ok := new(big.Int).SetString("3144605511029693144278234343371835", 10) s.Require().True(ok) - largerBigInt, ok := new(big.Int).SetString("88888888888888888888888888888888888888888888888888888888888888888888844444440", 10) + largerBigInt, ok := new(big.Int).SetString("8888888888888888888888888888888888888888888888888888888888888888888844444440", 10) s.Require().True(ok) - largestBigInt, ok := new(big.Int).SetString("133499189745056880149688856635597007162669032647290798121690100488888732861290034376435130433535", 10) + largestBigInt, ok := new(big.Int).SetString("33499189745056880149688856635597007162669032647290798121690100488888732861290034376435130433535", 10) s.Require().True(ok) tests := []struct { @@ -87,8 +88,8 @@ func (s *decimalTestSuite) TestNewDecFromStr() { {"foobar", true, sdk.Dec{}}, {"0.foobar", true, sdk.Dec{}}, {"0.foobar.", true, sdk.Dec{}}, - {"88888888888888888888888888888888888888888888888888888888888888888888844444440", false, sdk.NewDecFromBigInt(largerBigInt)}, - {"133499189745056880149688856635597007162669032647290798121690100488888732861290.034376435130433535", false, sdk.NewDecFromBigIntWithPrec(largestBigInt, 18)}, + {"8888888888888888888888888888888888888888888888888888888888888888888844444440", false, sdk.NewDecFromBigInt(largerBigInt)}, + {"33499189745056880149688856635597007162669032647290798121690100488888732861290.034376435130433535", false, sdk.NewDecFromBigIntWithPrec(largestBigInt, 18)}, {"133499189745056880149688856635597007162669032647290798121690100488888732861291", true, sdk.Dec{}}, } @@ -480,10 +481,14 @@ func (s *decimalTestSuite) TestDecSortableBytes() { } func (s *decimalTestSuite) TestDecEncoding() { - largestBigInt, ok := new(big.Int).SetString("133499189745056880149688856635597007162669032647290798121690100488888732861290034376435130433535", 10) + largestBigInt, ok := new(big.Int).SetString("33499189745056880149688856635597007162669032647290798121690100488888732861290034376435130433535", 10) s.Require().True(ok) - smallestBigInt, ok := new(big.Int).SetString("-133499189745056880149688856635597007162669032647290798121690100488888732861290034376435130433535", 10) + smallestBigInt, ok := new(big.Int).SetString("-33499189745056880149688856635597007162669032647290798121690100488888732861290034376435130433535", 10) + s.Require().True(ok) + + const maxDecBitLen = 315 + maxInt, ok := new(big.Int).SetString(strings.Repeat("1", maxDecBitLen), 2) s.Require().True(ok) testCases := []struct { @@ -523,15 +528,21 @@ func (s *decimalTestSuite) TestDecEncoding() { }, { sdk.NewDecFromBigIntWithPrec(largestBigInt, 18), - "313333343939313839373435303536383830313439363838383536363335353937303037313632363639303332363437323930373938313231363930313030343838383838373332383631323930303334333736343335313330343333353335", - "\"133499189745056880149688856635597007162669032647290798121690100488888732861290.034376435130433535\"", - "\"133499189745056880149688856635597007162669032647290798121690100488888732861290.034376435130433535\"\n", + "3333343939313839373435303536383830313439363838383536363335353937303037313632363639303332363437323930373938313231363930313030343838383838373332383631323930303334333736343335313330343333353335", + "\"33499189745056880149688856635597007162669032647290798121690100488888732861290.034376435130433535\"", + "\"33499189745056880149688856635597007162669032647290798121690100488888732861290.034376435130433535\"\n", }, { sdk.NewDecFromBigIntWithPrec(smallestBigInt, 18), - "2D313333343939313839373435303536383830313439363838383536363335353937303037313632363639303332363437323930373938313231363930313030343838383838373332383631323930303334333736343335313330343333353335", - "\"-133499189745056880149688856635597007162669032647290798121690100488888732861290.034376435130433535\"", - "\"-133499189745056880149688856635597007162669032647290798121690100488888732861290.034376435130433535\"\n", + "2D3333343939313839373435303536383830313439363838383536363335353937303037313632363639303332363437323930373938313231363930313030343838383838373332383631323930303334333736343335313330343333353335", + "\"-33499189745056880149688856635597007162669032647290798121690100488888732861290.034376435130433535\"", + "\"-33499189745056880149688856635597007162669032647290798121690100488888732861290.034376435130433535\"\n", + }, + { + sdk.NewDecFromBigIntWithPrec(maxInt, 18), + "3636373439353934383732353238343430303734383434343238333137373938353033353831333334353136333233363435333939303630383435303530323434343434333636343330363435303137313838323137353635323136373637", + "\"66749594872528440074844428317798503581334516323645399060845050244444366430645.017188217565216767\"", + "\"66749594872528440074844428317798503581334516323645399060845050244444366430645.017188217565216767\"\n", }, }