Skip to content

Commit 87d1097

Browse files
committedNov 24, 2022
8297530: java.lang.IllegalArgumentException: Negative length on strings concatenation
Reviewed-by: enikitin, alanb
1 parent 390e69a commit 87d1097

File tree

2 files changed

+141
-2
lines changed

2 files changed

+141
-2
lines changed
 

‎src/java.base/share/classes/java/lang/StringConcatHelper.java

+5-2
Original file line numberDiff line numberDiff line change
@@ -434,8 +434,11 @@ static byte[] newArrayWithSuffix(String suffix, long indexCoder) {
434434
@ForceInline
435435
static byte[] newArray(long indexCoder) {
436436
byte coder = (byte)(indexCoder >> 32);
437-
int index = (int)indexCoder;
438-
return (byte[]) UNSAFE.allocateUninitializedArray(byte.class, index << coder);
437+
int index = ((int)indexCoder) << coder;
438+
if (index < 0) {
439+
throw new OutOfMemoryError("Overflow: String length out of range");
440+
}
441+
return (byte[]) UNSAFE.allocateUninitializedArray(byte.class, index);
439442
}
440443

441444
/**
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
/*
2+
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
/**
25+
* @test 8297530
26+
* @summary This sanity tests that OOME is correctly thrown when
27+
* the length of the array to be allocated for a concatenation.
28+
* Before the fix for 8297530 an IllegalArgumentException could
29+
* erroneously be thrown when the length of the string is between
30+
* Integer.MAX_VALUE / 2 and Integer.MAX_VALUE and the String coder
31+
* is UTF16.
32+
*
33+
* @requires sun.arch.data.model == "64"
34+
* @run main/othervm -Xverify:all -Xmx4g ImplicitStringConcatOOME
35+
* @run main/othervm -Xverify:all -Xmx4g -XX:-CompactStrings ImplicitStringConcatOOME
36+
*/
37+
38+
import java.lang.reflect.Field;
39+
import java.lang.reflect.Modifier;
40+
41+
public class ImplicitStringConcatOOME {
42+
43+
static String s000, s001, s002, s003, s004, s005, s006, s007, s008, s009;
44+
static String s010, s011, s012, s013, s014, s015, s016, s017, s018, s019;
45+
static String s020, s021, s022, s023, s024, s025, s026, s027, s028, s029;
46+
static String s030, s031, s032, s033, s034, s035, s036, s037, s038, s039;
47+
static String s040, s041, s042, s043, s044, s045, s046, s047, s048, s049;
48+
static String s050, s051, s052, s053, s054, s055, s056, s057, s058, s059;
49+
static String s060, s061, s062, s063, s064, s065, s066, s067, s068, s069;
50+
static String s070, s071, s072, s073, s074, s075, s076, s077, s078, s079;
51+
static String s080, s081, s082, s083, s084, s085, s086, s087, s088, s089;
52+
static String s090, s091, s092, s093, s094, s095, s096, s097, s098, s099;
53+
54+
static String s100, s101, s102, s103, s104, s105, s106, s107, s108, s109;
55+
static String s110, s111, s112, s113, s114, s115, s116, s117, s118, s119;
56+
static String s120, s121, s122, s123, s124, s125, s126, s127, s128, s129;
57+
static String s130, s131, s132, s133, s134, s135, s136, s137, s138, s139;
58+
static String s140, s141, s142, s143, s144, s145, s146, s147, s148, s149;
59+
static String s150, s151, s152, s153, s154, s155, s156, s157, s158, s159;
60+
static String s160, s161, s162, s163, s164, s165, s166, s167, s168, s169;
61+
static String s170, s171, s172, s173, s174, s175, s176, s177, s178, s179;
62+
static String s180, s181, s182, s183, s184, s185, s186, s187, s188, s189;
63+
static String s190, s191, s192, s193, s194, s195, s196, s197, s198, s199;
64+
65+
static String s_utf16;
66+
static {
67+
String s = "10 letters".repeat(1_073_742);
68+
for (Field f : ImplicitStringConcatOOME.class.getDeclaredFields()) {
69+
if (Modifier.isStatic(f.getModifiers())) {
70+
try {
71+
f.set(null, s);
72+
} catch (IllegalAccessException e) {
73+
throw new IllegalStateException(e);
74+
}
75+
}
76+
}
77+
s_utf16 = "\u0257";
78+
}
79+
80+
public static void main(String[] args) throws Exception {
81+
try {
82+
String res =
83+
s000 + s001 + s002 + s003 + s004 + s005 + s006 + s007 + s008 + s009 +
84+
s010 + s011 + s012 + s013 + s014 + s015 + s016 + s017 + s018 + s019 +
85+
s020 + s021 + s022 + s023 + s024 + s025 + s026 + s027 + s028 + s029 +
86+
s030 + s031 + s032 + s033 + s034 + s035 + s036 + s037 + s038 + s039 +
87+
s040 + s041 + s042 + s043 + s044 + s045 + s046 + s047 + s048 + s049 +
88+
s050 + s051 + s052 + s053 + s054 + s055 + s056 + s057 + s058 + s059 +
89+
s060 + s061 + s062 + s063 + s064 + s065 + s066 + s067 + s068 + s069 +
90+
s070 + s071 + s072 + s073 + s074 + s075 + s076 + s077 + s078 + s079 +
91+
s080 + s081 + s082 + s083 + s084 + s085 + s086 + s087 + s088 + s089 +
92+
s090 + s091 + s092 + s093 + s094 + s095 + s096 + s097 + s098 + s099 +
93+
94+
s100 + s101 + s102 + s103 + s104 + s105 + s106 + s107 + s108 + s109 +
95+
s110 + s111 + s112 + s113 + s114 + s115 + s116 + s117 + s118 + s119 +
96+
s120 + s121 + s122 + s123 + s124 + s125 + s126 + s127 + s128 + s129 +
97+
s130 + s131 + s132 + s133 + s134 + s135 + s136 + s137 + s138 + s139 +
98+
s140 + s141 + s142 + s143 + s144 + s145 + s146 + s147 + s148 + s149 +
99+
s150 + s151 + s152 + s153 + s154 + s155 + s156 + s157 + s158 + s159 +
100+
s160 + s161 + s162 + s163 + s164 + s165 + s166 + s167 + s168 + s169 +
101+
s170 + s171 + s172 + s173 + s174 + s175 + s176 + s177 + s178 + s179 +
102+
s180 + s181 + s182 + s183 + s184 + s185 + s186 + s187 + s188 + s189 +
103+
s190 + s191 + s192 + s193 + s194 + s195 + s196 + s197 + s198 + s199;
104+
throw new IllegalStateException("Expected OOME");
105+
} catch (OutOfMemoryError e) {
106+
// Expected
107+
}
108+
try {
109+
// Compact Strings meant capacity for UTF16 strings were cut in
110+
// half, regardless of -XX:+CompactStrings setting
111+
String res =
112+
s000 + s001 + s002 + s003 + s004 + s005 + s006 + s007 + s008 + s009 +
113+
s010 + s011 + s012 + s013 + s014 + s015 + s016 + s017 + s018 + s019 +
114+
s020 + s021 + s022 + s023 + s024 + s025 + s026 + s027 + s028 + s029 +
115+
s030 + s031 + s032 + s033 + s034 + s035 + s036 + s037 + s038 + s039 +
116+
s040 + s041 + s042 + s043 + s044 + s045 + s046 + s047 + s048 + s049 +
117+
s050 + s051 + s052 + s053 + s054 + s055 + s056 + s057 + s058 + s059 +
118+
s060 + s061 + s062 + s063 + s064 + s065 + s066 + s067 + s068 + s069 +
119+
s070 + s071 + s072 + s073 + s074 + s075 + s076 + s077 + s078 + s079 +
120+
s080 + s081 + s082 + s083 + s084 + s085 + s086 + s087 + s088 + s089 +
121+
s090 + s091 + s092 + s093 + s094 + s095 + s096 + s097 + s098 + s099 +
122+
s_utf16;
123+
throw new IllegalStateException("Expected OOME");
124+
} catch (OutOfMemoryError e) {
125+
// Expected
126+
}
127+
}
128+
129+
public static void test(String expected, String actual) {
130+
// Fingers crossed: String concat should work.
131+
if (!expected.equals(actual)) {
132+
throw new IllegalStateException("Expected = " + expected + ", actual = " + actual);
133+
}
134+
}
135+
}
136+

0 commit comments

Comments
 (0)
Please sign in to comment.