xref: /aosp_15_r20/external/jazzer-api/examples/src/main/java/com/example/TurboJpegFuzzer.java (revision 33edd6723662ea34453766bfdca85dbfdd5342b8)
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.example;
16 
17 import com.code_intelligence.jazzer.api.FuzzedDataProvider;
18 import org.libjpegturbo.turbojpeg.TJ;
19 import org.libjpegturbo.turbojpeg.TJDecompressor;
20 import org.libjpegturbo.turbojpeg.TJException;
21 import org.libjpegturbo.turbojpeg.TJTransform;
22 import org.libjpegturbo.turbojpeg.TJTransformer;
23 
24 public class TurboJpegFuzzer {
25   static byte[] buffer = new byte[128 * 128 * 4];
26 
fuzzerInitialize()27   public static void fuzzerInitialize() throws TJException {
28     // Trigger an early load of the native library to show the coverage counters stats in libFuzzer.
29     new TJDecompressor();
30   }
31 
fuzzerTestOneInput(FuzzedDataProvider data)32   public static void fuzzerTestOneInput(FuzzedDataProvider data) {
33     try {
34       int flagsDecompress = data.consumeInt();
35       int flagsTransform = data.consumeInt();
36       int pixelFormat = data.consumeInt(TJ.PF_RGB, TJ.PF_CMYK);
37       // Specify explicit small target width/height so that we can reuse a
38       // fixed-size buffer.
39       int desiredWidth = data.consumeInt(1, 128);
40       int desiredHeight = data.consumeInt(1, 128);
41       int transformOp = data.consumeInt(TJTransform.OP_NONE, TJTransform.OP_ROT270);
42       int transformOptions = data.consumeInt();
43       int transformWidth = data.consumeBoolean() ? 128 : 64;
44       int transformHeight = data.consumeBoolean() ? 128 : 64;
45       TJDecompressor tjd;
46       if (data.consumeBoolean()) {
47         TJTransformer tjt = new TJTransformer(data.consumeRemainingAsBytes());
48         TJTransform tjf = new TJTransform(
49             0, 0, transformWidth, transformHeight, transformOp, transformOptions, null);
50         tjd = tjt.transform(new TJTransform[] {tjf}, flagsTransform)[0];
51       } else {
52         tjd = new TJDecompressor(data.consumeRemainingAsBytes());
53       }
54       tjd.decompress(buffer, 0, 0, desiredWidth, 0, desiredHeight, pixelFormat, flagsDecompress);
55     } catch (Exception ignored) {
56       // We are not looking for Java exceptions, but segfaults and ASan reports.
57     }
58   }
59 }
60