GuavaSerializerFuzzer.java
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
///////////////////////////////////////////////////////////////////////////
import com.code_intelligence.jazzer.api.FuzzedDataProvider;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.guava.GuavaModule;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.collect.ArrayListMultimap;
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.LinkedHashMultiset;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multiset;
import com.google.common.collect.Range;
import com.google.common.collect.RangeSet;
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 */
public class GuavaSerializerFuzzer {
private static ObjectMapper mapper;
public static void fuzzerInitialize() {
// Register the GuavaModule for the serialization
GuavaModule module = new GuavaModule();
module.configureAbsentsAsNulls(false);
mapper = new ObjectMapper().registerModule(module);
}
public static void fuzzerTestOneInput(FuzzedDataProvider data) {
try {
// Fuzz the serialize methods for different Guava objects
Integer listSize = data.consumeInt(1, 10);
switch (data.consumeInt(1, 12)) {
case 1:
Cache<String, String> cache = CacheBuilder.newBuilder().build();
cache.put(data.consumeString(data.remainingBytes()), data.consumeRemainingAsString());
mapper.enable(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS);
mapper.writeValueAsString(cache);
break;
case 2:
byte[] bytes = data.consumeRemainingAsBytes();
Byte[] byteArray = new Byte[bytes.length];
for (int i = 0; i < bytes.length; i++) {
byteArray[i] = bytes[i];
}
FluentIterable fluentIterable = FluentIterable.from(byteArray);
mapper.writeValueAsString(fluentIterable);
break;
case 3:
HashCode hashCode = HashCode.fromString(data.consumeRemainingAsString());
mapper.writeValueAsString(hashCode);
break;
case 4:
HostAndPort hostAndPort =
HostAndPort.fromParts(
data.consumeString(data.remainingBytes()), data.consumeInt(1, 65536));
mapper.writeValueAsString(hostAndPort);
break;
case 5:
Multimap<String, byte[]> multimap = HashMultimap.create();
multimap.put(data.consumeString(data.remainingBytes()), data.consumeRemainingAsBytes());
mapper
.writer()
.without(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS)
.writeValueAsString(multimap);
break;
case 6:
InternetDomainName internetDomainName =
InternetDomainName.from(data.consumeRemainingAsString());
mapper.writeValueAsString(internetDomainName);
break;
case 7:
ImmutableTable.Builder<Integer, String, String> immutableTableBuilder =
ImmutableTable.builder();
immutableTableBuilder.put(
data.consumeInt(1, 10),
data.consumeString(data.remainingBytes()),
data.consumeRemainingAsString());
ImmutableTable<Integer, String, String> immutableTable = immutableTableBuilder.build();
mapper.writeValueAsString(immutableTable);
break;
case 8:
Multiset<String> multiSet = LinkedHashMultiset.create();
multiSet.add(data.consumeRemainingAsString());
mapper.writeValueAsString(multiSet);
break;
case 9:
RangeSet<Integer> rangeSet = TreeRangeSet.create();
rangeSet.add(Range.closedOpen(data.consumeInt(), data.consumeInt()));
rangeSet.add(Range.openClosed(data.consumeInt(), data.consumeInt()));
rangeSet.add(Range.all());
mapper.writeValueAsString(rangeSet);
break;
case 10:
ImmutableRangeSet<Integer> immutableRangeSet =
ImmutableRangeSet.<Integer>builder()
.add(Range.closedOpen(data.consumeInt(), data.consumeInt()))
.add(Range.openClosed(data.consumeInt(), data.consumeInt()))
.add(Range.all())
.build();
mapper.writeValueAsString(immutableRangeSet);
case 11:
mapper.writeValueAsString(Bytes.asList(data.consumeRemainingAsBytes()).iterator());
case 12:
ArrayListMultimap<String, Object> arrayListMultimap = ArrayListMultimap.create();
arrayListMultimap.put(
data.consumeString(data.remainingBytes()), data.consumeRemainingAsString());
ArrayListMultimapContainer container = new ArrayListMultimapContainer(arrayListMultimap);
mapper.writeValueAsString(container);
}
} catch (IOException | IllegalArgumentException e) {
// Known exception
}
}
private static class ArrayListMultimapContainer {
@JsonTypeInfo(include = JsonTypeInfo.As.PROPERTY, use = JsonTypeInfo.Id.CLASS)
public Object object;
public ArrayListMultimapContainer(Object object) {
this.object = object;
}
}
}