1# Fuzzer for libhevc decoder and encoder 2 3This describes steps to build hevc_dec_fuzzer and hevc_enc_fuzzer binary. 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 libhevc repository 15``` 16$ git clone https://android.googlesource.com/platform/external/libhevc 17``` 18Create a directory inside libhevc and change directory 19``` 20 $ cd libhevc 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 $ make 30 ``` 31 32### Steps to run 33Create a directory CORPUS_DIR and copy some elementary hevc files 34(for hevc_dec_fuzzer) or yuv files (for hevc_enc_fuzzer) to that directory 35 36To run the fuzzers 37``` 38$ ./hevc_dec_fuzzer CORPUS_DIR 39$ ./hevc_enc_fuzzer CORPUS_DIR 40``` 41 42## Android 43 44### Steps to build 45Build the fuzzers 46``` 47 $ mm -j$(nproc) hevc_dec_fuzzer 48 $ mm -j$(nproc) hevc_enc_fuzzer 49``` 50 51### Steps to run 52Create a directory CORPUS_DIR and copy some elementary hevc files 53(for hevc_dec_fuzzer) or yuv files (for hevc_enc_fuzzer) to that folder 54Push this directory to device 55 56To run hevc_dec_fuzzer on device 57``` 58 $ adb sync data 59 $ adb shell /data/fuzz/hevc_dec_fuzzer CORPUS_DIR 60``` 61To run hevc_enc_fuzzer on device 62``` 63 $ adb sync data 64 $ adb shell /data/fuzz/arm64/hevc_enc_fuzzer/hevc_enc_fuzzer CORPUS_DIR 65``` 66 67To run hevc_dec_fuzzer on host 68``` 69 $ $ANDROID_HOST_OUT/fuzz/x86_64/hevc_dec_fuzzer/hevc_dec_fuzzer CORPUS_DIR 70``` 71 72To run hevc_enc_fuzzer on host 73``` 74 $ $ANDROID_HOST_OUT/fuzz/x86_64/hevc_enc_fuzzer/hevc_enc_fuzzer CORPUS_DIR 75``` 76 77 78# Appendix 79## libhevc encoder fuzzer 80 81## Plugin Design Considerations 82The fuzzer plugin for HEVC is designed based on the understanding of the 83codec and tries to achieve the following: 84 85##### Maximize code coverage 86The configuration parameters are not hardcoded, but instead selected based on 87incoming data. This ensures more code paths are reached by the fuzzer. 88 89HEVC supports the following parameters: 901. Frame Width (parameter name: `i4_width`) 912. Frame Height (parameter name: `i4_height`) 923. Intra max transform tree depth (parameter name: `i4_max_tr_tree_depth_I`) 934. Inter max transform tree depth (parameter name: `i4_max_tr_tree_depth_nI`) 945. CU level Qp modulation (parameter name: `i4_cu_level_rc`) 956. Rate control mode (parameter name: `i4_rate_control_mode`) 967. Frame level Qp (parameter name: `ai4_frame_qp`) 978. Encoder quality preset (parameter name: `i4_quality_preset`) 989. Target Bitrate (parameter name: `ai4_tgt_bitrate`) 9910. Enable entropy sync (parameter name: `i4_enable_entropy_sync`) 10011. Deblocking type (parameter name: `i4_deblocking_type`) 10112. Default scaling matrices (parameter name: `i4_use_default_sc_mtx`) 10213. Max temporal layers (parameter name: `i4_max_temporal_layers`) 10314. Max difference b/w IDR frames (parameter name: `i4_max_closed_gop_period`) 10415. Min difference b/w IDR frames (parameter name: `i4_min_closed_gop_period`) 10516. Max difference b/w I frames (parameter name: `i4_max_i_open_gop_period`) 10617. Max difference b/w CRA frames (parameter name: `i4_max_cra_open_gop_period`) 10718. Automatic insertion of SPS at each CDR (parameter name: `i4_sps_at_cdr_enable`) 10819. Enable VUI output (parameter name: `i4_vui_enable`) 10920. Enable SEI messages (parameter name: `i4_sei_enable_flag`) 11021. Architecture type (parameter name: `e_arch_type`) 11122. Enable force IDR frame test(parameter name: `mIsForceIdrEnabled`) 11223. Enable dynamic bitrate test (parameter name: `mIsDynamicBitrateChangeEnabled`) 11324. Force IDR frame number (parameter name: `mForceIdrInterval`) 11425. Frame number for dynamic bitrate (parameter name: `mDynamicBitrateInterval`) 115 116| Parameter| Valid Values| Configured Value| 117|------------- |-------------| ----- | 118| `i4_width` | In the range `0 to 10239` | All the bits of 1st and 2nd byte of data | 119| `i4_height` | In the range `0 to 10239` | All the bits of 3rd and 4th byte of data | 120| `i4_max_tr_tree_depth_I` | 0. `1` 1. `2` 2. `3` | All the bits of 5th byte of data | 121| `i4_max_tr_tree_depth_nI` | 0. `1` 1. `2` 2. `3` 3. `4` | bit 0 and 1 of 6th byte of data | 122| `i4_cu_level_rc` | 0. `0` 1. `1` | bit 0 of 7th byte of data | 123| `i4_rate_control_mode` | 0. `VBR` 1. `CQP` 2. `CBR` | All the bits of 8th byte of data modulus 3 | 124| `ai4_frame_qp` | In the range `1 to 51` | All the bits of 9th byte of data | 125| `i4_quality_preset` | 0. `IHEVCE_QUALITY_P0` 1. `IHEVCE_QUALITY_P2` 2. `IHEVCE_QUALITY_P3` 3. `IHEVCE_QUALITY_P4 4. `IHEVCE_QUALITY_P5` 5. `IHEVCE_QUALITY_P6` 6. `IHEVCE_QUALITY_P7` | All the bits of 10th byte of data modulus 7 | 126| `ai4_tgt_bitrate` | In the range `0 to 500000000` | All the bits of 11th and 12th byte of data | 127| `i4_enable_entropy_sync` | 0. `0` 1. `1` | bit 0 of 13th byte of data | 128| `i4_deblocking_type` | 0. `0` 1. `1` | bit 0 of 14th byte of data | 129| `i4_use_default_sc_mtx` | 0. `0` 1. `1` | bit 0 of 15th byte of data | 130| `i4_max_temporal_layers` | 0. `0` 1. `1` 2. `2` 3. `3` | bit 0 and 1 of 16th byte of data | 131| `i4_max_closed_gop_period` | In the range `0 to 255` | All the bits of 17th byte of data | 132| `i4_min_closed_gop_period` | In the range `0 to 255` | All the bits of 18th byte of data | 133| `i4_max_i_open_gop_period` | In the range `0 to 255` | All the bits of 19th byte of data | 134| `i4_max_cra_open_gop_period` | In the range `0 to 255` | All the bits of 20th byte of data | 135| `i4_sps_at_cdr_enable` | 0. `0` 1. `1` | bit 0 of 21st byte of data | 136| `i4_vui_enable` | 0. `0` 1. `1` | bit 0 of 22nd byte of data | 137| `i4_sei_enable_flag` | 0. `0` 1. `1` | bit 0 of 23th byte of data | 138| `e_arch_type` | 0. `ARCH_ARM_NONEON` 1. `ARCH_NA` | bit 0 and 1 of 24th byte of data | 139| `mIsForceIdrEnabled` | 0. `0` 1. `1` | bit 0 of 25th byte of data | 140| `mIsDynamicBitrateChangeEnabled` | 0. `0` 1. `1` | bit 0 of byte of data | 141| `mForceIdrInterval` | In the range `0 to 7` | bit 0, 1 and 2 of 27th byte of data | 142| `mDynamicBitrateInterval` | In the range `0 to 7` | bit 0, 1 and 2 of 28th byte of data | 143 144This also ensures that the plugin is always deterministic for any given input. 145 146##### Maximize utilization of input data 147The plugin feeds the entire input data to the codec using a loop. 148If the encode operation was successful, the input is advanced by the frame size. 149If the encode operation was un-successful, the input is still advanced by frame size so 150that the fuzzer can proceed to feed the next frame. 151 152This ensures that the plugin tolerates any kind of input (empty, huge, 153malformed, etc) and doesnt `exit()` on any input and thereby increasing the 154chance of identifying vulnerabilities. 155 156 157## References: 158 * http://llvm.org/docs/LibFuzzer.html 159 * https://github.com/google/oss-fuzz 160