mirror of https://github.com/google/oss-fuzz.git
jackson-datatypes-collections: Fix OOM on Iterable creation of primitive byte array (#11339)
This PR fixes 3 false positive issues in https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=64623, https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=64625 and https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=64634 which accidentally loops a very large byte array for too many times. In `GuavaSerailizerFuzzer` case 11. The logic uses a combination of `Iterables.cycle(T...)` and `Iterables.limit(Iterable, int)` to create an iterator for the fuzzing process. But there is a bug in the creation causing OOM. In Java, the generic type application is only possible for non-primitive type. For example, if the following code is run, the result is 2 and `elements[0] = 1` and `elements[1] = 2` inside `genericTest(T...)` because the generic type retrieves the Integer type successfully and `T` is treated as `Integer`. ```java public class Test { public static void main (String[] args) { Integer[] test = {1, 2}; genericTest(test); } public static <T> T genericTest(T...elements) { System.out.println(elements.length); } } ``` But if the code changes to use a primitive type array instead like the following, the result is 2 and `elements[0][0] = 1` and `elements[0][1] = 2` inside `genericTest(T...)` because the generic type fails to convert the primitive type and thus it treats `T` as `int[]`. ```java public class Test { public static void main (String[] args) { int[] test = {1, 2}; genericTest(test); } public static <T> T genericTest(T...elements) { System.out.println(elements.length); } } ``` Because of the above reason, the original code in `GuavaSerializerFuzzer` shown below provides a `byte[]` to the `Iterables.cycle(T...)` method. Thus the later `Iterables.limit(Iterable, int)` is looping through the whole byte[] for limit time, instead of looping the byte elements in the byte[]. It results in OOM in some issues when the `data.consumeRemainingAsBytes()` returns a very large byte array (e.g. 10k bytes). Instead of looping each byte in the byte array, it actually loops the whole byte array as a single object for 10k times which uses up the heap memory and causes OOM. ```java Iterables.limit(Iterables.cycle(data.consumeRemainingAsBytes()), remainingBytes)) ``` This PR fixes the problem by using the `Bytes.asList()` to retrieve the correct iterable objects for the fuzzing. Signed-off-by: Arthur Chan <arthur.chan@adalogics.com>
This commit is contained in:
parent
3a8b77fdde
commit
6b64a6b331
|
@ -25,7 +25,6 @@ import com.google.common.collect.FluentIterable;
|
|||
import com.google.common.collect.HashMultimap;
|
||||
import com.google.common.collect.ImmutableRangeSet;
|
||||
import com.google.common.collect.ImmutableTable;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.LinkedHashMultiset;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.collect.Multiset;
|
||||
|
@ -35,6 +34,7 @@ import com.google.common.collect.TreeRangeSet;
|
|||
import com.google.common.hash.HashCode;
|
||||
import com.google.common.net.HostAndPort;
|
||||
import com.google.common.net.InternetDomainName;
|
||||
import com.google.common.primitives.Bytes;
|
||||
import java.io.IOException;
|
||||
|
||||
/** This fuzzer targets the serialization methods of Guava objects */
|
||||
|
@ -122,9 +122,7 @@ public class GuavaSerializerFuzzer {
|
|||
.build();
|
||||
mapper.writeValueAsString(immutableRangeSet);
|
||||
case 11:
|
||||
Integer remainingBytes = data.remainingBytes();
|
||||
mapper.writeValueAsString(
|
||||
Iterables.limit(Iterables.cycle(data.consumeRemainingAsBytes()), remainingBytes));
|
||||
mapper.writeValueAsString(Bytes.asList(data.consumeRemainingAsBytes()).iterator());
|
||||
case 12:
|
||||
ArrayListMultimap<String, Object> arrayListMultimap = ArrayListMultimap.create();
|
||||
arrayListMultimap.put(
|
||||
|
|
Loading…
Reference in New Issue