From 990a7b0c62990ee3539929e30d0e108486028dc5 Mon Sep 17 00:00:00 2001 From: Shane Carr Date: Mon, 10 Apr 2017 22:36:04 +0000 Subject: [PATCH] ICU-13118 Fixing Out-Of-Memory error in scientific number formatter. X-SVN-Rev: 40026 --- .../number/formatters/ScientificFormat.java | 17 ++++++++++------- .../icu/dev/test/format/NumberFormatTest.java | 11 +++++++++++ 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/formatters/ScientificFormat.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/formatters/ScientificFormat.java index 767eeaf718a..feae79634f8 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/formatters/ScientificFormat.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/formatters/ScientificFormat.java @@ -142,15 +142,18 @@ public class ScientificFormat extends Format.BeforeFormat implements Rounder.Mul private ScientificFormat(DecimalFormatSymbols symbols, IProperties properties, Rounder rounder) { exponentShowPlusSign = properties.getExponentSignAlwaysShown(); exponentDigits = Math.max(1, properties.getMinimumExponentDigits()); + + // Calculate minInt/maxInt for the purposes of engineering notation: + // 0 <= minInt <= maxInt < 8 + // The values are validated separately for rounding. This scheme needs to prevent OOM issues + // (see #13118). Note that the bound 8 on integer digits is historic. int _maxInt = properties.getMaximumIntegerDigits(); int _minInt = properties.getMinimumIntegerDigits(); - // Special behavior: - if (_maxInt > 8) { - _maxInt = _minInt; - } - maxInt = _maxInt < 0 ? Integer.MAX_VALUE : _maxInt; - minInt = _minInt < 0 ? 0 : _minInt < maxInt ? _minInt : maxInt; - interval = Math.max(1, maxInt); + minInt = _minInt < 0 ? 0 : _minInt >= 8 ? 1 : _minInt; + maxInt = _maxInt < _minInt ? _minInt : _maxInt >= 8 ? _minInt : _maxInt; + assert 0 <= minInt && minInt <= maxInt && maxInt < 8; + + interval = maxInt < 1 ? 1 : maxInt; this.rounder = rounder; digitStrings = symbols.getDigitStrings(); // makes a copy diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/NumberFormatTest.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/NumberFormatTest.java index ee13913e2ed..9afc18e1976 100644 --- a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/NumberFormatTest.java +++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/NumberFormatTest.java @@ -4992,6 +4992,17 @@ public class NumberFormatTest extends TestFmwk { expect2(numfmt, num, "‎٪ ‎−۱٬۲۳۴"); } + @Test + public void Test13118() { + DecimalFormat df = new DecimalFormat("@@@"); + df.setScientificNotation(true); + for (double d=12345.67; d>1e-6; d/=10) { + String result = df.format(d); + assertEquals("Should produce a string of expected length on " + d, + d > 1 ? 6 : 7, result.length()); + } + } + @Test public void testPercentZero() { DecimalFormat df = (DecimalFormat) NumberFormat.getPercentInstance(); -- 2.40.0