diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 86372ae43..a4e868465 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -10,6 +10,7 @@ * FEATURE: vmauth: allow using regexp paths in `url_map`. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/1112) for details. * BUGFIX: vmagent: reduce memory usage when Kubernetes service discovery is used in big number of distinct jobs by sharing the cache. See https://github.com/VictoriaMetrics/VictoriaMetrics/issues/1113 +* BUGFIX: prevent exponent overflow when processing extremely small values close to zero such as `2.964393875E-314`. See https://github.com/VictoriaMetrics/VictoriaMetrics/issues/1114 # [v1.55.1](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.55.1) diff --git a/lib/decimal/decimal.go b/lib/decimal/decimal.go index 84304fefe..9b75814cd 100644 --- a/lib/decimal/decimal.go +++ b/lib/decimal/decimal.go @@ -456,6 +456,13 @@ func positiveFloatToDecimalSlow(f float64) (int64, int16) { prec = 1e15 } _, exp := math.Frexp(f) + // Bound the exponent according to https://en.wikipedia.org/wiki/Double-precision_floating-point_format + // This fixes the issue https://github.com/VictoriaMetrics/VictoriaMetrics/issues/1114 + if exp < -1022 { + exp = -1022 + } else if exp > 1023 { + exp = 1023 + } scale = int16(float64(exp) * (math.Ln2 / math.Ln10)) f *= math.Pow10(-int(scale)) } diff --git a/lib/decimal/decimal_test.go b/lib/decimal/decimal_test.go index f6a94ea97..5bc177d64 100644 --- a/lib/decimal/decimal_test.go +++ b/lib/decimal/decimal_test.go @@ -95,6 +95,20 @@ func TestPositiveFloatToDecimal(t *testing.T) { f(0.001130435, 1130435, -9) f(vInfPos, 9223372036854775, 3) f(vMax, 9223372036854775, 3) + + // Extreme cases. See https://github.com/VictoriaMetrics/VictoriaMetrics/issues/1114 + f(2.964393875e-100, 2964393875, -109) + f(2.964393875e-309, 2964393875, -318) + f(2.964393875e-314, 296439387505, -325) + f(2.964393875e-315, 2964393875047, -327) + f(2.964393875e-320, 296439387505, -331) + f(2.964393875e-324, 494065645841, -335) + f(2.964393875e-325, 0, 1) + + f(2.964393875e+307, 2964393875, 298) + f(9.964393875e+307, 9964393875, 298) + f(1.064393875e+308, 1064393875, 299) + f(1.797393875e+308, 1797393875, 299) } func TestAppendDecimalToFloat(t *testing.T) {