|
24 | 24 | import static com.code_intelligence.jazzer.mutation.mutator.lang.PrimitiveArrayMutatorFactory.PrimitiveArrayMutator.getLongPrimitiveArray; |
25 | 25 | import static com.code_intelligence.jazzer.mutation.mutator.lang.PrimitiveArrayMutatorFactory.PrimitiveArrayMutator.getShortPrimitiveArray; |
26 | 26 | import static com.code_intelligence.jazzer.mutation.mutator.lang.PrimitiveArrayMutatorFactory.PrimitiveArrayMutator.makePrimitiveArrayToBytesConverter; |
| 27 | +import static com.code_intelligence.jazzer.mutation.support.TypeSupport.notNull; |
| 28 | +import static com.code_intelligence.jazzer.mutation.support.TypeSupport.withLength; |
27 | 29 | import static com.google.common.truth.Truth.assertThat; |
28 | 30 | import static org.junit.jupiter.params.provider.Arguments.arguments; |
29 | 31 |
|
| 32 | +import com.code_intelligence.jazzer.mutation.api.SerializingMutator; |
| 33 | +import com.code_intelligence.jazzer.mutation.engine.ChainedMutatorFactory; |
30 | 34 | import com.code_intelligence.jazzer.mutation.support.TypeHolder; |
| 35 | +import java.io.ByteArrayInputStream; |
| 36 | +import java.io.ByteArrayOutputStream; |
| 37 | +import java.io.DataInputStream; |
| 38 | +import java.io.DataOutputStream; |
| 39 | +import java.io.IOException; |
31 | 40 | import java.lang.reflect.AnnotatedArrayType; |
32 | 41 | import java.lang.reflect.AnnotatedType; |
33 | 42 | import java.util.function.Function; |
@@ -636,4 +645,68 @@ void testRoundTrip_bytes(byte[] numbers) { |
636 | 645 | assertThat(libfuzzerBytesToBytes.apply(bytesToLibfuzzerBytes.apply(numbers))) |
637 | 646 | .isEqualTo(numbers); |
638 | 647 | } |
| 648 | + |
| 649 | + /* |
| 650 | + Testing that the maxRange for the byte[] type is 4096 bytes, which is the default max range for byte[] in Jazzer. |
| 651 | + This is important to ensure that the mutator does not generate byte arrays that are too large, which could lead to out-of-memory errors during fuzzing. |
| 652 | + */ |
| 653 | + static Stream<Arguments> byteArrayLength() { |
| 654 | + AnnotatedType defaultLen = new TypeHolder<byte[]>() {}.annotatedType(); |
| 655 | + AnnotatedType defaultLenNN = notNull(new TypeHolder<byte[]>() {}.annotatedType()); |
| 656 | + AnnotatedType withLen_10_20 = withLength(new TypeHolder<byte[]>() {}.annotatedType(), 10, 20); |
| 657 | + AnnotatedType withLen_10_5000 = |
| 658 | + withLength(new TypeHolder<byte[]>() {}.annotatedType(), 10, 5000); |
| 659 | + AnnotatedType withLen_10_20_NN = |
| 660 | + withLength(notNull(new TypeHolder<byte[]>() {}.annotatedType()), 10, 20); |
| 661 | + AnnotatedType withLen_10_5000_NN = |
| 662 | + withLength(notNull(new TypeHolder<byte[]>() {}.annotatedType()), 10, 5000); |
| 663 | + // type, numBytes to serialize with write(), expectedNumBytes after deserialization with read() |
| 664 | + return Stream.of( |
| 665 | + arguments(defaultLen, 5000, 4096), |
| 666 | + arguments(defaultLen, 100, 100), |
| 667 | + arguments(defaultLen, 0, 0), |
| 668 | + arguments(defaultLenNN, 5000, 4096), |
| 669 | + arguments(defaultLenNN, 100, 100), |
| 670 | + arguments(defaultLenNN, 0, 0), |
| 671 | + arguments(withLen_10_20, 15, 15), |
| 672 | + arguments(withLen_10_20, 25, 20), |
| 673 | + arguments(withLen_10_5000, 15, 15), |
| 674 | + arguments(withLen_10_5000, 25, 25), |
| 675 | + arguments(withLen_10_5000, 5000, 5000), |
| 676 | + arguments(withLen_10_5000, 10000, 5000), |
| 677 | + arguments(withLen_10_20_NN, 15, 15), |
| 678 | + arguments(withLen_10_20_NN, 25, 20), |
| 679 | + arguments(withLen_10_5000_NN, 15, 15), |
| 680 | + arguments(withLen_10_5000_NN, 25, 25), |
| 681 | + arguments(withLen_10_5000_NN, 5000, 5000), |
| 682 | + arguments(withLen_10_5000_NN, 10000, 5000)); |
| 683 | + } |
| 684 | + |
| 685 | + @ParameterizedTest |
| 686 | + @MethodSource("byteArrayLength") |
| 687 | + public void testByteArrayMaxRange_writeReadWithLength( |
| 688 | + AnnotatedType type, int serializationLength, int expectedReadLength) throws IOException { |
| 689 | + ChainedMutatorFactory factory = ChainedMutatorFactory.of(LangMutators.newFactories()); |
| 690 | + SerializingMutator<byte[]> mutator = (SerializingMutator<byte[]>) factory.createOrThrow(type); |
| 691 | + |
| 692 | + byte[] serialized; |
| 693 | + |
| 694 | + // serialize with write() |
| 695 | + ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
| 696 | + mutator.write(new byte[serializationLength], new DataOutputStream(baos)); |
| 697 | + serialized = baos.toByteArray(); |
| 698 | + |
| 699 | + // deserialize with read() |
| 700 | + byte[] data = mutator.read(new DataInputStream(new ByteArrayInputStream(serialized))); |
| 701 | + assertThat(data.length).isEqualTo(expectedReadLength); |
| 702 | + |
| 703 | + // serialize with writeExclusive() |
| 704 | + baos = new ByteArrayOutputStream(); |
| 705 | + mutator.writeExclusive(new byte[serializationLength], new DataOutputStream(baos)); |
| 706 | + serialized = baos.toByteArray(); |
| 707 | + |
| 708 | + // deserialize with readExclusive() |
| 709 | + data = mutator.readExclusive(new DataInputStream(new ByteArrayInputStream(serialized))); |
| 710 | + assertThat(data.length).isEqualTo(expectedReadLength); |
| 711 | + } |
639 | 712 | } |
0 commit comments