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

Commit 2fb39f8c authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Added timedtext_fuzzer"

parents 552744d4 76c690fe
Loading
Loading
Loading
Loading
+55 −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.
 */

cc_library_static {
    name: "timedtext_fuzz-protos",

    srcs: ["timedtext_fuzz.proto"],
    cflags: [
        "-Wall",
        "-Werror",
    ],
    shared_libs: ["libprotobuf-cpp-full"],
    proto: {
        type: "full",
        canonical_path_from_root: false,
        local_include_dirs: ["."],
        export_proto_headers: true,
    },
}

cc_fuzz {
    name: "timedtext_fuzzer",
    srcs: [
        "timedtext_fuzzer.cpp",
    ],
    static_libs: [
        "libstagefright_timedtext",
        "timedtext_fuzz-protos",
    ],
    shared_libs: [
        "libstagefright_foundation",
        "libprotobuf-cpp-full",
        "libbinder",
        "libprotobuf-mutator",
    ],
    fuzz_config: {
        cc: [
            "android-media-fuzzing-reports@google.com",
        ],
        componentid: 155276,
    },
}
+23 −0
Original line number Diff line number Diff line
# Fuzzer for libstagefright_timedtext

libstagefright_timedtext supports the following parameters:
1. Flags (parameter name: `flags`)
2. TimeMs (parameter name: `timeMs`)

| Parameter| Valid Values| Configured Value|
|------------- |-------------| ----- |
| `flags`   | 1. `TextDescriptions::OUT_OF_BAND_TEXT_SRT` 2.  `TextDescriptions::GLOBAL_DESCRIPTIONS` 3. `TextDescriptions::IN_BAND_TEXT_3GPP` 4. `TextDescriptions::LOCAL_DESCRIPTIONS` | Value chosen from valid values by obtaining index from FuzzedDataProvider|
| `timeMs`   | `INT_MIN` to `INT_MAX` | Value obtained from FuzzedDataProvider|


#### Steps to run

1. Build the fuzzer
```
  $ mm -j$(nproc) timedtext_fuzzer
```
2. Run on device
```
  $ adb sync data
  $ adb shell /data/fuzz/arm64/timedtext_fuzzer/timedtext_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.
 */

/*
 * proto files are used for Structure Aware fuzzing so that fuzzing can be
 * made more effective.
 * timedtext_fuzz.proto is used to declare structures, which are used
 * purely inside timedtext_fuzzer.
 */

syntax = "proto3";

enum Flag {
    flag3gppglobal = 0;
    flag3gpplocal = 1;
    flagsrtlocal = 2;
}

enum ChunkType {
    default = 0;
    tx3g = 1954034535;
    styl = 1937013100;
    krok = 1802661739;
    hlit = 1751935348;
    hclr = 1751346290;
    dlay = 1684824441;
    href = 1752327526;
    tbox = 1952608120;
    blnk = 1651273323;
    txrp = 1953985136;
}

message FontRecord {
    uint32 fontId = 1;
    repeated uint32 font = 2;
}

message SRTLocal {
    repeated uint32 data = 1;
}

message GPPGlobal {
    uint64 reservedBytes = 1;
    uint32 displayFlags = 2;
    int32 horizontal_vertical_justification = 3;
    uint32 rgba = 4;
    int32 textBox = 5;
    uint32 styleRecordStart = 6;
    uint32 fontId = 7;
    uint32 fontStyle = 8;
    uint32 entryCount = 9;
    repeated FontRecord fontEntry = 10;
    uint32 defaultDisparity = 11;
}

message StyleRecord {
    uint32 startchar = 1;
    uint32 font = 2;
    uint32 rgba = 3;
}

message TextStyleBox {
    uint32 count = 1;
    repeated StyleRecord record = 2;
}

message HighlightBox {
    uint32 start = 1;
    uint32 end = 2;
}

message HighlightColor {
    uint32 rgba = 1;
}

message TextKaraokeBox {
    uint32 highlightStartTime = 1;
    uint32 entryCount = 2;
    repeated uint64 highlightData = 3;
}

message BoxRecord {
    uint32 topleft = 1;
    uint32 bottomright = 2;
}

message BlinkBox {
    uint32 charoffset = 1;
}

message HyperTextBox {
    uint32 charoffset = 1;
    uint32 urlLength = 2;
    repeated uint32 url = 3;
    uint32 altLength = 4;
    repeated uint32 altString = 5;
}

message GPPLocalText {
    string text = 1;
}

message GPPLocalFormat {
    uint64 reservedBytes = 1;
    oneof formatStyle {
        TextStyleBox textbox = 2;
        HighlightBox hltbox = 3;
        HighlightColor hltcolor = 4;
        TextKaraokeBox krokbox = 5;
        uint32 scrollDelay = 6;
        HyperTextBox hrefBox = 7;
        BoxRecord boxrecord = 8;
        BlinkBox blinkBox = 9;
        uint32 wrapFlag = 10;
    }
}

message GPPLocal {
    GPPLocalText localtext = 1;
    GPPLocalFormat format = 2;
}

message TimedText {
    Flag handle = 1;
    int32 timeMs = 2;
    SRTLocal srt = 3;
    GPPGlobal global = 4;
    GPPLocal local = 5;
}
+181 −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 <binder/Parcel.h>
#include <timedtext/TextDescriptions.h>
#include <timedtext_fuzz.pb.h>
#include "fuzzer/FuzzedDataProvider.h"
#include "src/libfuzzer/libfuzzer_macro.h"

using namespace android;
constexpr int32_t kTextBytes = 2;
constexpr int32_t kChunkBytes = 8;
constexpr int32_t kChunkTypeBytes = 4;
constexpr int32_t kGlobalTextOffset = 0;
constexpr size_t kByte3Mask = 0xff000000UL;
constexpr size_t kByte2Mask = 0x00ff0000UL;
constexpr size_t kByte1Mask = 0x0000ff00UL;
constexpr size_t kByte0Mask = 0x000000ffUL;

/**
 * Sets ChunkSize/ChunkType (uint32_t) in timedtext-description vector<uint8_t>
 * by extracting each byte from ChunkSize and populating the vector.
 */
void setChunkParameter(std::vector<uint8_t>& timedtext, size_t param, size_t paramOffset) {
    timedtext[paramOffset + 0] = (param & kByte3Mask) >> 24;
    timedtext[paramOffset + 1] = (param & kByte2Mask) >> 16;
    timedtext[paramOffset + 2] = (param & kByte1Mask) >> 8;
    timedtext[paramOffset + 3] = (param & kByte0Mask);
}

/**
 * Sets TextLength(uint16_t) in 3GPPLocal-description vector<uint8_t>
 * by extracting each byte from TextLength and populating the vector.
 */
void setTextSize(std::vector<uint8_t>& local3GPPDescription, int32_t textLength) {
    local3GPPDescription[0] = (textLength & kByte1Mask) >> 8;
    local3GPPDescription[1] = (textLength & kByte0Mask);
}

DEFINE_PROTO_FUZZER(const TimedText& input) {
    switch (input.handle()) {
        case flag3gppglobal: {
            size_t gppGlobalByteSize = input.global().ByteSizeLong();
            if (gppGlobalByteSize) {
                std::vector<uint8_t> global3GPPDescription(gppGlobalByteSize + kChunkBytes);
                setChunkParameter(global3GPPDescription, gppGlobalByteSize, kGlobalTextOffset);
                setChunkParameter(global3GPPDescription, tx3g, kGlobalTextOffset + kChunkTypeBytes);
                input.global().SerializeToArray(global3GPPDescription.data() + kChunkBytes,
                                                global3GPPDescription.size());
                Parcel* parcel = new Parcel();
                TextDescriptions::getParcelOfDescriptions(
                        global3GPPDescription.data(), global3GPPDescription.size(),
                        TextDescriptions::IN_BAND_TEXT_3GPP | TextDescriptions::GLOBAL_DESCRIPTIONS,
                        input.timems(), parcel);
                delete parcel;
            }
            break;
        }
        case flag3gpplocal: {
            size_t gppLocalByteSize = input.local().ByteSizeLong();
            if (gppLocalByteSize) {
                std::vector<uint8_t> local3GPPDescription(gppLocalByteSize + kChunkBytes +
                                                          kTextBytes);
                std::string text = input.local().localtext().text();
                int32_t textLength = text.size();
                setTextSize(local3GPPDescription, textLength);
                input.local().localtext().SerializeToArray(local3GPPDescription.data() + kTextBytes,
                                                           textLength);
                size_t gppLocalFormatSize = input.local().format().ByteSizeLong();
                size_t textOffset = textLength + kTextBytes;
                setChunkParameter(local3GPPDescription, gppLocalFormatSize, textOffset);
                switch (input.local().format().formatStyle_case()) {
                    case GPPLocalFormat::FormatStyleCase::kTextbox: {
                        setChunkParameter(local3GPPDescription, styl, textOffset + kChunkTypeBytes);
                        input.local().format().SerializeToArray(
                                local3GPPDescription.data() + textOffset + kChunkBytes,
                                gppLocalFormatSize);
                        break;
                    }
                    case GPPLocalFormat::FormatStyleCase::kHltbox: {
                        setChunkParameter(local3GPPDescription, hlit, textOffset + kChunkTypeBytes);
                        input.local().format().SerializeToArray(
                                local3GPPDescription.data() + textOffset + kChunkBytes,
                                gppLocalFormatSize);
                        break;
                    }
                    case GPPLocalFormat::FormatStyleCase::kHltcolor: {
                        setChunkParameter(local3GPPDescription, hclr, textOffset + kChunkTypeBytes);
                        input.local().format().SerializeToArray(
                                local3GPPDescription.data() + textOffset + kChunkBytes,
                                gppLocalFormatSize);
                        break;
                    }
                    case GPPLocalFormat::FormatStyleCase::kKrokbox: {
                        setChunkParameter(local3GPPDescription, krok, textOffset + kChunkTypeBytes);
                        input.local().format().SerializeToArray(
                                local3GPPDescription.data() + textOffset + kChunkBytes,
                                gppLocalFormatSize);
                        break;
                    }
                    case GPPLocalFormat::FormatStyleCase::kScrollDelay: {
                        setChunkParameter(local3GPPDescription, dlay, textOffset + kChunkTypeBytes);
                        input.local().format().SerializeToArray(
                                local3GPPDescription.data() + textOffset + kChunkBytes,
                                gppLocalFormatSize);
                        break;
                    }
                    case GPPLocalFormat::FormatStyleCase::kHrefBox: {
                        setChunkParameter(local3GPPDescription, href, textOffset + kChunkTypeBytes);
                        input.local().format().SerializeToArray(
                                local3GPPDescription.data() + textOffset + kChunkBytes,
                                gppLocalFormatSize);
                        break;
                    }
                    case GPPLocalFormat::FormatStyleCase::kBoxrecord: {
                        setChunkParameter(local3GPPDescription, tbox, textOffset + kChunkTypeBytes);
                        input.local().format().SerializeToArray(
                                local3GPPDescription.data() + textOffset + kChunkBytes,
                                gppLocalFormatSize);
                        break;
                    }
                    case GPPLocalFormat::FormatStyleCase::kBlinkBox: {
                        setChunkParameter(local3GPPDescription, blnk, textOffset + kChunkTypeBytes);
                        input.local().format().SerializeToArray(
                                local3GPPDescription.data() + textOffset + kChunkBytes,
                                gppLocalFormatSize);
                        break;
                    }
                    case GPPLocalFormat::FormatStyleCase::kWrapFlag: {
                        setChunkParameter(local3GPPDescription, txrp, textOffset + kChunkTypeBytes);
                        input.local().format().SerializeToArray(
                                local3GPPDescription.data() + textOffset + kChunkBytes,
                                gppLocalFormatSize);
                        break;
                    }
                    default: {
                        break;
                    }
                }
                Parcel* parcel = new Parcel();
                TextDescriptions::getParcelOfDescriptions(
                        local3GPPDescription.data(), local3GPPDescription.size(),
                        TextDescriptions::IN_BAND_TEXT_3GPP | TextDescriptions::LOCAL_DESCRIPTIONS,
                        input.timems(), parcel);
                delete parcel;
            }
            break;
        }
        case flagsrtlocal: {
            size_t srtByteSize = input.srt().ByteSizeLong();
            if (srtByteSize) {
                std::vector<uint8_t> srtLocalDescription(srtByteSize);
                input.srt().SerializeToArray(srtLocalDescription.data(),
                                             srtLocalDescription.size());
                Parcel* parcel = new Parcel();
                TextDescriptions::getParcelOfDescriptions(
                        srtLocalDescription.data(), srtLocalDescription.size(),
                        TextDescriptions::OUT_OF_BAND_TEXT_SRT |
                                TextDescriptions::LOCAL_DESCRIPTIONS,
                        input.timems(), parcel);
                delete parcel;
            }
            break;
        }
        default:
            break;
    }
}