8025535: Unsafe typecast in java.util.stream.SortedOps
Reviewed-by: mduigou, chegar
This commit is contained in:
parent
f640e20e65
commit
7ee60c366e
@ -277,8 +277,10 @@ final class SortedOps {
|
||||
}
|
||||
}
|
||||
|
||||
private static final String BAD_SIZE = "Stream size exceeds max array size";
|
||||
|
||||
/**
|
||||
* {@link ForkJoinTask} for implementing sort on SIZED reference streams.
|
||||
* {@link Sink} for implementing sort on SIZED reference streams.
|
||||
*/
|
||||
private static final class SizedRefSortingSink<T> extends Sink.ChainedReference<T, T> {
|
||||
private final Comparator<? super T> comparator;
|
||||
@ -293,16 +295,12 @@ final class SortedOps {
|
||||
@Override
|
||||
public void begin(long size) {
|
||||
if (size >= Nodes.MAX_ARRAY_SIZE)
|
||||
throw new IllegalArgumentException("Stream size exceeds max array size");
|
||||
throw new IllegalArgumentException(BAD_SIZE);
|
||||
array = (T[]) new Object[(int) size];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void end() {
|
||||
// Need to use offset rather than array.length since the downstream
|
||||
// many be short-circuiting
|
||||
// @@@ A better approach is to know if the downstream short-circuits
|
||||
// and check sink.cancellationRequested
|
||||
Arrays.sort(array, 0, offset, comparator);
|
||||
downstream.begin(offset);
|
||||
for (int i = 0; i < offset; i++)
|
||||
@ -331,6 +329,8 @@ final class SortedOps {
|
||||
|
||||
@Override
|
||||
public void begin(long size) {
|
||||
if (size >= Nodes.MAX_ARRAY_SIZE)
|
||||
throw new IllegalArgumentException(BAD_SIZE);
|
||||
list = (size >= 0) ? new ArrayList<T>((int) size) : new ArrayList<T>();
|
||||
}
|
||||
|
||||
@ -363,7 +363,7 @@ final class SortedOps {
|
||||
@Override
|
||||
public void begin(long size) {
|
||||
if (size >= Nodes.MAX_ARRAY_SIZE)
|
||||
throw new IllegalArgumentException("Stream size exceeds max array size");
|
||||
throw new IllegalArgumentException(BAD_SIZE);
|
||||
array = new int[(int) size];
|
||||
}
|
||||
|
||||
@ -395,6 +395,8 @@ final class SortedOps {
|
||||
|
||||
@Override
|
||||
public void begin(long size) {
|
||||
if (size >= Nodes.MAX_ARRAY_SIZE)
|
||||
throw new IllegalArgumentException(BAD_SIZE);
|
||||
b = (size > 0) ? new SpinedBuffer.OfInt((int) size) : new SpinedBuffer.OfInt();
|
||||
}
|
||||
|
||||
@ -428,7 +430,7 @@ final class SortedOps {
|
||||
@Override
|
||||
public void begin(long size) {
|
||||
if (size >= Nodes.MAX_ARRAY_SIZE)
|
||||
throw new IllegalArgumentException("Stream size exceeds max array size");
|
||||
throw new IllegalArgumentException(BAD_SIZE);
|
||||
array = new long[(int) size];
|
||||
}
|
||||
|
||||
@ -460,6 +462,8 @@ final class SortedOps {
|
||||
|
||||
@Override
|
||||
public void begin(long size) {
|
||||
if (size >= Nodes.MAX_ARRAY_SIZE)
|
||||
throw new IllegalArgumentException(BAD_SIZE);
|
||||
b = (size > 0) ? new SpinedBuffer.OfLong((int) size) : new SpinedBuffer.OfLong();
|
||||
}
|
||||
|
||||
@ -493,7 +497,7 @@ final class SortedOps {
|
||||
@Override
|
||||
public void begin(long size) {
|
||||
if (size >= Nodes.MAX_ARRAY_SIZE)
|
||||
throw new IllegalArgumentException("Stream size exceeds max array size");
|
||||
throw new IllegalArgumentException(BAD_SIZE);
|
||||
array = new double[(int) size];
|
||||
}
|
||||
|
||||
@ -525,6 +529,8 @@ final class SortedOps {
|
||||
|
||||
@Override
|
||||
public void begin(long size) {
|
||||
if (size >= Nodes.MAX_ARRAY_SIZE)
|
||||
throw new IllegalArgumentException(BAD_SIZE);
|
||||
b = (size > 0) ? new SpinedBuffer.OfDouble((int) size) : new SpinedBuffer.OfDouble();
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,8 @@ import org.testng.annotations.Test;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Spliterators;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.*;
|
||||
|
||||
import static java.util.stream.LambdaTestHelpers.*;
|
||||
@ -37,6 +39,69 @@ import static java.util.stream.LambdaTestHelpers.*;
|
||||
*/
|
||||
@Test
|
||||
public class SortedOpTest extends OpTestCase {
|
||||
|
||||
public void testRefStreamTooLarge() {
|
||||
Function<LongStream, Stream<Long>> f = s ->
|
||||
// Clear the SORTED flag
|
||||
s.mapToObj(i -> i)
|
||||
.sorted();
|
||||
|
||||
testStreamTooLarge(f, Stream::findFirst);
|
||||
}
|
||||
|
||||
public void testIntStreamTooLarge() {
|
||||
Function<LongStream, IntStream> f = s ->
|
||||
// Clear the SORTED flag
|
||||
s.mapToInt(i -> (int) i)
|
||||
.sorted();
|
||||
|
||||
testStreamTooLarge(f, IntStream::findFirst);
|
||||
}
|
||||
|
||||
public void testLongStreamTooLarge() {
|
||||
Function<LongStream, LongStream> f = s ->
|
||||
// Clear the SORTED flag
|
||||
s.map(i -> i)
|
||||
.sorted();
|
||||
|
||||
testStreamTooLarge(f, LongStream::findFirst);
|
||||
}
|
||||
|
||||
public void testDoubleStreamTooLarge() {
|
||||
Function<LongStream, DoubleStream> f = s ->
|
||||
// Clear the SORTED flag
|
||||
s.mapToDouble(i -> (double) i)
|
||||
.sorted();
|
||||
|
||||
testStreamTooLarge(f, DoubleStream::findFirst);
|
||||
}
|
||||
|
||||
<T, S extends BaseStream<T, S>> void testStreamTooLarge(Function<LongStream, S> s,
|
||||
Function<S, ?> terminal) {
|
||||
// Set up conditions for a large input > maximum array size
|
||||
Supplier<LongStream> input = () -> LongStream.range(0, 1L + Integer.MAX_VALUE);
|
||||
|
||||
// Transformation functions
|
||||
List<Function<LongStream, LongStream>> transforms = Arrays.asList(
|
||||
ls -> ls,
|
||||
ls -> ls.parallel(),
|
||||
// Clear the SIZED flag
|
||||
ls -> ls.limit(Long.MAX_VALUE),
|
||||
ls -> ls.limit(Long.MAX_VALUE).parallel());
|
||||
|
||||
for (Function<LongStream, LongStream> transform : transforms) {
|
||||
RuntimeException caught = null;
|
||||
try {
|
||||
terminal.apply(s.apply(transform.apply(input.get())));
|
||||
} catch (RuntimeException e) {
|
||||
caught = e;
|
||||
}
|
||||
assertNotNull(caught, "Expected an instance of exception IllegalArgumentException but no exception thrown");
|
||||
assertTrue(caught instanceof IllegalArgumentException,
|
||||
String.format("Expected an instance of exception IllegalArgumentException but got %s", caught));
|
||||
}
|
||||
}
|
||||
|
||||
public void testSorted() {
|
||||
assertCountSum(countTo(0).stream().sorted(), 0, 0);
|
||||
assertCountSum(countTo(10).stream().sorted(), 10, 55);
|
||||
|
Loading…
x
Reference in New Issue
Block a user