diff --git a/core/src/main/java/com/alibaba/fastjson2/JSONReaderUTF16.java b/core/src/main/java/com/alibaba/fastjson2/JSONReaderUTF16.java index 4effb63bcb..c99660d293 100644 --- a/core/src/main/java/com/alibaba/fastjson2/JSONReaderUTF16.java +++ b/core/src/main/java/com/alibaba/fastjson2/JSONReaderUTF16.java @@ -4379,18 +4379,12 @@ public final BigDecimal readBigDecimal() { } valueType = JSON_TYPE_INT; - boolean overflow = false; + int digitCount = 0; // Total digit count for overflow detection long longValue = 0; while (ch >= '0' && ch <= '9') { valid = true; - if (!overflow) { - long r = longValue * 10; - if ((longValue | 10) >>> 31 == 0L || (r / 10 == longValue)) { - longValue = r + (ch - '0'); - } else { - overflow = true; - } - } + longValue = (longValue << 3) + (longValue << 1) + (ch & 0xf); + digitCount++; if (offset == end) { ch = EOI; @@ -4400,10 +4394,6 @@ public final BigDecimal readBigDecimal() { ch = chars[offset++]; } - if (longValue < 0) { - overflow = true; - } - this.scale = 0; if (ch == '.') { valueType = JSON_TYPE_DEC; @@ -4411,14 +4401,8 @@ public final BigDecimal readBigDecimal() { while (ch >= '0' && ch <= '9') { valid = true; this.scale++; - if (!overflow) { - long r = longValue * 10; - if ((longValue | 10) >>> 31 == 0L || (r / 10 == longValue)) { - longValue = r + (ch - '0'); - } else { - overflow = true; - } - } + longValue = (longValue << 3) + (longValue << 1) + (ch & 0xf); + digitCount++; if (offset == end) { ch = EOI; @@ -4429,6 +4413,9 @@ public final BigDecimal readBigDecimal() { } } + // Check overflow: more than 18 digits, or 19 digits with negative value (sign bit set) + boolean overflow = digitCount > 18 && (digitCount > 19 || longValue < 0); + int expValue = 0; if (ch == 'e' || ch == 'E') { boolean negativeExp; @@ -4520,8 +4507,12 @@ public final BigDecimal readBigDecimal() { } } if (!value) { - if (expValue == 0 && !overflow && longValue != 0) { - decimal = BigDecimal.valueOf(negative ? -longValue : longValue, scale); + if (!overflow && longValue != 0) { + // Combine scale and exponent: scale - expValue + // For 1.5E3: scale=1, exp=3 => combined=-2 => 1500 + // For 1.5E-3: scale=1, exp=-3 => combined=4 => 0.0015 + int combinedScale = scale - expValue; + decimal = BigDecimal.valueOf(negative ? -longValue : longValue, combinedScale); value = true; } diff --git a/core/src/main/java/com/alibaba/fastjson2/JSONReaderUTF8.java b/core/src/main/java/com/alibaba/fastjson2/JSONReaderUTF8.java index 9b4696de4d..e647deda14 100644 --- a/core/src/main/java/com/alibaba/fastjson2/JSONReaderUTF8.java +++ b/core/src/main/java/com/alibaba/fastjson2/JSONReaderUTF8.java @@ -6822,18 +6822,12 @@ public final BigDecimal readBigDecimal() { } valueType = JSON_TYPE_INT; - boolean overflow = false; + int digitCount = 0; // Total digit count for overflow detection long longValue = 0; while (ch >= '0' && ch <= '9') { valid = true; - if (!overflow) { - long r = longValue * 10; - if ((longValue | 10) >>> 31 == 0L || (r / 10 == longValue)) { - longValue = r + (ch - '0'); - } else { - overflow = true; - } - } + longValue = (longValue << 3) + (longValue << 1) + (ch & 0xf); + digitCount++; if (offset == end) { ch = EOI; @@ -6843,10 +6837,6 @@ public final BigDecimal readBigDecimal() { ch = bytes[offset++]; } - if (longValue < 0) { - overflow = true; - } - this.scale = 0; if (ch == '.') { valueType = JSON_TYPE_DEC; @@ -6854,14 +6844,8 @@ public final BigDecimal readBigDecimal() { while (ch >= '0' && ch <= '9') { valid = true; this.scale++; - if (!overflow) { - long r = longValue * 10; - if ((longValue | 10) >>> 31 == 0L || (r / 10 == longValue)) { - longValue = r + (ch - '0'); - } else { - overflow = true; - } - } + longValue = (longValue << 3) + (longValue << 1) + (ch & 0xf); + digitCount++; if (offset == end) { ch = EOI; @@ -6872,6 +6856,9 @@ public final BigDecimal readBigDecimal() { } } + // Check overflow: more than 18 digits, or 19 digits with negative value (sign bit set) + boolean overflow = digitCount > 18 && (digitCount > 19 || longValue < 0); + int expValue = 0; if (ch == 'e' || ch == 'E') { boolean negativeExp; @@ -6959,8 +6946,12 @@ public final BigDecimal readBigDecimal() { } } if (!value) { - if (expValue == 0 && !overflow && longValue != 0) { - decimal = BigDecimal.valueOf(negative ? -longValue : longValue, scale); + if (!overflow && longValue != 0) { + // Combine scale and exponent: scale - expValue + // For 1.5E3: scale=1, exp=3 => combined=-2 => 1500 + // For 1.5E-3: scale=1, exp=-3 => combined=4 => 0.0015 + int combinedScale = scale - expValue; + decimal = BigDecimal.valueOf(negative ? -longValue : longValue, combinedScale); value = true; }