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 static final class SizedRefSortingSink<T> extends Sink.ChainedReference<T, T> {
|
||||||
private final Comparator<? super T> comparator;
|
private final Comparator<? super T> comparator;
|
||||||
@ -293,16 +295,12 @@ final class SortedOps {
|
|||||||
@Override
|
@Override
|
||||||
public void begin(long size) {
|
public void begin(long size) {
|
||||||
if (size >= Nodes.MAX_ARRAY_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];
|
array = (T[]) new Object[(int) size];
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void end() {
|
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);
|
Arrays.sort(array, 0, offset, comparator);
|
||||||
downstream.begin(offset);
|
downstream.begin(offset);
|
||||||
for (int i = 0; i < offset; i++)
|
for (int i = 0; i < offset; i++)
|
||||||
@ -331,6 +329,8 @@ final class SortedOps {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void begin(long size) {
|
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>();
|
list = (size >= 0) ? new ArrayList<T>((int) size) : new ArrayList<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -363,7 +363,7 @@ final class SortedOps {
|
|||||||
@Override
|
@Override
|
||||||
public void begin(long size) {
|
public void begin(long size) {
|
||||||
if (size >= Nodes.MAX_ARRAY_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];
|
array = new int[(int) size];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -395,6 +395,8 @@ final class SortedOps {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void begin(long size) {
|
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();
|
b = (size > 0) ? new SpinedBuffer.OfInt((int) size) : new SpinedBuffer.OfInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -428,7 +430,7 @@ final class SortedOps {
|
|||||||
@Override
|
@Override
|
||||||
public void begin(long size) {
|
public void begin(long size) {
|
||||||
if (size >= Nodes.MAX_ARRAY_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];
|
array = new long[(int) size];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -460,6 +462,8 @@ final class SortedOps {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void begin(long size) {
|
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();
|
b = (size > 0) ? new SpinedBuffer.OfLong((int) size) : new SpinedBuffer.OfLong();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -493,7 +497,7 @@ final class SortedOps {
|
|||||||
@Override
|
@Override
|
||||||
public void begin(long size) {
|
public void begin(long size) {
|
||||||
if (size >= Nodes.MAX_ARRAY_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];
|
array = new double[(int) size];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -525,6 +529,8 @@ final class SortedOps {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void begin(long size) {
|
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();
|
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.*;
|
||||||
import java.util.Spliterators;
|
import java.util.Spliterators;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.function.Supplier;
|
||||||
import java.util.stream.*;
|
import java.util.stream.*;
|
||||||
|
|
||||||
import static java.util.stream.LambdaTestHelpers.*;
|
import static java.util.stream.LambdaTestHelpers.*;
|
||||||
@ -37,6 +39,69 @@ import static java.util.stream.LambdaTestHelpers.*;
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public class SortedOpTest extends OpTestCase {
|
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() {
|
public void testSorted() {
|
||||||
assertCountSum(countTo(0).stream().sorted(), 0, 0);
|
assertCountSum(countTo(0).stream().sorted(), 0, 0);
|
||||||
assertCountSum(countTo(10).stream().sorted(), 10, 55);
|
assertCountSum(countTo(10).stream().sorted(), 10, 55);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user