1# Fuzzer for libavc decoder and encoder 2 3This describes steps to build avc_dec_fuzzer and avc_enc_fuzzer. 4 5## Linux x86/x64 6 7### Requirements 8- cmake (3.9.1 or above) 9- make 10- clang (6.0 or above) 11 needs to support -fsanitize=fuzzer, -fsanitize=fuzzer-no-link 12 13### Steps to build 14Clone libavc repository 15``` 16$ git clone https://android.googlesource.com/platform/external/libavc 17``` 18Create a directory inside libavc and change directory 19``` 20 $ cd libavc 21 $ mkdir build 22 $ cd build 23``` 24Build fuzzer with required sanitizers (-DSANITIZE=fuzzer-no-link is mandatory 25 to enable fuzzers) 26``` 27 $ cmake .. -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ \ 28 -DCMAKE_BUILD_TYPE=Debug -DSANITIZE=fuzzer-no-link,address,\ 29 signed-integer-overflow,unsigned-integer-overflow 30 $ make 31 ``` 32 33### Steps to run 34Create a directory CORPUS_DIR and copy some elementary h264 files 35(for avc_dec_fuzzer) or yuv files (for avc_enc_fuzzer) to that directory 36 37To run the fuzzers 38``` 39$ ./avc_dec_fuzzer CORPUS_DIR 40$ ./mvc_dec_fuzzer CORPUS_DIR 41$ ./avc_enc_fuzzer CORPUS_DIR 42``` 43 44## Android 45 46### Steps to build 47Build the fuzzers 48``` 49 $ mm -j$(nproc) avc_dec_fuzzer 50 $ mm -j$(nproc) mvc_dec_fuzzer 51 $ mm -j$(nproc) avc_enc_fuzzer 52``` 53 54### Steps to run 55Create a directory CORPUS_DIR and copy some elementary h264 files 56(for avc_dec_fuzzer) or yuv files (for avc_enc_fuzzer) to that folder 57Push this directory to device 58 59To run avc_dec_fuzzer on device 60``` 61 $ adb sync data 62 $ adb shell /data/fuzz/arm64/avc_dec_fuzzer/avc_dec_fuzzer CORPUS_DIR 63``` 64To run mvc_dec_fuzzer on device 65``` 66 $ adb sync data 67 $ adb shell /data/fuzz/arm64/mvc_dec_fuzzer/mvc_dec_fuzzer CORPUS_DIR 68``` 69To run avc_enc_fuzzer on device 70``` 71 $ adb sync data 72 $ adb shell /data/fuzz/arm64/avc_enc_fuzzer/avc_enc_fuzzer CORPUS_DIR 73``` 74 75To run avc_dec_fuzzer on host 76``` 77 $ $ANDROID_HOST_OUT/fuzz/x86_64/avc_dec_fuzzer/avc_dec_fuzzer CORPUS_DIR 78``` 79 80To run mvc_dec_fuzzer on host 81``` 82 $ $ANDROID_HOST_OUT/fuzz/x86_64/mvc_dec_fuzzer/mvc_dec_fuzzer CORPUS_DIR 83``` 84 85To run avc_enc_fuzzer on host 86``` 87 $ $ANDROID_HOST_OUT/fuzz/x86_64/avc_enc_fuzzer/avc_enc_fuzzer CORPUS_DIR 88``` 89 90 91# Appendix 92## libavc encoder fuzzer 93 94## Plugin Design Considerations 95The fuzzer plugin for AVC is designed based on the understanding of the 96codec and tries to achieve the following: 97 98##### Maximize code coverage 99The configuration parameters are not hardcoded, but instead selected based on 100incoming data. This ensures more code paths are reached by the fuzzer. 101 102AVC supports the following parameters: 1031. Frame Width (parameter name: `u4_wd`) 1042. Frame Height (parameter name: `u4_ht`) 1053. Input color format (parameter name: `e_inp_color_fmt`) 1064. Architecture type (parameter name: `e_arch`) 1075. Rate control mode (parameter name: `e_rc_mode`) 1086. Number of cores (parameter name: `u4_num_cores`) 1097. Maximum B frames (parameter name: `u4_num_bframes`) 1108. Encoder speed preset (parameter name: `u4_enc_speed_preset`) 1119. enable constrained intra prediction (parameter name: `u4_constrained_intra_pred`) 11210. enable intra 4x4 (parameter name: `u4_enable_intra_4x4`) 11311. Qp for I frames (parameter name: `u4_i_qp`) 11412. Qp for P frames (parameter name: `u4_p_qp`) 11513. Qp for B frames (parameter name: `u4_b_qp`) 11614. Target Bitrate (parameter name: `u4_target_bitrate`) 11715. Intra refresh period in frames (parameter name: `u4_air_refresh_period`) 11816. Enable half pel ME (parameter name: `u4_enable_hpel`) 11917. Enable quarter pel ME (parameter name: `u4_enable_qpel`) 12018. ME speed preset (parameter name: `u4_me_speed_preset`) 12119. Adaptive intra refresh mode (parameter name: `e_air_mode`) 12220. Disable deblock level (parameter name: `u4_disable_deblock_level`) 12321. Max search range in X direction (parameter name: `u4_srch_rng_x`) 12422. Max search range in Y direction (parameter name: `u4_srch_rng_y`) 12523. I frame interval (parameter name: `u4_i_frm_interval`) 12624. IDR frame interval (parameter name: `u4_idr_frm_interval`) 12725. Enable mastering display color volume info (parameter name: `u1_sei_mdcv_params_present_flag`) 12826. Enable content light level info (parameter name: `u1_sei_cll_params_present_flag`) 12927. Enable ambient viewing environment info (parameter name: `u1_sei_ave_params_present_flag`) 13028. Enable content color volume info (parameter name: `u1_sei_ccv_params_present_flag`) 13129. Profile (parameter name: `e_profile`) 13230. Enable aspect_ratio info (parameter name: `u1_aspect_ratio_info_present_flag`) 13331. Enable NAL HRD parameters presence (parameter name: `u1_nal_hrd_parameters_present_flag`) 13432. Enable VCL HRD parameters presence (parameter name: `u1_vcl_hrd_parameters_present_flag`) 13533. Enable force IDR frame (parameter name: `mIsForceIdrEnabled`) 13634. Enable dynamic bitrate change (parameter name: `mIsDynamicBitRateChangeEnabled`) 13735. Enable dynamic framerate change (parameter name: `mIsDynamicFrameRateChangeEnabled`) 13836. Force IDR frame number (parameter name: `mForceIdrInterval`) 13937. Frame number for dynamic bitrate (parameter name: `mDynamicBitRateInterval`) 14038. Frame number for dynamic framerate (parameter name: `mDynamicFrameRateInterval`) 141 142| Parameter| Valid Values| Configured Value| 143|------------- |-------------| ----- | 144| `u4_wd` | In the range `0 to 10239` | All the bits of 1st and 2nd byte of data | 145| `u4_ht` | In the range `0 to 10239` | All the bits of 3rd and 4th byte of data | 146| `e_inp_color_fmt` | 0. `IV_YUV_420P` 1. `IV_YUV_420SP_UV` 2. `IV_YUV_422ILE` 3. `IV_YUV_420SP_VU` | All the bits of 5th byte of data | 147| `e_arch` | 0. `ARCH_ARM_NONEON` 1. `ARCH_NA` | bit 0 and 1 of 6th byte of data | 148| `e_rc_mode` | 0. `IVE_RC_NONE` 1. `IVE_RC_STORAGE` 2. `IVE_RC_CBR_NON_LOW_DELAY` 3. `IVE_RC_CBR_LOW_DELAY` | All the bits of 7th byte of data modulus 4 | 149| `u4_num_cores` | 0. `0` 1. `1` 2. `2` 3. `3`| bit 0 and 1 of 8th byte of data | 150| `u4_num_bframes` | In the range `0 to 7` | bit 0, 1 and 2 of 9th byte of data | 151| `u4_enc_speed_preset` | 0. `IVE_CONFIG` 1. `IVE_SLOWEST` 2. `IVE_NORMAL` 3. `IVE_FAST` 4. `IVE_HIGH_SPEED` 5. `IVE_FASTEST` | All the bits of 10th byte of data modulus 6 | 152| `u4_constrained_intra_pred` | 0. `0` 1. `1` | bit 0 of 11th byte of data | 153| `u4_enable_intra_4x4` | 0. `0` 1. `1` | bit 0 of 12th byte of data | 154| `u4_i_qp` | In the range `4 to 51` | All the bits of 13th byte of data | 155| `u4_p_qp` | In the range `4 to 51` | All the bits of 14th byte of data | 156| `u4_b_qp` | In the range `4 to 51` | All the bits of 15th byte of data | 157| `u4_target_bitrate` | In the range `0 to 500000000` | All the bits of 16th and 17th byte of data | 158| `u4_target_bitrate` | In the range `0 to 255` | All the bits of 18th byte of data | 159| `u4_air_refresh_period` | In the range `1 to 256` | All the bits of 19th byte of data | 160| `u4_air_refresh_period` | In the range `1 to 256` | All the bits of 19th byte of data | 161| `u4_enable_hpel` | 0. `0` 1. `1` | bit 0 of 20th byte of data | 162| `u4_enable_qpel` | 0. `0` 1. `1` | bit 0 of 21st byte of data | 163| `u4_me_speed_preset` | 0. `0` 1. `50` 2. `75` 3. `100` | All the bits of 22nd byte of data modulus 4 | 164| `e_air_mode` | 0. `IVE_AIR_MODE_NONE` 1. `IVE_AIR_MODE_CYCLIC` 2. `IVE_AIR_MODE_RANDOM` | All the bits of 23rd byte of data modulus 3 | 165| `u4_disable_deblock_level` | 0. `0` 1. `1` 2. `2` 3. `3` | bit 0 and 1 of 24th byte of data | 166| `u4_srch_rng_x` | In the range `0 to 255` | All the bits of 25th byte of data | 167| `u4_srch_rng_y` | In the range `0 to 255`| All the bits of 26th byte of data | 168| `u4_i_frm_interval` | In the range `1 to 256` | All the bits of 27th byte of data | 169| `u4_idr_frm_interval` | In the range `1 to 256` | All the bits of 28th byte of data | 170| `u1_sei_mdcv_params_present_flag` | 0. `0` 1. `1` | bit 0 of 29th byte of data | 171| `u1_sei_cll_params_present_flag` | 0. `0` 1. `1` | bit 0 of 30th byte of data | 172| `u1_sei_ave_params_present_flag` | 0. `0` 1. `1` | bit 0 of 31st byte of data | 173| `u1_sei_ccv_params_present_flag` | 0. `0` 1. `1` | bit 0 of 32nd byte of data | 174| `e_profile` | 0. `IV_PROFILE_BASE` 1. `IV_PROFILE_MAIN` | bit 0 and 1 of 33th byte of data modulus 2 | 175| `u1_aspect_ratio_info_present_flag` | 0. `0` 1. `1` | bit 0 of 34th byte of data | 176| `u1_nal_hrd_parameters_present_flag` | 0. `0` 1. `1` | bit 0 of 35th byte of data | 177| `u1_vcl_hrd_parameters_present_flag` | 0. `0` 1. `1` | bit 0 of 36th byte of data | 178| `mIsForceIdrEnabled` | 0. `0` 1. `1` | bit 0 of 37th byte of data | 179| `mIsDynamicBitRateChangeEnabled` | 0. `0` 1. `1` | bit 0 of 38th byte of data | 180| `mIsDynamicFrameRateChangeEnabled` | 0. `0` 1. `1` | bit 0 of 39th byte of data | 181| `mForceIdrInterval` | In the range `0 to 7` | bit 0, 1 and 2 of 40th byte of data | 182| `mDynamicBitRateInterval` | In the range `0 to 7` | bit 0, 1 and 2 of 41st byte of data | 183| `mDynamicFrameRateInterval` | In the range `0 to 7` | bit 0, 1 and 2 of 42nd byte of data | 184 185This also ensures that the plugin is always deterministic for any given input. 186 187##### Maximize utilization of input data 188The plugin feeds the entire input data to the codec using a loop. 189If the encode operation was successful, the input is advanced by the frame size. 190If the encode operation was un-successful, the input is still advanced by frame size so 191that the fuzzer can proceed to feed the next frame. 192 193This ensures that the plugin tolerates any kind of input (empty, huge, 194malformed, etc) and doesnt `exit()` on any input and thereby increasing the 195chance of identifying vulnerabilities. 196 197 198## References: 199 * http://llvm.org/docs/LibFuzzer.html 200 * https://github.com/google/oss-fuzz 201