diff --git a/src/java.base/share/classes/java/lang/AbstractStringBuilder.java b/src/java.base/share/classes/java/lang/AbstractStringBuilder.java index b63e9d0921005..d317557cbb19c 100644 --- a/src/java.base/share/classes/java/lang/AbstractStringBuilder.java +++ b/src/java.base/share/classes/java/lang/AbstractStringBuilder.java @@ -924,9 +924,9 @@ public AbstractStringBuilder append(int i) { int spaceNeeded = count + DecimalDigits.stringSize(i); byte[] value = ensureCapacitySameCoder(this.value, coder, spaceNeeded); if (isLatin1(coder)) { - DecimalDigits.getCharsLatin1(i, spaceNeeded, value); + DecimalDigits.uncheckedGetCharsLatin1(i, spaceNeeded, value); } else { - DecimalDigits.getCharsUTF16(i, spaceNeeded, value); + DecimalDigits.uncheckedGetCharsUTF16(i, spaceNeeded, value); } this.value = value; this.count = spaceNeeded; @@ -951,9 +951,9 @@ public AbstractStringBuilder append(long l) { int spaceNeeded = count + DecimalDigits.stringSize(l); byte[] value = ensureCapacitySameCoder(this.value, coder, spaceNeeded); if (isLatin1(coder)) { - DecimalDigits.getCharsLatin1(l, spaceNeeded, value); + DecimalDigits.uncheckedGetCharsLatin1(l, spaceNeeded, value); } else { - DecimalDigits.getCharsUTF16(l, spaceNeeded, value); + DecimalDigits.uncheckedGetCharsUTF16(l, spaceNeeded, value); } this.value = value; this.count = spaceNeeded; diff --git a/src/java.base/share/classes/java/lang/Integer.java b/src/java.base/share/classes/java/lang/Integer.java index 1350a66b66c7c..a95149a3eddb5 100644 --- a/src/java.base/share/classes/java/lang/Integer.java +++ b/src/java.base/share/classes/java/lang/Integer.java @@ -432,11 +432,11 @@ public static String toString(int i) { int size = DecimalDigits.stringSize(i); if (COMPACT_STRINGS) { byte[] buf = new byte[size]; - DecimalDigits.getCharsLatin1(i, size, buf); + DecimalDigits.uncheckedGetCharsLatin1(i, size, buf); return new String(buf, LATIN1); } else { byte[] buf = new byte[size * 2]; - DecimalDigits.getCharsUTF16(i, size, buf); + DecimalDigits.uncheckedGetCharsUTF16(i, size, buf); return new String(buf, UTF16); } } diff --git a/src/java.base/share/classes/java/lang/Long.java b/src/java.base/share/classes/java/lang/Long.java index 3093f37e99ac7..20e07f41b9e10 100644 --- a/src/java.base/share/classes/java/lang/Long.java +++ b/src/java.base/share/classes/java/lang/Long.java @@ -462,11 +462,11 @@ public static String toString(long i) { int size = DecimalDigits.stringSize(i); if (COMPACT_STRINGS) { byte[] buf = new byte[size]; - DecimalDigits.getCharsLatin1(i, size, buf); + DecimalDigits.uncheckedGetCharsLatin1(i, size, buf); return new String(buf, LATIN1); } else { byte[] buf = new byte[size * 2]; - DecimalDigits.getCharsUTF16(i, size, buf); + DecimalDigits.uncheckedGetCharsUTF16(i, size, buf); return new String(buf, UTF16); } } diff --git a/src/java.base/share/classes/java/lang/StringConcatHelper.java b/src/java.base/share/classes/java/lang/StringConcatHelper.java index f82e392a1fb54..a5f6abbfdf179 100644 --- a/src/java.base/share/classes/java/lang/StringConcatHelper.java +++ b/src/java.base/share/classes/java/lang/StringConcatHelper.java @@ -315,12 +315,12 @@ static long prepend(long indexCoder, byte[] buf, char value, String prefix) { static long prepend(long indexCoder, byte[] buf, int value, String prefix) { int index = (int)indexCoder; if (indexCoder < UTF16) { - index = DecimalDigits.getCharsLatin1(value, index, buf); + index = DecimalDigits.uncheckedGetCharsLatin1(value, index, buf); index -= prefix.length(); prefix.getBytes(buf, index, String.LATIN1); return index; } else { - index = DecimalDigits.getCharsUTF16(value, index, buf); + index = DecimalDigits.uncheckedGetCharsUTF16(value, index, buf); index -= prefix.length(); prefix.getBytes(buf, index, String.UTF16); return index | UTF16; @@ -341,12 +341,12 @@ static long prepend(long indexCoder, byte[] buf, int value, String prefix) { static long prepend(long indexCoder, byte[] buf, long value, String prefix) { int index = (int)indexCoder; if (indexCoder < UTF16) { - index = DecimalDigits.getCharsLatin1(value, index, buf); + index = DecimalDigits.uncheckedGetCharsLatin1(value, index, buf); index -= prefix.length(); prefix.getBytes(buf, index, String.LATIN1); return index; } else { - index = DecimalDigits.getCharsUTF16(value, index, buf); + index = DecimalDigits.uncheckedGetCharsUTF16(value, index, buf); index -= prefix.length(); prefix.getBytes(buf, index, String.UTF16); return index | UTF16; @@ -713,11 +713,11 @@ static int prepend(int index, byte coder, byte[] buf, char value, String prefix) */ static int prepend(int index, byte coder, byte[] buf, int value, String prefix) { if (coder == String.LATIN1) { - index = DecimalDigits.getCharsLatin1(value, index, buf); + index = DecimalDigits.uncheckedGetCharsLatin1(value, index, buf); index -= prefix.length(); prefix.getBytes(buf, index, String.LATIN1); } else { - index = DecimalDigits.getCharsUTF16(value, index, buf); + index = DecimalDigits.uncheckedGetCharsUTF16(value, index, buf); index -= prefix.length(); prefix.getBytes(buf, index, String.UTF16); } @@ -737,11 +737,11 @@ static int prepend(int index, byte coder, byte[] buf, int value, String prefix) */ static int prepend(int index, byte coder, byte[] buf, long value, String prefix) { if (coder == String.LATIN1) { - index = DecimalDigits.getCharsLatin1(value, index, buf); + index = DecimalDigits.uncheckedGetCharsLatin1(value, index, buf); index -= prefix.length(); prefix.getBytes(buf, index, String.LATIN1); } else { - index = DecimalDigits.getCharsUTF16(value, index, buf); + index = DecimalDigits.uncheckedGetCharsUTF16(value, index, buf); index -= prefix.length(); prefix.getBytes(buf, index, String.UTF16); } diff --git a/src/java.base/share/classes/java/math/BigDecimal.java b/src/java.base/share/classes/java/math/BigDecimal.java index dd6253a713273..b7a2cad1d7679 100644 --- a/src/java.base/share/classes/java/math/BigDecimal.java +++ b/src/java.base/share/classes/java/math/BigDecimal.java @@ -4138,9 +4138,9 @@ private String layoutChars(boolean sci) { int highInt = (int)intCompact / 100; int highIntSize = DecimalDigits.stringSize(highInt); byte[] buf = new byte[highIntSize + 3]; - DecimalDigits.getCharsLatin1(highInt, highIntSize, buf); + DecimalDigits.uncheckedGetCharsLatin1(highInt, highIntSize, buf); buf[highIntSize] = '.'; - DecimalDigits.putPairLatin1(buf, highIntSize + 1, lowInt); + DecimalDigits.uncheckedPutPairLatin1(buf, highIntSize + 1, lowInt); try { return JLA.newStringNoRepl(buf, StandardCharsets.ISO_8859_1); } catch (CharacterCodingException cce) { diff --git a/src/java.base/share/classes/jdk/internal/util/DecimalDigits.java b/src/java.base/share/classes/jdk/internal/util/DecimalDigits.java index d3df46dcd3c4d..6c0c745651e34 100644 --- a/src/java.base/share/classes/jdk/internal/util/DecimalDigits.java +++ b/src/java.base/share/classes/jdk/internal/util/DecimalDigits.java @@ -143,14 +143,15 @@ public static int stringSize(long x) { * values, to cover the Integer.MIN_VALUE case. Converting otherwise * (negative to positive) will expose -Integer.MIN_VALUE that overflows * integer. + *
+ * WARNING: This method does not perform any bound checks. * * @param i value to convert * @param index next index, after the least significant digit * @param buf target buffer, Latin1-encoded * @return index of the most significant digit or minus sign, if present */ - public static int getCharsLatin1(int i, int index, byte[] buf) { - // Used by trusted callers. Assumes all necessary bounds checks have been done by the caller. + public static int uncheckedGetCharsLatin1(int i, int index, byte[] buf) { int q; int charPos = index; @@ -163,20 +164,20 @@ public static int getCharsLatin1(int i, int index, byte[] buf) { while (i <= -100) { q = i / 100; charPos -= 2; - putPairLatin1(buf, charPos, (q * 100) - i); + uncheckedPutPairLatin1(buf, charPos, (q * 100) - i); i = q; } // We know there are at most two digits left at this point. if (i <= -10) { charPos -= 2; - putPairLatin1(buf, charPos, -i); + uncheckedPutPairLatin1(buf, charPos, -i); } else { - putCharLatin1(buf, --charPos, '0' - i); + uncheckedPutCharLatin1(buf, --charPos, '0' - i); } if (negative) { - putCharLatin1(buf, --charPos, '-'); + uncheckedPutCharLatin1(buf, --charPos, '-'); } return charPos; } @@ -193,14 +194,15 @@ public static int getCharsLatin1(int i, int index, byte[] buf) { * values, to cover the Long.MIN_VALUE case. Converting otherwise * (negative to positive) will expose -Long.MIN_VALUE that overflows * long. + *
+ * WARNING: This method does not perform any bound checks. * * @param i value to convert * @param index next index, after the least significant digit * @param buf target buffer, Latin1-encoded * @return index of the most significant digit or minus sign, if present */ - public static int getCharsLatin1(long i, int index, byte[] buf) { - // Used by trusted callers. Assumes all necessary bounds checks have been done by the caller. + public static int uncheckedGetCharsLatin1(long i, int index, byte[] buf) { long q; int charPos = index; @@ -213,7 +215,7 @@ public static int getCharsLatin1(long i, int index, byte[] buf) { while (i < Integer.MIN_VALUE) { q = i / 100; charPos -= 2; - putPairLatin1(buf, charPos, (int)((q * 100) - i)); + uncheckedPutPairLatin1(buf, charPos, (int)((q * 100) - i)); i = q; } @@ -223,36 +225,37 @@ public static int getCharsLatin1(long i, int index, byte[] buf) { while (i2 <= -100) { q2 = i2 / 100; charPos -= 2; - putPairLatin1(buf, charPos, (q2 * 100) - i2); + uncheckedPutPairLatin1(buf, charPos, (q2 * 100) - i2); i2 = q2; } // We know there are at most two digits left at this point. if (i2 <= -10) { charPos -= 2; - putPairLatin1(buf, charPos, -i2); + uncheckedPutPairLatin1(buf, charPos, -i2); } else { - putCharLatin1(buf, --charPos, '0' - i2); + uncheckedPutCharLatin1(buf, --charPos, '0' - i2); } if (negative) { - putCharLatin1(buf, --charPos, '-'); + uncheckedPutCharLatin1(buf, --charPos, '-'); } return charPos; } /** - * This is a variant of {@link DecimalDigits#getCharsLatin1(int, int, byte[])}, but for + * This is a variant of {@link DecimalDigits#uncheckedGetCharsLatin1(int, int, byte[])}, but for * UTF-16 coder. + *
+ * WARNING: This method does not perform any bound checks. * * @param i value to convert * @param index next index, after the least significant digit * @param buf target buffer, UTF16-coded. * @return index of the most significant digit or minus sign, if present */ - public static int getCharsUTF16(int i, int index, byte[] buf) { - // Used by trusted callers. Assumes all necessary bounds checks have been done by the caller. + public static int uncheckedGetCharsUTF16(int i, int index, byte[] buf) { int q; int charPos = index; @@ -265,36 +268,37 @@ public static int getCharsUTF16(int i, int index, byte[] buf) { while (i <= -100) { q = i / 100; charPos -= 2; - putPairUTF16(buf, charPos, (q * 100) - i); + uncheckedPutPairUTF16(buf, charPos, (q * 100) - i); i = q; } // We know there are at most two digits left at this point. if (i <= -10) { charPos -= 2; - putPairUTF16(buf, charPos, -i); + uncheckedPutPairUTF16(buf, charPos, -i); } else { - putCharUTF16(buf, --charPos, '0' - i); + uncheckedPutCharUTF16(buf, --charPos, '0' - i); } if (negative) { - putCharUTF16(buf, --charPos, '-'); + uncheckedPutCharUTF16(buf, --charPos, '-'); } return charPos; } /** - * This is a variant of {@link DecimalDigits#getCharsLatin1(long, int, byte[])}, but for + * This is a variant of {@link DecimalDigits#uncheckedGetCharsLatin1(long, int, byte[])}, but for * UTF-16 coder. + *
+ * WARNING: This method does not perform any bound checks. * * @param i value to convert * @param index next index, after the least significant digit * @param buf target buffer, UTF16-coded. * @return index of the most significant digit or minus sign, if present */ - public static int getCharsUTF16(long i, int index, byte[] buf) { - // Used by trusted callers. Assumes all necessary bounds checks have been done by the caller. + public static int uncheckedGetCharsUTF16(long i, int index, byte[] buf) { long q; int charPos = index; @@ -307,7 +311,7 @@ public static int getCharsUTF16(long i, int index, byte[] buf) { while (i < Integer.MIN_VALUE) { q = i / 100; charPos -= 2; - putPairUTF16(buf, charPos, (int)((q * 100) - i)); + uncheckedPutPairUTF16(buf, charPos, (int)((q * 100) - i)); i = q; } @@ -317,26 +321,26 @@ public static int getCharsUTF16(long i, int index, byte[] buf) { while (i2 <= -100) { q2 = i2 / 100; charPos -= 2; - putPairUTF16(buf, charPos, (q2 * 100) - i2); + uncheckedPutPairUTF16(buf, charPos, (q2 * 100) - i2); i2 = q2; } // We know there are at most two digits left at this point. if (i2 <= -10) { charPos -= 2; - putPairUTF16(buf, charPos, -i2); + uncheckedPutPairUTF16(buf, charPos, -i2); } else { - putCharUTF16(buf, --charPos, '0' - i2); + uncheckedPutCharUTF16(buf, --charPos, '0' - i2); } if (negative) { - putCharUTF16(buf, --charPos, '-'); + uncheckedPutCharUTF16(buf, --charPos, '-'); } return charPos; } /** - * This is a variant of {@link DecimalDigits#getCharsUTF16(long, int, byte[])}, but for + * This is a variant of {@link DecimalDigits#uncheckedGetCharsUTF16(long, int, byte[])}, but for * UTF-16 coder. * * @param i value to convert @@ -345,7 +349,6 @@ public static int getCharsUTF16(long i, int index, byte[] buf) { * @return index of the most significant digit or minus sign, if present */ public static int getChars(long i, int index, char[] buf) { - // Used by trusted callers. Assumes all necessary bounds checks have been done by the caller. long q; int charPos = index; @@ -402,34 +405,42 @@ public static void putPair(char[] buf, int charPos, int v) { /** * Insert the 2-bytes integer into the buf as 2 decimal digit ASCII bytes, * only least significant 16 bits of {@code v} are used. + *
+ * WARNING: This method does not perform any bound checks. + * * @param buf byte buffer to copy into * @param charPos insert point * @param v to convert */ - public static void putPairLatin1(byte[] buf, int charPos, int v) { + public static void uncheckedPutPairLatin1(byte[] buf, int charPos, int v) { int packed = DIGITS[v & 0x7f]; - putCharLatin1(buf, charPos, packed & 0xFF); - putCharLatin1(buf, charPos + 1, packed >> 8); + uncheckedPutCharLatin1(buf, charPos, packed & 0xFF); + uncheckedPutCharLatin1(buf, charPos + 1, packed >> 8); } /** * Insert the 2-chars integer into the buf as 2 decimal digit UTF16 bytes, * only least significant 16 bits of {@code v} are used. + *
+ * WARNING: This method does not perform any bound checks. + * * @param buf byte buffer to copy into * @param charPos insert point * @param v to convert */ - public static void putPairUTF16(byte[] buf, int charPos, int v) { + public static void uncheckedPutPairUTF16(byte[] buf, int charPos, int v) { int packed = DIGITS[v & 0x7f]; - putCharUTF16(buf, charPos, packed & 0xFF); - putCharUTF16(buf, charPos + 1, packed >> 8); + uncheckedPutCharUTF16(buf, charPos, packed & 0xFF); + uncheckedPutCharUTF16(buf, charPos + 1, packed >> 8); } - private static void putCharLatin1(byte[] buf, int charPos, int c) { + private static void uncheckedPutCharLatin1(byte[] buf, int charPos, int c) { + assert charPos >= 0 && charPos < buf.length; UNSAFE.putByte(buf, ARRAY_BYTE_BASE_OFFSET + charPos, (byte) c); } - private static void putCharUTF16(byte[] buf, int charPos, int c) { + private static void uncheckedPutCharUTF16(byte[] buf, int charPos, int c) { + assert charPos >= 0 && charPos < (buf.length >> 1); UNSAFE.putCharUnaligned(buf, ARRAY_BYTE_BASE_OFFSET + ((long) charPos << 1), (char) c); } } diff --git a/test/hotspot/jtreg/compiler/patches/java.base/java/lang/Helper.java b/test/hotspot/jtreg/compiler/patches/java.base/java/lang/Helper.java index aef27bfb9a49e..e6c8b68fc6fc0 100644 --- a/test/hotspot/jtreg/compiler/patches/java.base/java/lang/Helper.java +++ b/test/hotspot/jtreg/compiler/patches/java.base/java/lang/Helper.java @@ -120,14 +120,14 @@ public static int codePointCountSB(byte[] val, int beginIndex, int endIndex) { public static int getChars(int i, int begin, int end, byte[] value) { StringUTF16.checkBoundsBeginEnd(begin, end, value); - int pos = DecimalDigits.getCharsUTF16(i, end, value); + int pos = DecimalDigits.uncheckedGetCharsUTF16(i, end, value); assert begin == pos; return pos; } public static int getChars(long l, int begin, int end, byte[] value) { StringUTF16.checkBoundsBeginEnd(begin, end, value); - int pos = DecimalDigits.getCharsUTF16(l, end, value); + int pos = DecimalDigits.uncheckedGetCharsUTF16(l, end, value); assert begin == pos; return pos; }