1*a58d3d2aSXin Li# Fuzzer for libopus decoder 2*a58d3d2aSXin Li 3*a58d3d2aSXin Li## Plugin Design Considerations 4*a58d3d2aSXin LiThe fuzzer plugin for opus decoder is designed based on the understanding of the 5*a58d3d2aSXin Licodec and tries to achieve the following: 6*a58d3d2aSXin Li 7*a58d3d2aSXin Li##### Maximize code coverage 8*a58d3d2aSXin Li 9*a58d3d2aSXin LiThis fuzzer provides support for both single stream and multi stream inputs, 10*a58d3d2aSXin Lithus enabling fuzzing for API's provided for single stream as well as multi 11*a58d3d2aSXin Listream. 12*a58d3d2aSXin Li 13*a58d3d2aSXin LiFollowing arguments are passed to OPUS_DEC_CREATE_API: 14*a58d3d2aSXin Li 15*a58d3d2aSXin Li1. Sampling frequency (parameter name: `Fs`) 16*a58d3d2aSXin Li2. Number of channels (parameter name: `channels`) 17*a58d3d2aSXin Li 18*a58d3d2aSXin Li| Parameter| Valid Values| Configured Value| 19*a58d3d2aSXin Li|------------- |-------------| ----- | 20*a58d3d2aSXin Li| `Fs` | `8000 ` `12000 ` `16000 ` `24000 ` `48000 ` | Derived from Byte-9 of input stream| 21*a58d3d2aSXin Li| `channels` | `1 ` `2 ` | Derived from Byte-9 of input stream | 22*a58d3d2aSXin Li 23*a58d3d2aSXin Li##### Maximize utilization of input data 24*a58d3d2aSXin LiThe plugin feeds the entire input data to the codec. Frame sizes are determined only 25*a58d3d2aSXin Liafter the call to extractor, so in absence of call to extractor, 26*a58d3d2aSXin Liwe feed the entire data to the decoder. 27*a58d3d2aSXin LiThis ensures that the plugin tolerates any kind of input (empty, huge, 28*a58d3d2aSXin Limalformed, etc) and doesnt `exit()` on any input and thereby increasing the 29*a58d3d2aSXin Lichance of identifying vulnerabilities. 30*a58d3d2aSXin Li 31*a58d3d2aSXin Li## Build 32*a58d3d2aSXin Li 33*a58d3d2aSXin LiThis describes steps to build opus_dec_fuzzer and opus_multistream_dec_fuzzer binary. 34*a58d3d2aSXin Li 35*a58d3d2aSXin Li## Android 36*a58d3d2aSXin Li 37*a58d3d2aSXin Li### Steps to build 38*a58d3d2aSXin LiBuild the fuzzer 39*a58d3d2aSXin Li``` 40*a58d3d2aSXin Li $ mm -j$(nproc) opus_dec_fuzzer 41*a58d3d2aSXin Li $ mm -j$(nproc) opus_multistream_dec_fuzzer 42*a58d3d2aSXin Li``` 43*a58d3d2aSXin Li 44*a58d3d2aSXin Li### Steps to run 45*a58d3d2aSXin LiCreate a directory CORPUS_DIR and copy some opus files to that folder. 46*a58d3d2aSXin LiPush this directory to device. 47*a58d3d2aSXin Li 48*a58d3d2aSXin LiTo run on device 49*a58d3d2aSXin Li``` 50*a58d3d2aSXin Li $ adb sync data 51*a58d3d2aSXin Li $ adb shell /data/fuzz/arm64/opus_dec_fuzzer/opus_dec_fuzzer CORPUS_DIR 52*a58d3d2aSXin Li $ adb shell /data/fuzz/arm64/opus_multistream_dec_fuzzer/opus_multistream_dec_fuzzer CORPUS_DIR 53*a58d3d2aSXin Li``` 54*a58d3d2aSXin LiTo run on host 55*a58d3d2aSXin Li``` 56*a58d3d2aSXin Li $ $ANDROID_HOST_OUT/fuzz/x86_64/opus_dec_fuzzer/opus_dec_fuzzer CORPUS_DIR 57*a58d3d2aSXin Li $ $ANDROID_HOST_OUT/fuzz/x86_64/opus_multistream_dec_fuzzer/opus_multistream_dec_fuzzer CORPUS_DIR 58*a58d3d2aSXin Li``` 59*a58d3d2aSXin Li 60*a58d3d2aSXin Li# Fuzzer for libopus encoder 61*a58d3d2aSXin Li 62*a58d3d2aSXin Li## Plugin Design Considerations 63*a58d3d2aSXin LiThe fuzzer plugin for opus encoder is designed based on the understanding of the 64*a58d3d2aSXin Licodec and tries to achieve the following: 65*a58d3d2aSXin Li 66*a58d3d2aSXin Li##### Maximize code coverage 67*a58d3d2aSXin Li 68*a58d3d2aSXin LiThis fuzzer provides support for both single stream and multi stream inputs, 69*a58d3d2aSXin Lithus enabling fuzzing for API's provided for single stream as well as multi 70*a58d3d2aSXin Listream. 71*a58d3d2aSXin LiFollowing arguments are passed to OPUS_ENC_CREATE_API: 72*a58d3d2aSXin Li 73*a58d3d2aSXin Li1. Sampling rate (parameter name: `sampleRate`) 74*a58d3d2aSXin Li2. Number of channels (parameter name: `channels`) 75*a58d3d2aSXin Li 76*a58d3d2aSXin Li| Parameter| Valid Values| Configured Value| 77*a58d3d2aSXin Li|------------- |-------------| ----- | 78*a58d3d2aSXin Li| `sampleRate` | `8000 ` `12000 ` `16000 ` `24000 ` `48000 ` | An index ranging from 0-4 is calculated using first byte of data which is used to assign value to `sampleRate` from array `kSampleRates`| 79*a58d3d2aSXin Li| `channels` (single stream) | `1 ` `2 ` | Calculated using second byte of data | 80*a58d3d2aSXin Li| `channels` (multi stream) | In range `1 `- `255 ` | Calculated using second byte of data | 81*a58d3d2aSXin Li 82*a58d3d2aSXin LiFollowing arguments are passed to OPUS_ENC_CTL_API: 83*a58d3d2aSXin Li 84*a58d3d2aSXin Li1. OPUS_SET_BITRATE (parameter name: `bitRate`) 85*a58d3d2aSXin Li2. OPUS_SET_COMPLEXITY (parameter name: `complexity`) 86*a58d3d2aSXin Li3. OPUS_SET_APPLICATION (parameter name: `application`) 87*a58d3d2aSXin Li4. OPUS_SET_DTX (parameter name: `setDTX`) 88*a58d3d2aSXin Li5. OPUS_SET_SIGNAL (parameter name: `signal`) 89*a58d3d2aSXin Li6. OPUS_SET_VBR (parameter name: `setVBR`) 90*a58d3d2aSXin Li7. OPUS_SET_VBR_CONSTRAINT (parameter name: `setVBRConstraint`) 91*a58d3d2aSXin Li8. OPUS_SET_FORCE_CHANNELS (parameter name: `forceChannel`) 92*a58d3d2aSXin Li9. OPUS_SET_MAX_BANDWIDTH (parameter name: `maxBandwidth`) 93*a58d3d2aSXin Li10. OPUS_SET_INBAND_FEC (parameter name: `setInbandFec`) 94*a58d3d2aSXin Li11. OPUS_SET_PACKET_LOSS_PERC (parameter name: `pktLoss`) 95*a58d3d2aSXin Li12. OPUS_SET_LSB_DEPTH (parameter name: `lsbDepth`) 96*a58d3d2aSXin Li13. OPUS_SET_PREDICTION_DISABLED (parameter name: `setPredDisable`) 97*a58d3d2aSXin Li14. OPUS_SET_EXPERT_FRAME_DURATION (parameter name: `frameSizeEnum`) 98*a58d3d2aSXin Li 99*a58d3d2aSXin Li| Parameter| Valid Values| Configured Value| 100*a58d3d2aSXin Li|------------- |-------------| ----- | 101*a58d3d2aSXin Li| `bitRate` | In range `500 ` to `512000 ` | Calculated using all bits of 3rd, 4th and 5th byte of data | 102*a58d3d2aSXin Li| `complexity` |0.`0 ` 1.`1 ` 2.`2 ` 3.`3 ` 4.`4 ` 5.`5 ` 6.`6 ` 7.`7 ` 8.`8 ` 9.`9 ` 10.`10 ` | Calculated using all bits of 6th byte of data | 103*a58d3d2aSXin Li| `application` | 0.`OPUS_APPLICATION_VOIP ` 1.`OPUS_APPLICATION_AUDIO ` 2.`OPUS_APPLICATION_RESTRICTED_LOWDELAY ` | Calculated using all bits of 7th byte of data | 104*a58d3d2aSXin Li| `setDTX` | 0.`0 ` 1.`1 ` | Calculated using bit 0 of 8th byte of data | 105*a58d3d2aSXin Li| `signal` | 0.`OPUS_AUTO ` 1.`OPUS_SIGNAL_VOICE ` 2.`OPUS_SIGNAL_MUSIC ` | Calculated using bit 0 and bit 1 of 9th byte of data | 106*a58d3d2aSXin Li| `setVBR` | 0.`0 ` 1.`1 ` | Calculated using bit 0 of 10th byte of data | 107*a58d3d2aSXin Li| `setVBRConstraint` | 0.`0 ` 1.`1 ` | Calculated using bit 0 of 11th byte of data | 108*a58d3d2aSXin Li| `forceChannel` | 0.`OPUS_AUTO ` 1.`1 ` 2.`2 ` | Calculated using all bits of 12th byte of data | 109*a58d3d2aSXin Li| `maxBandwidth` | 0.`OPUS_BANDWIDTH_NARROWBAND ` 1.`OPUS_BANDWIDTH_MEDIUMBAND ` 2.`OPUS_BANDWIDTH_WIDEBAND ` 3.`OPUS_BANDWIDTH_SUPERWIDEBAND ` 4.`OPUS_BANDWIDTH_FULLBAND ` | Calculated using all bits of 13th byte of data | 110*a58d3d2aSXin Li| `setInbandFec` | 0.`0 ` 1.`1 ` | Calculated using bit 0 of 14th byte of data | 111*a58d3d2aSXin Li| `pktLoss` | 0.`0 ` 1.`1 ` 2.`2 ` 3.`5 `| Calculated using all bits of 15th byte of data | 112*a58d3d2aSXin Li| `lsbDepth` | 0.`8 ` 1.`24 ` | Calculated using bit 0 of 16th byte of data | 113*a58d3d2aSXin Li| `setPredDisable` | 0.`0 ` 1.`1 ` | Calculated using bit 0 of 17th byte of data | 114*a58d3d2aSXin Li| `frameSizeEnum` | 0.`OPUS_FRAMESIZE_2_5_MS ` 1.`OPUS_FRAMESIZE_5_MS ` 2.`OPUS_FRAMESIZE_10_MS ` 3.`OPUS_FRAMESIZE_20_MS ` 4.`OPUS_FRAMESIZE_40_MS ` 5.`OPUS_FRAMESIZE_60_MS ` 6.`OPUS_FRAMESIZE_80_MS ` 7.`OPUS_FRAMESIZE_100_MS ` 8.`OPUS_FRAMESIZE_120_MS ` | Calculated using all bits of 18th byte of data | 115*a58d3d2aSXin Li 116*a58d3d2aSXin Li 117*a58d3d2aSXin Li##### Maximize utilization of input data 118*a58d3d2aSXin LiThe plugin feeds the entire input data to the codec. For buffer size which is not a multiple of mNumPcmBytesPerInputFrame, we will accumulate the input and keep it. Once the input is filled with expected number of bytes, we will send it to encoder. This ensures that the plugin tolerates any kind of input (empty, huge, 119*a58d3d2aSXin Limalformed, etc) and doesnt `exit()` on any input and thereby increasing the chance of identifying vulnerabilities. 120*a58d3d2aSXin Li 121*a58d3d2aSXin Li## Build 122*a58d3d2aSXin Li 123*a58d3d2aSXin LiThis describes steps to build opus_enc_fuzzer and opus_multistream_enc_fuzzer. 124*a58d3d2aSXin Li 125*a58d3d2aSXin Li## Android 126*a58d3d2aSXin Li 127*a58d3d2aSXin Li### Steps to build 128*a58d3d2aSXin LiBuild the fuzzer 129*a58d3d2aSXin Li``` 130*a58d3d2aSXin Li $ mm -j$(nproc) opus_enc_fuzzer 131*a58d3d2aSXin Li $ mm -j$(nproc) opus_multistream_enc_fuzzer 132*a58d3d2aSXin Li``` 133*a58d3d2aSXin Li 134*a58d3d2aSXin Li### Steps to run 135*a58d3d2aSXin LiCreate a directory CORPUS_DIR and copy some raw media files to that folder. 136*a58d3d2aSXin LiPush this directory to device. 137*a58d3d2aSXin Li 138*a58d3d2aSXin LiTo run on device 139*a58d3d2aSXin Li``` 140*a58d3d2aSXin Li $ adb sync data 141*a58d3d2aSXin Li $ adb shell /data/fuzz/arm64/opus_enc_fuzzer/opus_enc_fuzzer CORPUS_DIR 142*a58d3d2aSXin Li $ adb shell /data/fuzz/arm64/opus_multistream_enc_fuzzer/opus_multistream_enc_fuzzer CORPUS_DIR 143*a58d3d2aSXin Li``` 144*a58d3d2aSXin LiTo run on host 145*a58d3d2aSXin Li``` 146*a58d3d2aSXin Li $ $ANDROID_HOST_OUT/fuzz/x86_64/opus_enc_fuzzer/opus_enc_fuzzer CORPUS_DIR 147*a58d3d2aSXin Li $ $ANDROID_HOST_OUT/fuzz/x86_64/opus_multistream_enc_fuzzer/opus_multistream_enc_fuzzer CORPUS_DIR 148*a58d3d2aSXin Li``` 149*a58d3d2aSXin Li 150*a58d3d2aSXin Li## References: 151*a58d3d2aSXin Li * http://llvm.org/docs/LibFuzzer.html 152*a58d3d2aSXin Li * https://github.com/google/oss-fuzz 153