1 // Copyright 2021 Code Intelligence GmbH 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package com.code_intelligence.jazzer.driver; 16 17 import com.code_intelligence.jazzer.api.FuzzedDataProvider; 18 import java.io.ByteArrayOutputStream; 19 import java.io.IOException; 20 import java.io.ObjectOutputStream; 21 import java.util.ArrayList; 22 import java.util.Base64; 23 24 // Wraps the native FuzzedDataProviderImpl and serializes all its return values 25 // into a Base64-encoded string. 26 public final class RecordingFuzzedDataProvider implements FuzzedDataProvider { 27 private final FuzzedDataProvider target; 28 private final ArrayList<Object> recordedReplies = new ArrayList<>(); 29 RecordingFuzzedDataProvider(FuzzedDataProvider target)30 private RecordingFuzzedDataProvider(FuzzedDataProvider target) { 31 this.target = target; 32 } 33 makeFuzzedDataProviderProxy(FuzzedDataProvider target)34 public static FuzzedDataProvider makeFuzzedDataProviderProxy(FuzzedDataProvider target) { 35 return new RecordingFuzzedDataProvider(target); 36 } 37 serializeFuzzedDataProviderProxy(FuzzedDataProvider proxy)38 public static String serializeFuzzedDataProviderProxy(FuzzedDataProvider proxy) 39 throws IOException { 40 return ((RecordingFuzzedDataProvider) proxy).serialize(); 41 } 42 recordAndReturn(T object)43 private <T> T recordAndReturn(T object) { 44 recordedReplies.add(object); 45 return object; 46 } 47 serialize()48 private String serialize() throws IOException { 49 byte[] rawOut; 50 try (ByteArrayOutputStream byteStream = new ByteArrayOutputStream()) { 51 try (ObjectOutputStream objectStream = new ObjectOutputStream(byteStream)) { 52 objectStream.writeObject(recordedReplies); 53 } 54 rawOut = byteStream.toByteArray(); 55 } 56 return Base64.getEncoder().encodeToString(rawOut); 57 } 58 59 @Override consumeBoolean()60 public boolean consumeBoolean() { 61 return recordAndReturn(target.consumeBoolean()); 62 } 63 64 @Override consumeBooleans(int maxLength)65 public boolean[] consumeBooleans(int maxLength) { 66 return recordAndReturn(target.consumeBooleans(maxLength)); 67 } 68 69 @Override consumeByte()70 public byte consumeByte() { 71 return recordAndReturn(target.consumeByte()); 72 } 73 74 @Override consumeByte(byte min, byte max)75 public byte consumeByte(byte min, byte max) { 76 return recordAndReturn(target.consumeByte(min, max)); 77 } 78 79 @Override consumeBytes(int maxLength)80 public byte[] consumeBytes(int maxLength) { 81 return recordAndReturn(target.consumeBytes(maxLength)); 82 } 83 84 @Override consumeRemainingAsBytes()85 public byte[] consumeRemainingAsBytes() { 86 return recordAndReturn(target.consumeRemainingAsBytes()); 87 } 88 89 @Override consumeShort()90 public short consumeShort() { 91 return recordAndReturn(target.consumeShort()); 92 } 93 94 @Override consumeShort(short min, short max)95 public short consumeShort(short min, short max) { 96 return recordAndReturn(target.consumeShort(min, max)); 97 } 98 99 @Override consumeShorts(int maxLength)100 public short[] consumeShorts(int maxLength) { 101 return recordAndReturn(target.consumeShorts(maxLength)); 102 } 103 104 @Override consumeInt()105 public int consumeInt() { 106 return recordAndReturn(target.consumeInt()); 107 } 108 109 @Override consumeInt(int min, int max)110 public int consumeInt(int min, int max) { 111 return recordAndReturn(target.consumeInt(min, max)); 112 } 113 114 @Override consumeInts(int maxLength)115 public int[] consumeInts(int maxLength) { 116 return recordAndReturn(target.consumeInts(maxLength)); 117 } 118 119 @Override consumeLong()120 public long consumeLong() { 121 return recordAndReturn(target.consumeLong()); 122 } 123 124 @Override consumeLong(long min, long max)125 public long consumeLong(long min, long max) { 126 return recordAndReturn(target.consumeLong(min, max)); 127 } 128 129 @Override consumeLongs(int maxLength)130 public long[] consumeLongs(int maxLength) { 131 return recordAndReturn(target.consumeLongs(maxLength)); 132 } 133 134 @Override consumeFloat()135 public float consumeFloat() { 136 return recordAndReturn(target.consumeFloat()); 137 } 138 139 @Override consumeRegularFloat()140 public float consumeRegularFloat() { 141 return recordAndReturn(target.consumeRegularFloat()); 142 } 143 144 @Override consumeRegularFloat(float min, float max)145 public float consumeRegularFloat(float min, float max) { 146 return recordAndReturn(target.consumeRegularFloat(min, max)); 147 } 148 149 @Override consumeProbabilityFloat()150 public float consumeProbabilityFloat() { 151 return recordAndReturn(target.consumeProbabilityFloat()); 152 } 153 154 @Override consumeDouble()155 public double consumeDouble() { 156 return recordAndReturn(target.consumeDouble()); 157 } 158 159 @Override consumeRegularDouble()160 public double consumeRegularDouble() { 161 return recordAndReturn(target.consumeRegularDouble()); 162 } 163 164 @Override consumeRegularDouble(double min, double max)165 public double consumeRegularDouble(double min, double max) { 166 return recordAndReturn(target.consumeRegularDouble(min, max)); 167 } 168 169 @Override consumeProbabilityDouble()170 public double consumeProbabilityDouble() { 171 return recordAndReturn(target.consumeProbabilityDouble()); 172 } 173 174 @Override consumeChar()175 public char consumeChar() { 176 return recordAndReturn(target.consumeChar()); 177 } 178 179 @Override consumeChar(char min, char max)180 public char consumeChar(char min, char max) { 181 return recordAndReturn(target.consumeChar(min, max)); 182 } 183 184 @Override consumeCharNoSurrogates()185 public char consumeCharNoSurrogates() { 186 return recordAndReturn(target.consumeCharNoSurrogates()); 187 } 188 189 @Override consumeString(int maxLength)190 public String consumeString(int maxLength) { 191 return recordAndReturn(target.consumeString(maxLength)); 192 } 193 194 @Override consumeRemainingAsString()195 public String consumeRemainingAsString() { 196 return recordAndReturn(target.consumeRemainingAsString()); 197 } 198 199 @Override consumeAsciiString(int maxLength)200 public String consumeAsciiString(int maxLength) { 201 return recordAndReturn(target.consumeAsciiString(maxLength)); 202 } 203 204 @Override consumeRemainingAsAsciiString()205 public String consumeRemainingAsAsciiString() { 206 return recordAndReturn(target.consumeRemainingAsAsciiString()); 207 } 208 209 @Override remainingBytes()210 public int remainingBytes() { 211 return recordAndReturn(target.remainingBytes()); 212 } 213 } 214