Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 25956357 authored by Akshata Kadam's avatar Akshata Kadam Committed by Nisha CT
Browse files

Added ndk_sync_codec_fuzzer

Test: ./ndk_sync_codec_fuzzer
Bug: 231667886

Change-Id: I413d44bb6f89a0c9941c09ef8fc623a8acf03fb0
(cherry picked from commit b2306f1344399c41fbb2c63235b0dc761bdbe8e6)
parent 9d946be3
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -97,3 +97,13 @@ cc_fuzz {
    defaults: ["libmediandk_fuzzer_defaults"],
    shared_libs: ["libbinder_ndk",],
}

cc_fuzz {
    name: "ndk_sync_codec_fuzzer",
    srcs: [
            "ndk_sync_codec_fuzzer.cpp",
             "NdkMediaCodecFuzzerBase.cpp",
          ],
    header_libs: ["libnativewindow_headers",],
    defaults: ["libmediandk_fuzzer_defaults",],
}
+14 −0
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@
+ [ndk_mediaformat_fuzzer](#NdkMediaFormat)
+ [ndk_drm_fuzzer](#NdkDrm)
+ [ndk_mediamuxer_fuzzer](#NdkMediaMuxer)
+ [ndk_sync_codec_fuzzer](#NdkSyncCodec)

# <a name="NdkCrypto"></a> Fuzzer for NdkCrypto

@@ -142,3 +143,16 @@ NdkMediaMuxer supports the following parameters:
  $ adb sync data
  $ adb shell /data/fuzz/arm64/ndk_mediamuxer_fuzzer/ndk_mediamuxer_fuzzer
```

# <a name="NdkSyncCodec"></a>Fuzzer for NdkSyncCodec

#### Steps to run
1. Build the fuzzer
```
  $ mm -j$(nproc) ndk_sync_codec_fuzzer
```
2. Run on device
```
  $ adb sync data
  $ adb shell /data/fuzz/arm64/ndk_sync_codec_fuzzer/ndk_sync_codec_fuzzer
```
+142 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 The Android Open Source Project
 *
 * 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.
 */
#include <NdkMediaCodecFuzzerBase.h>

constexpr int32_t kMaxNdkCodecAPIs = 12;

class NdkSyncCodecFuzzer : public NdkMediaCodecFuzzerBase {
  public:
    NdkSyncCodecFuzzer(const uint8_t* data, size_t size)
        : NdkMediaCodecFuzzerBase(), mFdp(data, size) {
        setFdp(&mFdp);
    };
    void invokeSyncCodeConfigAPI();

    static void CodecOnFrameRendered(AMediaCodec* codec, void* userdata, int64_t mediaTimeUs,
                                     int64_t systemNano) {
        (void)codec;
        (void)userdata;
        (void)mediaTimeUs;
        (void)systemNano;
    };

  private:
    FuzzedDataProvider mFdp;
    AMediaCodec* mCodec = nullptr;
    void invokekSyncCodecAPIs(bool isEncoder);
};

void NdkSyncCodecFuzzer::invokekSyncCodecAPIs(bool isEncoder) {
    ANativeWindow* nativeWindow = nullptr;
    AMediaFormat* format = getCodecFormat();
    int32_t numOfFrames = mFdp.ConsumeIntegralInRange<size_t>(kMinIterations, kMaxIterations);
    int32_t count = 0;
    while (++count <= numOfFrames) {
        int32_t ndkcodecAPI = mFdp.ConsumeIntegralInRange<size_t>(kMinAPICase, kMaxNdkCodecAPIs);
        switch (ndkcodecAPI) {
            case 0: {  // configure the codec
                AMediaCodec_configure(mCodec, format, nativeWindow, nullptr /* crypto */,
                                      (isEncoder ? AMEDIACODEC_CONFIGURE_FLAG_ENCODE : 0));
                break;
            }
            case 1: {  // start codec
                AMediaCodec_start(mCodec);
                break;
            }
            case 2: {  // stop codec
                AMediaCodec_stop(mCodec);
                break;
            }
            case 3: {  // create persistent input surface
                AMediaCodec_createPersistentInputSurface(&nativeWindow);
                break;
            }
            case 4: {  // buffer operation APIs
                invokeInputBufferOperationAPI(mCodec);
                break;
            }
            case 5: {
                invokeOutputBufferOperationAPI(mCodec);
                break;
            }
            case 6: {  // get input and output Format
                invokeCodecFormatAPI(mCodec);
                break;
            }
            case 7: {
                AMediaCodec_signalEndOfInputStream(mCodec);
                break;
            }
            case 8: {  // set parameters
                // Create a new parameter and set
                AMediaFormat* params = AMediaFormat_new();
                AMediaFormat_setInt32(
                        params, "video-bitrate",
                        mFdp.ConsumeIntegralInRange<size_t>(kMinIntKeyValue, kMaxIntKeyValue));
                AMediaCodec_setParameters(mCodec, params);
                AMediaFormat_delete(params);
                break;
            }
            case 9: {  // flush codec
                AMediaCodec_flush(mCodec);
                if (mFdp.ConsumeBool()) {
                    AMediaCodec_start(mCodec);
                }
                break;
            }
            case 10: {  // get the codec name
                char* name = nullptr;
                AMediaCodec_getName(mCodec, &name);
                AMediaCodec_releaseName(mCodec, name);
                break;
            }
            case 11: {  // set callback API for frame render output
                std::vector<uint8_t> userData = mFdp.ConsumeBytes<uint8_t>(
                        mFdp.ConsumeIntegralInRange<size_t>(kMinBytes, kMaxBytes));
                AMediaCodecOnFrameRendered callback = CodecOnFrameRendered;
                AMediaCodec_setOnFrameRenderedCallback(mCodec, callback, userData.data());
                break;
            }
            case 12:
            default: {  // set persistent input surface
                AMediaCodec_setInputSurface(mCodec, nativeWindow);
            }
        }
    }
    if (nativeWindow) {
        ANativeWindow_release(nativeWindow);
    }
    if (format) {
        AMediaFormat_delete(format);
    }
}

void NdkSyncCodecFuzzer::invokeSyncCodeConfigAPI() {
    while (mFdp.remaining_bytes() > 0) {
        bool isEncoder = mFdp.ConsumeBool();
        mCodec = createCodec(isEncoder, mFdp.ConsumeBool() /* isCodecForClient */);
        if (mCodec) {
            invokekSyncCodecAPIs(isEncoder);
            AMediaCodec_delete(mCodec);
        }
    }
}

extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
    NdkSyncCodecFuzzer ndkSyncCodecFuzzer(data, size);
    ndkSyncCodecFuzzer.invokeSyncCodeConfigAPI();
    return 0;
}