From fa20f134df1365a786026c9a582a8df1b6c7b0e1 Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Fri, 17 Jul 2026 20:01:43 +0100 Subject: [PATCH] bigint check --- .../apache/xmlbeans/impl/util/MathUtil.java | 17 ++++++++ .../impl/values/JavaDecimalHolder.java | 2 +- .../xmlbeans/impl/values/JavaIntHolder.java | 3 +- .../impl/values/JavaIntegerHolder.java | 2 +- .../impl/values/JavaIntegerHolderEx.java | 3 +- .../xmlbeans/impl/values/JavaLongHolder.java | 3 +- .../xmlbeans/impl/values/XmlObjectBase.java | 3 +- .../xmlbeans/impl/util/TestMathUtil.java | 39 +++++++++++++++++++ 8 files changed, 66 insertions(+), 6 deletions(-) create mode 100644 src/test/java/org/apache/xmlbeans/impl/util/TestMathUtil.java diff --git a/src/main/java/org/apache/xmlbeans/impl/util/MathUtil.java b/src/main/java/org/apache/xmlbeans/impl/util/MathUtil.java index d263575e9..66caaa53f 100644 --- a/src/main/java/org/apache/xmlbeans/impl/util/MathUtil.java +++ b/src/main/java/org/apache/xmlbeans/impl/util/MathUtil.java @@ -155,4 +155,21 @@ public static Integer parseAsInteger(String s) { } return Integer.parseInt(s); } + + /** + * @param value BigDecimal to convert + * @return valid BigInteger + * @throws IllegalArgumentException if the input has an absolute exponent that is too large to safely convert + * @throws NullPointerException if string is null + */ + public static BigInteger toBigInteger(BigDecimal value) { + BigDecimal normalized = value.stripTrailingZeros(); + int integerDigits = normalized.precision() - normalized.scale(); + if (integerDigits > MAX_NUMBER_LENGTH || normalized.scale() < -MAX_NUMBER_LENGTH) { + throw new IllegalArgumentException( + "BigDecimal magnitude too large to convert safely: approx " + + integerDigits + " integer digits (limit " + MAX_NUMBER_LENGTH + ")"); + } + return normalized.toBigInteger(); + } } diff --git a/src/main/java/org/apache/xmlbeans/impl/values/JavaDecimalHolder.java b/src/main/java/org/apache/xmlbeans/impl/values/JavaDecimalHolder.java index afb93b045..97acb3448 100644 --- a/src/main/java/org/apache/xmlbeans/impl/values/JavaDecimalHolder.java +++ b/src/main/java/org/apache/xmlbeans/impl/values/JavaDecimalHolder.java @@ -156,7 +156,7 @@ protected int value_hash_code() { } } - BigInteger intval = _value.toBigInteger(); + BigInteger intval = MathUtil.toBigInteger(_value); if (intval.compareTo(_maxlong) > 0 || intval.compareTo(_minlong) < 0) { diff --git a/src/main/java/org/apache/xmlbeans/impl/values/JavaIntHolder.java b/src/main/java/org/apache/xmlbeans/impl/values/JavaIntHolder.java index 29b5eddc8..48d533474 100644 --- a/src/main/java/org/apache/xmlbeans/impl/values/JavaIntHolder.java +++ b/src/main/java/org/apache/xmlbeans/impl/values/JavaIntHolder.java @@ -20,6 +20,7 @@ import org.apache.xmlbeans.XmlErrorCodes; import org.apache.xmlbeans.XmlObject; import org.apache.xmlbeans.impl.schema.BuiltinSchemaTypeSystem; +import org.apache.xmlbeans.impl.util.MathUtil; import org.apache.xmlbeans.impl.util.XsTypeConverter; import java.math.BigDecimal; @@ -77,7 +78,7 @@ public int getIntValue() { // setters protected void set_BigDecimal(BigDecimal v) { - set_BigInteger(v.toBigInteger()); + set_BigInteger(MathUtil.toBigInteger(v)); } protected void set_BigInteger(BigInteger v) { diff --git a/src/main/java/org/apache/xmlbeans/impl/values/JavaIntegerHolder.java b/src/main/java/org/apache/xmlbeans/impl/values/JavaIntegerHolder.java index 6edd803ef..ffc2bc0be 100644 --- a/src/main/java/org/apache/xmlbeans/impl/values/JavaIntegerHolder.java +++ b/src/main/java/org/apache/xmlbeans/impl/values/JavaIntegerHolder.java @@ -74,7 +74,7 @@ public BigInteger getBigIntegerValue() { // setters protected void set_BigDecimal(BigDecimal v) { - _value = v.toBigInteger(); + _value = MathUtil.toBigInteger(v); } protected void set_BigInteger(BigInteger v) { diff --git a/src/main/java/org/apache/xmlbeans/impl/values/JavaIntegerHolderEx.java b/src/main/java/org/apache/xmlbeans/impl/values/JavaIntegerHolderEx.java index 6ecb2b30b..53ce72999 100644 --- a/src/main/java/org/apache/xmlbeans/impl/values/JavaIntegerHolderEx.java +++ b/src/main/java/org/apache/xmlbeans/impl/values/JavaIntegerHolderEx.java @@ -21,6 +21,7 @@ import org.apache.xmlbeans.XmlPositiveInteger; import org.apache.xmlbeans.impl.common.QNameHelper; import org.apache.xmlbeans.impl.common.ValidationContext; +import org.apache.xmlbeans.impl.util.MathUtil; import java.math.BigInteger; @@ -152,7 +153,7 @@ private static BigInteger getBigIntegerValue(XmlObject o) { SchemaType s = o.schemaType(); switch (s.getDecimalSize()) { case SchemaType.SIZE_BIG_DECIMAL: - return ((XmlObjectBase) o).getBigDecimalValue().toBigInteger(); + return MathUtil.toBigInteger(((XmlObjectBase) o).getBigDecimalValue()); case SchemaType.SIZE_BIG_INTEGER: return ((XmlObjectBase) o).getBigIntegerValue(); default: diff --git a/src/main/java/org/apache/xmlbeans/impl/values/JavaLongHolder.java b/src/main/java/org/apache/xmlbeans/impl/values/JavaLongHolder.java index d3ffbbe50..d432a0b20 100644 --- a/src/main/java/org/apache/xmlbeans/impl/values/JavaLongHolder.java +++ b/src/main/java/org/apache/xmlbeans/impl/values/JavaLongHolder.java @@ -20,6 +20,7 @@ import org.apache.xmlbeans.XmlErrorCodes; import org.apache.xmlbeans.XmlObject; import org.apache.xmlbeans.impl.schema.BuiltinSchemaTypeSystem; +import org.apache.xmlbeans.impl.util.MathUtil; import org.apache.xmlbeans.impl.util.XsTypeConverter; import java.math.BigDecimal; @@ -72,7 +73,7 @@ public long getLongValue() { // setters protected void set_BigDecimal(BigDecimal v) { - set_BigInteger(v.toBigInteger()); + set_BigInteger(MathUtil.toBigInteger(v)); } protected void set_BigInteger(BigInteger v) { diff --git a/src/main/java/org/apache/xmlbeans/impl/values/XmlObjectBase.java b/src/main/java/org/apache/xmlbeans/impl/values/XmlObjectBase.java index d08c50641..8623ff50f 100644 --- a/src/main/java/org/apache/xmlbeans/impl/values/XmlObjectBase.java +++ b/src/main/java/org/apache/xmlbeans/impl/values/XmlObjectBase.java @@ -20,6 +20,7 @@ import org.apache.xmlbeans.impl.schema.SchemaTypeImpl; import org.apache.xmlbeans.impl.schema.SchemaTypeVisitorImpl; import org.apache.xmlbeans.impl.util.LongUTFDataInputStream; +import org.apache.xmlbeans.impl.util.MathUtil; import org.apache.xmlbeans.impl.validator.Validator; import org.w3c.dom.Node; import org.xml.sax.ContentHandler; @@ -1346,7 +1347,7 @@ public BigDecimal getBigDecimalValue() { // numerics: integral public BigInteger getBigIntegerValue() { BigDecimal bd = getBigDecimalValue(); - return bd == null ? null : bd.toBigInteger(); + return bd == null ? null : MathUtil.toBigInteger(bd); } public byte getByteValue() { diff --git a/src/test/java/org/apache/xmlbeans/impl/util/TestMathUtil.java b/src/test/java/org/apache/xmlbeans/impl/util/TestMathUtil.java new file mode 100644 index 000000000..f56f46e61 --- /dev/null +++ b/src/test/java/org/apache/xmlbeans/impl/util/TestMathUtil.java @@ -0,0 +1,39 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.xmlbeans.impl.util; + +import org.junit.jupiter.api.Test; + +import java.math.BigDecimal; +import java.math.BigInteger; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class TestMathUtil { + @Test + public void testToBigInteger() { + BigInteger expected = new BigInteger("1234567890"); + assertEquals(expected, MathUtil.toBigInteger(new BigDecimal(expected))); + } + + @Test + public void testToBigIntegerBigExponent() { + BigDecimal expected = new BigDecimal("1E+2000"); + assertThrows(IllegalArgumentException.class, () -> MathUtil.toBigInteger(expected)); + } +}