Skip to content

Commit c64c841

Browse files
committed
feat: use @valuepool when mutating primitive arrays
1 parent 42b2e9a commit c64c841

File tree

1 file changed

+64
-0
lines changed

1 file changed

+64
-0
lines changed

src/main/java/com/code_intelligence/jazzer/mutation/mutator/lang/PrimitiveArrayMutatorFactory.java

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,19 @@
3636
import com.code_intelligence.jazzer.mutation.support.RangeSupport.FloatRange;
3737
import com.code_intelligence.jazzer.mutation.support.RangeSupport.LongRange;
3838
import com.code_intelligence.jazzer.mutation.support.TypeHolder;
39+
import com.code_intelligence.jazzer.mutation.support.ValuePoolSupport;
40+
import java.io.ByteArrayInputStream;
3941
import java.io.DataInputStream;
4042
import java.io.DataOutputStream;
4143
import java.io.IOException;
4244
import java.lang.reflect.AnnotatedArrayType;
4345
import java.lang.reflect.AnnotatedType;
4446
import java.nio.ByteBuffer;
47+
import java.util.Arrays;
4548
import java.util.Optional;
4649
import java.util.function.Function;
4750
import java.util.function.Predicate;
51+
import java.util.stream.Stream;
4852

4953
final class PrimitiveArrayMutatorFactory implements MutatorFactory {
5054

@@ -81,6 +85,7 @@ public static final class PrimitiveArrayMutator<T> extends SerializingMutator<T>
8185
private final SerializingMutator<byte[]> innerMutator;
8286
private final Function<byte[], T> toPrimitive;
8387
private final Function<T, byte[]> toBytes;
88+
private final T[] valuePool;
8489

8590
@SuppressWarnings("unchecked")
8691
public PrimitiveArrayMutator(AnnotatedType type) {
@@ -93,6 +98,56 @@ public PrimitiveArrayMutator(AnnotatedType type) {
9398
(SerializingMutator<byte[]>) LibFuzzerMutatorFactory.tryCreate(innerByteArray).get();
9499
toPrimitive = (Function<byte[], T>) makeBytesToPrimitiveArrayConverter(elementType);
95100
toBytes = (Function<T, byte[]>) makePrimitiveArrayToBytesConverter(elementType);
101+
Optional<T[]> valuePool = extractValuePool(type);
102+
this.valuePool = valuePool.orElse(null);
103+
System.out.println(
104+
"Created ValuePool with length: " + (this.valuePool == null ? 0 : this.valuePool.length));
105+
}
106+
107+
public boolean getMutatedType(Object value) {
108+
return value.getClass().isArray()
109+
&& value.getClass().getComponentType().isPrimitive()
110+
&& value.getClass().getComponentType() == elementType.getType();
111+
}
112+
113+
public Optional<T[]> extractValuePool(AnnotatedType type) {
114+
return ValuePoolSupport.extractRawValues(type)
115+
.map(
116+
stream ->
117+
stream
118+
.flatMap(
119+
o -> {
120+
if (getMutatedType(o)) {
121+
return Stream.of(o);
122+
} else {
123+
return Stream.empty();
124+
}
125+
})
126+
.distinct()
127+
.map(o -> (T) o)
128+
// use a round-trip from the inner mutator to see if length and range
129+
// constraints are met
130+
.filter(
131+
o -> {
132+
try {
133+
byte[] valueBytes = toBytes.apply(o);
134+
byte[] roundTrip =
135+
toBytes.apply(
136+
toPrimitive.apply(
137+
innerMutator.readExclusive(
138+
new DataInputStream(
139+
new ByteArrayInputStream(valueBytes)))));
140+
System.out.println(
141+
"ValuePool candidate original bytes length: "
142+
+ valueBytes.length
143+
+ ", roundTrip bytes length: "
144+
+ roundTrip.length);
145+
return Arrays.equals(roundTrip, valueBytes);
146+
} catch (IOException e) {
147+
return false;
148+
}
149+
})
150+
.toArray(size -> (T[]) Arrays.copyOf(new Object[0], size)));
96151
}
97152

98153
@Override
@@ -128,6 +183,15 @@ public T init(PseudoRandom prng) {
128183

129184
@Override
130185
public T mutate(T value, PseudoRandom prng) {
186+
if (valuePool != null && valuePool.length > 0) {
187+
if (prng.choice()) {
188+
return prng.pickIn(valuePool);
189+
} else {
190+
// 50% chance to mutate vs picking from the pool
191+
return (T)
192+
toPrimitive.apply(innerMutator.mutate(toBytes.apply(prng.pickIn(valuePool)), prng));
193+
}
194+
}
131195
return (T) toPrimitive.apply(innerMutator.mutate(toBytes.apply(value), prng));
132196
}
133197

0 commit comments

Comments
 (0)