Skip to content

Commit 8720b6b

Browse files
Istvan NeuwirthGoogle Java Core Libraries
Istvan Neuwirth
authored and
Google Java Core Libraries
committed
Changed Longs.concat() to throw IllegalArgumentException if the input arrays contain too many elements.
See #3303 Fixes #3304 RELNOTES=n/a PiperOrigin-RevId: 543451555
1 parent 01dcc2e commit 8720b6b

File tree

4 files changed

+86
-4
lines changed

4 files changed

+86
-4
lines changed

android/guava-tests/test/com/google/common/primitives/LongsTest.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,37 @@ public void testConcat() {
198198
.isEqualTo(new long[] {(long) 1, (long) 2, (long) 3, (long) 4});
199199
}
200200

201+
@GwtIncompatible // different overflow behavior; could probably be made to work by using ~~
202+
public void testConcat_overflow_negative() {
203+
int dim1 = 1 << 16;
204+
int dim2 = 1 << 15;
205+
assertThat(dim1 * dim2).isLessThan(0);
206+
testConcat_overflow(dim1, dim2);
207+
}
208+
209+
@GwtIncompatible // different overflow behavior; could probably be made to work by using ~~
210+
public void testConcat_overflow_nonNegative() {
211+
int dim1 = 1 << 16;
212+
int dim2 = 1 << 16;
213+
assertThat(dim1 * dim2).isAtLeast(0);
214+
testConcat_overflow(dim1, dim2);
215+
}
216+
217+
private static void testConcat_overflow(int arraysDim1, int arraysDim2) {
218+
assertThat((long) arraysDim1 * arraysDim2).isNotEqualTo((long) (arraysDim1 * arraysDim2));
219+
220+
long[][] arrays = new long[arraysDim1][];
221+
// it's shared to avoid using too much memory in tests
222+
long[] sharedArray = new long[arraysDim2];
223+
Arrays.fill(arrays, sharedArray);
224+
225+
try {
226+
Longs.concat(arrays);
227+
fail();
228+
} catch (IllegalArgumentException expected) {
229+
}
230+
}
231+
201232
private static void assertByteArrayEquals(byte[] expected, byte[] actual) {
202233
assertWithMessage(
203234
"Expected: " + Arrays.toString(expected) + ", but got: " + Arrays.toString(actual))

android/guava/src/com/google/common/primitives/Longs.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -244,13 +244,15 @@ public static long constrainToRange(long value, long min, long max) {
244244
*
245245
* @param arrays zero or more {@code long} arrays
246246
* @return a single array containing all the values from the source arrays, in order
247+
* @throws IllegalArgumentException if the total number of elements in {@code arrays} does not fit
248+
* in an {@code int}
247249
*/
248250
public static long[] concat(long[]... arrays) {
249-
int length = 0;
251+
long length = 0;
250252
for (long[] array : arrays) {
251253
length += array.length;
252254
}
253-
long[] result = new long[length];
255+
long[] result = new long[checkNoOverflow(length)];
254256
int pos = 0;
255257
for (long[] array : arrays) {
256258
System.arraycopy(array, 0, result, pos, array.length);
@@ -259,6 +261,14 @@ public static long[] concat(long[]... arrays) {
259261
return result;
260262
}
261263

264+
private static int checkNoOverflow(long result) {
265+
checkArgument(
266+
result == (int) result,
267+
"the total number of elements (%s) in the arrays must fit in an int",
268+
result);
269+
return (int) result;
270+
}
271+
262272
/**
263273
* Returns a big-endian representation of {@code value} in an 8-element byte array; equivalent to
264274
* {@code ByteBuffer.allocate(8).putLong(value).array()}. For example, the input value {@code

guava-tests/test/com/google/common/primitives/LongsTest.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,37 @@ public void testConcat() {
198198
.isEqualTo(new long[] {(long) 1, (long) 2, (long) 3, (long) 4});
199199
}
200200

201+
@GwtIncompatible // different overflow behavior; could probably be made to work by using ~~
202+
public void testConcat_overflow_negative() {
203+
int dim1 = 1 << 16;
204+
int dim2 = 1 << 15;
205+
assertThat(dim1 * dim2).isLessThan(0);
206+
testConcat_overflow(dim1, dim2);
207+
}
208+
209+
@GwtIncompatible // different overflow behavior; could probably be made to work by using ~~
210+
public void testConcat_overflow_nonNegative() {
211+
int dim1 = 1 << 16;
212+
int dim2 = 1 << 16;
213+
assertThat(dim1 * dim2).isAtLeast(0);
214+
testConcat_overflow(dim1, dim2);
215+
}
216+
217+
private static void testConcat_overflow(int arraysDim1, int arraysDim2) {
218+
assertThat((long) arraysDim1 * arraysDim2).isNotEqualTo((long) (arraysDim1 * arraysDim2));
219+
220+
long[][] arrays = new long[arraysDim1][];
221+
// it's shared to avoid using too much memory in tests
222+
long[] sharedArray = new long[arraysDim2];
223+
Arrays.fill(arrays, sharedArray);
224+
225+
try {
226+
Longs.concat(arrays);
227+
fail();
228+
} catch (IllegalArgumentException expected) {
229+
}
230+
}
231+
201232
private static void assertByteArrayEquals(byte[] expected, byte[] actual) {
202233
assertWithMessage(
203234
"Expected: " + Arrays.toString(expected) + ", but got: " + Arrays.toString(actual))

guava/src/com/google/common/primitives/Longs.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -246,13 +246,15 @@ public static long constrainToRange(long value, long min, long max) {
246246
*
247247
* @param arrays zero or more {@code long} arrays
248248
* @return a single array containing all the values from the source arrays, in order
249+
* @throws IllegalArgumentException if the total number of elements in {@code arrays} does not fit
250+
* in an {@code int}
249251
*/
250252
public static long[] concat(long[]... arrays) {
251-
int length = 0;
253+
long length = 0;
252254
for (long[] array : arrays) {
253255
length += array.length;
254256
}
255-
long[] result = new long[length];
257+
long[] result = new long[checkNoOverflow(length)];
256258
int pos = 0;
257259
for (long[] array : arrays) {
258260
System.arraycopy(array, 0, result, pos, array.length);
@@ -261,6 +263,14 @@ public static long[] concat(long[]... arrays) {
261263
return result;
262264
}
263265

266+
private static int checkNoOverflow(long result) {
267+
checkArgument(
268+
result == (int) result,
269+
"the total number of elements (%s) in the arrays must fit in an int",
270+
result);
271+
return (int) result;
272+
}
273+
264274
/**
265275
* Returns a big-endian representation of {@code value} in an 8-element byte array; equivalent to
266276
* {@code ByteBuffer.allocate(8).putLong(value).array()}. For example, the input value {@code

0 commit comments

Comments
 (0)