Skip to content

Commit

Permalink
types: fix overflow check of types/convert.go::floatStrToIntStr (#11114)
Browse files Browse the repository at this point in the history
Signed-off-by: H-ZeX <hzx20112012@gmail.com>
  • Loading branch information
H-ZeX authored and lonng committed Jul 16, 2019
1 parent 593fb7d commit 3ec46b0
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 8 deletions.
17 changes: 9 additions & 8 deletions types/convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,9 @@ func roundIntStr(numNextDot byte, intStr string) string {
// strconv.ParseInt, we can't parse float first then convert it to string because precision will
// be lost. For example, the string value "18446744073709551615" which is the max number of unsigned
// int will cause some precision to lose. intStr[0] may be a positive and negative sign like '+' or '-'.
//
// This func will find serious overflow such as the len of intStr > 20 (without prefix `+/-`)
// however, it will not check whether the intStr overflow BIGINT.
func floatStrToIntStr(sc *stmtctx.StatementContext, validFloat string, oriStr string) (intStr string, _ error) {
var dotIdx = -1
var eIdx = -1
Expand Down Expand Up @@ -443,12 +446,15 @@ func floatStrToIntStr(sc *stmtctx.StatementContext, validFloat string, oriStr st
if err != nil {
return validFloat, errors.Trace(err)
}
if exp > 0 && int64(intCnt) > (math.MaxInt64-int64(exp)) {
// (exp + incCnt) overflows MaxInt64.
intCnt += exp
if exp >= 0 && (intCnt > 21 || intCnt < 0) {
// MaxInt64 has 19 decimal digits.
// MaxUint64 has 20 decimal digits.
// And the intCnt may contain the len of `+/-`,
// so I use 21 here as the early detection.
sc.AppendWarning(ErrOverflow.GenWithStackByArgs("BIGINT", oriStr))
return validFloat[:eIdx], nil
}
intCnt += exp
if intCnt <= 0 {
intStr = "0"
if intCnt == 0 && len(digits) > 0 {
Expand All @@ -474,11 +480,6 @@ func floatStrToIntStr(sc *stmtctx.StatementContext, validFloat string, oriStr st
} else {
// convert scientific notation decimal number
extraZeroCount := intCnt - len(digits)
if extraZeroCount > 20 {
// Append overflow warning and return to avoid allocating too much memory.
sc.AppendWarning(ErrOverflow.GenWithStackByArgs("BIGINT", oriStr))
return validFloat[:eIdx], nil
}
intStr = string(digits) + strings.Repeat("0", extraZeroCount)
}
return intStr, nil
Expand Down
1 change: 1 addition & 0 deletions types/convert_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -708,6 +708,7 @@ func (s *testTypeConvertSuite) TestGetValidFloat(c *C) {
{".5e0", "1"},
{"+.5e0", "+1"},
{"-.5e0", "-1"},
{".5", "1"},
{"123.456789e5", "12345679"},
{"123.456784e5", "12345678"},
}
Expand Down

0 comments on commit 3ec46b0

Please sign in to comment.