Skip to content

Commit 6da8018

Browse files
committed
fix: assertion failure when fuzzing proto strings
When parsing protobuf messages from libfuzzer bytes in the protobuf mutator we don't enforce length limits. This could lead to maxSizeIncrease < 0 situations if the e.g. a String read by the protobuf mutator exceeds the size limit. To guard against similar cases we now enforce the size constraints for the byte array that is being mutated before performing the mutation.
1 parent da56919 commit 6da8018

File tree

4 files changed

+24
-12
lines changed

4 files changed

+24
-12
lines changed

selffuzz/src/test/java/com/code_intelligence/selffuzz/mutation/ArgumentsMutatorFuzzTest.java

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -206,15 +206,13 @@ void fuzz_Enums(MyEnum e0, MyEnum e1, MyEnum e2) {}
206206

207207
@SelfFuzzTest
208208
void fuzz_ProtoBufs(
209-
// com.google.protobuf.StringValue v0, // BUG: makes maxIncreaseSize negative in
210-
// LibProtobufMutator.mutate
209+
com.google.protobuf.StringValue v0,
211210
com.google.protobuf.Int32Value v1,
212211
com.google.protobuf.BoolValue v2,
213212
com.google.protobuf.UInt64Value v3,
214213
com.google.protobuf.FloatValue v4,
215214
com.google.protobuf.DoubleValue v5,
216-
// com.google.protobuf.BytesValue v6, // BUG: makes maxIncreaseSize negative in
217-
// LibProtobufMutator.mutate
215+
com.google.protobuf.BytesValue v6,
218216
com.google.protobuf.Int64Value v7) {
219217
if (v7 != null) {
220218
assertThat(v7.getValue()).isAtLeast(Long.MIN_VALUE);
@@ -224,25 +222,22 @@ void fuzz_ProtoBufs(
224222

225223
@SelfFuzzTest
226224
void fuzz_ProtoBufsNotNull(
227-
// @NotNull com.google.protobuf.StringValue v0, // BUG: makes maxIncreaseSize negative in
228-
// LibProtobufMutator.mutate
225+
@NotNull com.google.protobuf.StringValue v0,
229226
@NotNull com.google.protobuf.Int32Value v1,
230227
@NotNull com.google.protobuf.BoolValue v2,
231228
@NotNull com.google.protobuf.UInt64Value v3,
232229
@NotNull com.google.protobuf.FloatValue v4,
233230
@NotNull com.google.protobuf.DoubleValue v5,
234-
// @NotNull com.google.protobuf.BytesValue v6, // BUG: makes maxIncreaseSize negative in
235-
// LibProtobufMutator.mutate
231+
@NotNull com.google.protobuf.BytesValue v6,
236232
@NotNull com.google.protobuf.Int64Value v7) {
237233
if (v7 != null) {
238234
assertThat(v7.getValue()).isAtLeast(Long.MIN_VALUE);
239235
assertThat(v7.getValue()).isAtMost(Long.MAX_VALUE);
240236
}
241237
}
242238

243-
// BUG: makes maxIncreaseSize negative in LibProtobufMutator.mutate
244-
// @SelfFuzzTest
245-
// public static void fuzz_TestProtobuf(TestProtobuf o1) {}
239+
@SelfFuzzTest
240+
public static void fuzz_TestProtobuf(Proto2.TestProtobuf o1) {}
246241

247242
@SelfFuzzTest
248243
void fuzz_MapField3(Proto3.MapField3 o1) {}

selffuzz/src/test/java/com/code_intelligence/selffuzz/mutation/BUILD.bazel

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ java_fuzz_target_test(
1010
],
1111
data = ["//selffuzz/src/test/resources:ArgumentsMutatorFuzzTest-corpus"],
1212
env = {
13-
"_JAVA_OPTIONS": "-Xmx1024m",
13+
"_JAVA_OPTIONS": "-Xmx2048m",
1414
},
1515
fuzzer_args = [
1616
# Make sure that the fuzzer can run. Longer fuzzing runs will be done in a separate GH action.

src/main/java/com/code_intelligence/jazzer/mutation/mutator/libfuzzer/LibFuzzerMutatorFactory.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,9 @@ private int maxInitialSize() {
113113

114114
@Override
115115
public byte[] mutate(byte[] value, PseudoRandom prng) {
116+
// Enforce length constraints on the input to mutate. We do this because some mutators (e.g.
117+
// protobuf mutator) don't enforce length constraints in the read methods.
118+
value = enforceLength(value);
116119
int maxLengthIncrease = maxLength - value.length;
117120
byte[] mutated = LibFuzzerMutate.mutateDefault(value, maxLengthIncrease);
118121
return enforceLength(mutated);

src/test/java/com/code_intelligence/jazzer/mutation/mutator/lang/StringMutatorTest.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,20 @@ void testReadInputsLongerThanMaxLength() throws IOException {
226226
assertThat(s).isEqualTo("fooba");
227227
}
228228

229+
@Test
230+
void testMutateWithInputLongerThanMaxLength() {
231+
SerializingMutator<String> mutator =
232+
(SerializingMutator<String>)
233+
factory.createOrThrow(
234+
new TypeHolder<@NotNull @WithUtf8Length(max = 5) String>() {}.annotatedType());
235+
assertThat(mutator.toString()).isEqualTo("String");
236+
String s = "foobarbazf";
237+
try (MockPseudoRandom prng = mockPseudoRandom()) {
238+
s = mutator.mutate(s, prng);
239+
}
240+
assertThat(s.length()).isAtMost(5);
241+
}
242+
229243
@Test
230244
void testMaxLengthMutate() {
231245
SerializingMutator<String> mutator =

0 commit comments

Comments
 (0)