Merge changes Iaf823919,I5b95b358,I24eae032 am: ed7c7e6f62 am: b13b01d529 am: ecaf388d27 am: e9e5f9cf7d am: 8051d09d03
Change-Id: I9d6c23ca67fb05893877fa34f45861b86a693e1c (cherry picked from commit 43f429e09f76bedb62c51631df3bd5965a0d6582) Bug: 150829891gugelfrei
parent
10b1611714
commit
110b817302
@ -0,0 +1,35 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2020 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.
|
||||
*
|
||||
*****************************************************************************
|
||||
* Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
|
||||
*/
|
||||
|
||||
cc_fuzz {
|
||||
name: "amrwb_dec_fuzzer",
|
||||
host_supported: true,
|
||||
srcs: [
|
||||
"amrwb_dec_fuzzer.cpp",
|
||||
],
|
||||
static_libs: [
|
||||
"libstagefright_amrwbdec",
|
||||
],
|
||||
target: {
|
||||
darwin: {
|
||||
enabled: false,
|
||||
},
|
||||
},
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
# Fuzzer for libstagefright_amrwbdec decoder
|
||||
|
||||
## Plugin Design Considerations
|
||||
The fuzzer plugin for AMR-WB is designed based on the understanding of the
|
||||
codec and tries to achieve the following:
|
||||
|
||||
##### Maximize code coverage
|
||||
The configuration parameters are not hardcoded, but instead selected based on
|
||||
incoming data. This ensures more code paths are reached by the fuzzer.
|
||||
|
||||
AMR-WB supports the following parameters:
|
||||
1. Quality (parameter name: `quality`)
|
||||
2. Mode (parameter name: `mode`)
|
||||
|
||||
| Parameter| Valid Values| Configured Value|
|
||||
|------------- |-------------| ----- |
|
||||
| `quality` | 0. `Bad Quality` 1. `Good quality` | Bit 0 (LSB) of 1st byte of data. |
|
||||
| `mode` | 0. `MODE_7k` 1. `MODE_9k` 2. `MODE_12k` 3. `MODE_14k` 4. `MODE_16k ` 5. `MODE_18k` 6. `MODE_20k` 7. `MODE_23k` 8. `MODE_24k` 9. `MRDTX` | Bits 3, 4, 5 and 6 of 1st byte of data. |
|
||||
|
||||
This also ensures that the plugin is always deterministic for any given input.
|
||||
|
||||
##### Maximize utilization of input data
|
||||
The plugin feeds the entire input data to the codec using a loop.
|
||||
If the decode operation was successful, the input is advanced by the frame size
|
||||
which is based on `mode` and `quality` selected.
|
||||
If the decode operation was un-successful, the input is still advanced by frame size so
|
||||
that the fuzzer can proceed to feed the next frame.
|
||||
|
||||
This ensures that the plugin tolerates any kind of input (empty, huge,
|
||||
malformed, etc) and doesnt `exit()` on any input and thereby increasing the
|
||||
chance of identifying vulnerabilities.
|
||||
|
||||
## Build
|
||||
|
||||
This describes steps to build amrwb_dec_fuzzer binary.
|
||||
|
||||
### Android
|
||||
|
||||
#### Steps to build
|
||||
Build the fuzzer
|
||||
```
|
||||
$ mm -j$(nproc) amrwb_dec_fuzzer
|
||||
```
|
||||
|
||||
#### Steps to run
|
||||
Create a directory CORPUS_DIR and copy some amrwb files to that folder
|
||||
Push this directory to device.
|
||||
|
||||
To run on device
|
||||
```
|
||||
$ adb sync data
|
||||
$ adb shell /data/fuzz/arm64/amrwb_dec_fuzzer/amrwb_dec_fuzzer CORPUS_DIR
|
||||
```
|
||||
To run on host
|
||||
```
|
||||
$ $ANDROID_HOST_OUT/fuzz/x86_64/amrwb_dec_fuzzer/amrwb_dec_fuzzer CORPUS_DIR
|
||||
```
|
||||
|
||||
## References:
|
||||
* http://llvm.org/docs/LibFuzzer.html
|
||||
* https://github.com/google/oss-fuzz
|
@ -0,0 +1,110 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2020 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.
|
||||
*
|
||||
*****************************************************************************
|
||||
* Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
|
||||
*/
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
#include <algorithm>
|
||||
#include "pvamrwbdecoder.h"
|
||||
#include "pvamrwbdecoder_api.h"
|
||||
|
||||
// Constants for AMR-WB.
|
||||
constexpr int32_t kSamplesPerFrame = 320;
|
||||
constexpr int32_t kBitsPerSample = 16;
|
||||
constexpr int32_t kMaxSourceDataUnitSize = KAMRWB_NB_BITS_MAX * sizeof(int16_t);
|
||||
constexpr int32_t kOutputBufferSize = kSamplesPerFrame * kBitsPerSample / 8;
|
||||
constexpr int32_t kFrameSizes[16] = {17, 23, 32, 36, 40, 46, 50, 58,
|
||||
60, 17, 23, 32, 36, 40, 46, 50};
|
||||
|
||||
class Codec {
|
||||
public:
|
||||
Codec() = default;
|
||||
~Codec() { deInitDecoder(); }
|
||||
bool initDecoder();
|
||||
void decodeFrames(const uint8_t *data, size_t size);
|
||||
void deInitDecoder();
|
||||
|
||||
private:
|
||||
void *mAmrHandle = nullptr;
|
||||
int16_t *mDecoderCookie = nullptr;
|
||||
void *mDecoderBuffer = nullptr;
|
||||
};
|
||||
|
||||
bool Codec::initDecoder() {
|
||||
mDecoderBuffer = malloc(pvDecoder_AmrWbMemRequirements());
|
||||
if (mDecoderBuffer) {
|
||||
pvDecoder_AmrWb_Init(&mAmrHandle, mDecoderBuffer, &mDecoderCookie);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void Codec::deInitDecoder() {
|
||||
if (mDecoderBuffer) {
|
||||
free(mDecoderBuffer);
|
||||
mDecoderBuffer = nullptr;
|
||||
}
|
||||
mAmrHandle = nullptr;
|
||||
mDecoderCookie = nullptr;
|
||||
}
|
||||
|
||||
void Codec::decodeFrames(const uint8_t *data, size_t size) {
|
||||
while (size > 0) {
|
||||
uint8_t modeByte = *data;
|
||||
bool quality = modeByte & 0x01;
|
||||
int16 mode = ((modeByte >> 3) & 0x0f);
|
||||
++data;
|
||||
--size;
|
||||
int32_t frameSize = kFrameSizes[mode];
|
||||
int16_t inputSampleBuf[kMaxSourceDataUnitSize];
|
||||
uint8_t *inputBuf = new uint8_t[frameSize];
|
||||
if (!inputBuf) {
|
||||
return;
|
||||
}
|
||||
int32_t minSize = std::min((int32_t)size, frameSize);
|
||||
memcpy(inputBuf, data, minSize);
|
||||
int16 frameMode = mode;
|
||||
int16 frameType;
|
||||
RX_State_wb rx_state;
|
||||
mime_unsorting(inputBuf, inputSampleBuf, &frameType, &frameMode, quality, &rx_state);
|
||||
|
||||
int16_t numSamplesOutput;
|
||||
int16_t outputBuf[kOutputBufferSize];
|
||||
pvDecoder_AmrWb(frameMode, inputSampleBuf, outputBuf, &numSamplesOutput, mDecoderBuffer,
|
||||
frameType, mDecoderCookie);
|
||||
data += minSize;
|
||||
size -= minSize;
|
||||
delete[] inputBuf;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
if (size < 2) {
|
||||
return 0;
|
||||
}
|
||||
Codec *codec = new Codec();
|
||||
if (!codec) {
|
||||
return 0;
|
||||
}
|
||||
if (codec->initDecoder()) {
|
||||
codec->decodeFrames(data, size);
|
||||
}
|
||||
delete codec;
|
||||
return 0;
|
||||
}
|
Loading…
Reference in new issue