1*c83a76b0SSuyog Pawar# Fuzzer for libhevc decoder and encoder 2*c83a76b0SSuyog Pawar 3*c83a76b0SSuyog PawarThis describes steps to build hevc_dec_fuzzer and hevc_enc_fuzzer binary. 4*c83a76b0SSuyog Pawar 5*c83a76b0SSuyog Pawar## Linux x86/x64 6*c83a76b0SSuyog Pawar 7*c83a76b0SSuyog Pawar### Requirements 8*c83a76b0SSuyog Pawar- cmake (3.9.1 or above) 9*c83a76b0SSuyog Pawar- make 10*c83a76b0SSuyog Pawar- clang (6.0 or above) 11*c83a76b0SSuyog Pawar needs to support -fsanitize=fuzzer, -fsanitize=fuzzer-no-link 12*c83a76b0SSuyog Pawar 13*c83a76b0SSuyog Pawar### Steps to build 14*c83a76b0SSuyog PawarClone libhevc repository 15*c83a76b0SSuyog Pawar``` 16*c83a76b0SSuyog Pawar$ git clone https://android.googlesource.com/platform/external/libhevc 17*c83a76b0SSuyog Pawar``` 18*c83a76b0SSuyog PawarCreate a directory inside libhevc and change directory 19*c83a76b0SSuyog Pawar``` 20*c83a76b0SSuyog Pawar $ cd libhevc 21*c83a76b0SSuyog Pawar $ mkdir build 22*c83a76b0SSuyog Pawar $ cd build 23*c83a76b0SSuyog Pawar``` 24*c83a76b0SSuyog PawarBuild fuzzer with required sanitizers (-DSANITIZE=fuzzer-no-link is mandatory 25*c83a76b0SSuyog Pawar to enable fuzzers) 26*c83a76b0SSuyog Pawar``` 27*c83a76b0SSuyog Pawar $ cmake .. -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ \ 28*c83a76b0SSuyog Pawar -DCMAKE_BUILD_TYPE=Debug -DSANITIZE=fuzzer-no-link,address 29*c83a76b0SSuyog Pawar $ make 30*c83a76b0SSuyog Pawar ``` 31*c83a76b0SSuyog Pawar 32*c83a76b0SSuyog Pawar### Steps to run 33*c83a76b0SSuyog PawarCreate a directory CORPUS_DIR and copy some elementary hevc files 34*c83a76b0SSuyog Pawar(for hevc_dec_fuzzer) or yuv files (for hevc_enc_fuzzer) to that directory 35*c83a76b0SSuyog Pawar 36*c83a76b0SSuyog PawarTo run the fuzzers 37*c83a76b0SSuyog Pawar``` 38*c83a76b0SSuyog Pawar$ ./hevc_dec_fuzzer CORPUS_DIR 39*c83a76b0SSuyog Pawar$ ./hevc_enc_fuzzer CORPUS_DIR 40*c83a76b0SSuyog Pawar``` 41*c83a76b0SSuyog Pawar 42*c83a76b0SSuyog Pawar## Android 43*c83a76b0SSuyog Pawar 44*c83a76b0SSuyog Pawar### Steps to build 45*c83a76b0SSuyog PawarBuild the fuzzers 46*c83a76b0SSuyog Pawar``` 47*c83a76b0SSuyog Pawar $ mm -j$(nproc) hevc_dec_fuzzer 48*c83a76b0SSuyog Pawar $ mm -j$(nproc) hevc_enc_fuzzer 49*c83a76b0SSuyog Pawar``` 50*c83a76b0SSuyog Pawar 51*c83a76b0SSuyog Pawar### Steps to run 52*c83a76b0SSuyog PawarCreate a directory CORPUS_DIR and copy some elementary hevc files 53*c83a76b0SSuyog Pawar(for hevc_dec_fuzzer) or yuv files (for hevc_enc_fuzzer) to that folder 54*c83a76b0SSuyog PawarPush this directory to device 55*c83a76b0SSuyog Pawar 56*c83a76b0SSuyog PawarTo run hevc_dec_fuzzer on device 57*c83a76b0SSuyog Pawar``` 58*c83a76b0SSuyog Pawar $ adb sync data 59*c83a76b0SSuyog Pawar $ adb shell /data/fuzz/hevc_dec_fuzzer CORPUS_DIR 60*c83a76b0SSuyog Pawar``` 61*c83a76b0SSuyog PawarTo run hevc_enc_fuzzer on device 62*c83a76b0SSuyog Pawar``` 63*c83a76b0SSuyog Pawar $ adb sync data 64*c83a76b0SSuyog Pawar $ adb shell /data/fuzz/arm64/hevc_enc_fuzzer/hevc_enc_fuzzer CORPUS_DIR 65*c83a76b0SSuyog Pawar``` 66*c83a76b0SSuyog Pawar 67*c83a76b0SSuyog PawarTo run hevc_dec_fuzzer on host 68*c83a76b0SSuyog Pawar``` 69*c83a76b0SSuyog Pawar $ $ANDROID_HOST_OUT/fuzz/x86_64/hevc_dec_fuzzer/hevc_dec_fuzzer CORPUS_DIR 70*c83a76b0SSuyog Pawar``` 71*c83a76b0SSuyog Pawar 72*c83a76b0SSuyog PawarTo run hevc_enc_fuzzer on host 73*c83a76b0SSuyog Pawar``` 74*c83a76b0SSuyog Pawar $ $ANDROID_HOST_OUT/fuzz/x86_64/hevc_enc_fuzzer/hevc_enc_fuzzer CORPUS_DIR 75*c83a76b0SSuyog Pawar``` 76*c83a76b0SSuyog Pawar 77*c83a76b0SSuyog Pawar 78*c83a76b0SSuyog Pawar# Appendix 79*c83a76b0SSuyog Pawar## libhevc encoder fuzzer 80*c83a76b0SSuyog Pawar 81*c83a76b0SSuyog Pawar## Plugin Design Considerations 82*c83a76b0SSuyog PawarThe fuzzer plugin for HEVC is designed based on the understanding of the 83*c83a76b0SSuyog Pawarcodec and tries to achieve the following: 84*c83a76b0SSuyog Pawar 85*c83a76b0SSuyog Pawar##### Maximize code coverage 86*c83a76b0SSuyog PawarThe configuration parameters are not hardcoded, but instead selected based on 87*c83a76b0SSuyog Pawarincoming data. This ensures more code paths are reached by the fuzzer. 88*c83a76b0SSuyog Pawar 89*c83a76b0SSuyog PawarHEVC supports the following parameters: 90*c83a76b0SSuyog Pawar1. Frame Width (parameter name: `i4_width`) 91*c83a76b0SSuyog Pawar2. Frame Height (parameter name: `i4_height`) 92*c83a76b0SSuyog Pawar3. Intra max transform tree depth (parameter name: `i4_max_tr_tree_depth_I`) 93*c83a76b0SSuyog Pawar4. Inter max transform tree depth (parameter name: `i4_max_tr_tree_depth_nI`) 94*c83a76b0SSuyog Pawar5. CU level Qp modulation (parameter name: `i4_cu_level_rc`) 95*c83a76b0SSuyog Pawar6. Rate control mode (parameter name: `i4_rate_control_mode`) 96*c83a76b0SSuyog Pawar7. Frame level Qp (parameter name: `ai4_frame_qp`) 97*c83a76b0SSuyog Pawar8. Encoder quality preset (parameter name: `i4_quality_preset`) 98*c83a76b0SSuyog Pawar9. Target Bitrate (parameter name: `ai4_tgt_bitrate`) 99*c83a76b0SSuyog Pawar10. Enable entropy sync (parameter name: `i4_enable_entropy_sync`) 100*c83a76b0SSuyog Pawar11. Deblocking type (parameter name: `i4_deblocking_type`) 101*c83a76b0SSuyog Pawar12. Default scaling matrices (parameter name: `i4_use_default_sc_mtx`) 102*c83a76b0SSuyog Pawar13. Max temporal layers (parameter name: `i4_max_temporal_layers`) 103*c83a76b0SSuyog Pawar14. Max difference b/w IDR frames (parameter name: `i4_max_closed_gop_period`) 104*c83a76b0SSuyog Pawar15. Min difference b/w IDR frames (parameter name: `i4_min_closed_gop_period`) 105*c83a76b0SSuyog Pawar16. Max difference b/w I frames (parameter name: `i4_max_i_open_gop_period`) 106*c83a76b0SSuyog Pawar17. Max difference b/w CRA frames (parameter name: `i4_max_cra_open_gop_period`) 107*c83a76b0SSuyog Pawar18. Automatic insertion of SPS at each CDR (parameter name: `i4_sps_at_cdr_enable`) 108*c83a76b0SSuyog Pawar19. Enable VUI output (parameter name: `i4_vui_enable`) 109*c83a76b0SSuyog Pawar20. Enable SEI messages (parameter name: `i4_sei_enable_flag`) 110*c83a76b0SSuyog Pawar21. Architecture type (parameter name: `e_arch_type`) 111*c83a76b0SSuyog Pawar22. Enable force IDR frame test(parameter name: `mIsForceIdrEnabled`) 112*c83a76b0SSuyog Pawar23. Enable dynamic bitrate test (parameter name: `mIsDynamicBitrateChangeEnabled`) 113*c83a76b0SSuyog Pawar24. Force IDR frame number (parameter name: `mForceIdrInterval`) 114*c83a76b0SSuyog Pawar25. Frame number for dynamic bitrate (parameter name: `mDynamicBitrateInterval`) 115*c83a76b0SSuyog Pawar 116*c83a76b0SSuyog Pawar| Parameter| Valid Values| Configured Value| 117*c83a76b0SSuyog Pawar|------------- |-------------| ----- | 118*c83a76b0SSuyog Pawar| `i4_width` | In the range `0 to 10239` | All the bits of 1st and 2nd byte of data | 119*c83a76b0SSuyog Pawar| `i4_height` | In the range `0 to 10239` | All the bits of 3rd and 4th byte of data | 120*c83a76b0SSuyog Pawar| `i4_max_tr_tree_depth_I` | 0. `1` 1. `2` 2. `3` | All the bits of 5th byte of data | 121*c83a76b0SSuyog Pawar| `i4_max_tr_tree_depth_nI` | 0. `1` 1. `2` 2. `3` 3. `4` | bit 0 and 1 of 6th byte of data | 122*c83a76b0SSuyog Pawar| `i4_cu_level_rc` | 0. `0` 1. `1` | bit 0 of 7th byte of data | 123*c83a76b0SSuyog Pawar| `i4_rate_control_mode` | 0. `VBR` 1. `CQP` 2. `CBR` | All the bits of 8th byte of data modulus 3 | 124*c83a76b0SSuyog Pawar| `ai4_frame_qp` | In the range `1 to 51` | All the bits of 9th byte of data | 125*c83a76b0SSuyog Pawar| `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*c83a76b0SSuyog Pawar| `ai4_tgt_bitrate` | In the range `0 to 500000000` | All the bits of 11th and 12th byte of data | 127*c83a76b0SSuyog Pawar| `i4_enable_entropy_sync` | 0. `0` 1. `1` | bit 0 of 13th byte of data | 128*c83a76b0SSuyog Pawar| `i4_deblocking_type` | 0. `0` 1. `1` | bit 0 of 14th byte of data | 129*c83a76b0SSuyog Pawar| `i4_use_default_sc_mtx` | 0. `0` 1. `1` | bit 0 of 15th byte of data | 130*c83a76b0SSuyog Pawar| `i4_max_temporal_layers` | 0. `0` 1. `1` 2. `2` 3. `3` | bit 0 and 1 of 16th byte of data | 131*c83a76b0SSuyog Pawar| `i4_max_closed_gop_period` | In the range `0 to 255` | All the bits of 17th byte of data | 132*c83a76b0SSuyog Pawar| `i4_min_closed_gop_period` | In the range `0 to 255` | All the bits of 18th byte of data | 133*c83a76b0SSuyog Pawar| `i4_max_i_open_gop_period` | In the range `0 to 255` | All the bits of 19th byte of data | 134*c83a76b0SSuyog Pawar| `i4_max_cra_open_gop_period` | In the range `0 to 255` | All the bits of 20th byte of data | 135*c83a76b0SSuyog Pawar| `i4_sps_at_cdr_enable` | 0. `0` 1. `1` | bit 0 of 21st byte of data | 136*c83a76b0SSuyog Pawar| `i4_vui_enable` | 0. `0` 1. `1` | bit 0 of 22nd byte of data | 137*c83a76b0SSuyog Pawar| `i4_sei_enable_flag` | 0. `0` 1. `1` | bit 0 of 23th byte of data | 138*c83a76b0SSuyog Pawar| `e_arch_type` | 0. `ARCH_ARM_NONEON` 1. `ARCH_NA` | bit 0 and 1 of 24th byte of data | 139*c83a76b0SSuyog Pawar| `mIsForceIdrEnabled` | 0. `0` 1. `1` | bit 0 of 25th byte of data | 140*c83a76b0SSuyog Pawar| `mIsDynamicBitrateChangeEnabled` | 0. `0` 1. `1` | bit 0 of byte of data | 141*c83a76b0SSuyog Pawar| `mForceIdrInterval` | In the range `0 to 7` | bit 0, 1 and 2 of 27th byte of data | 142*c83a76b0SSuyog Pawar| `mDynamicBitrateInterval` | In the range `0 to 7` | bit 0, 1 and 2 of 28th byte of data | 143*c83a76b0SSuyog Pawar 144*c83a76b0SSuyog PawarThis also ensures that the plugin is always deterministic for any given input. 145*c83a76b0SSuyog Pawar 146*c83a76b0SSuyog Pawar##### Maximize utilization of input data 147*c83a76b0SSuyog PawarThe plugin feeds the entire input data to the codec using a loop. 148*c83a76b0SSuyog PawarIf the encode operation was successful, the input is advanced by the frame size. 149*c83a76b0SSuyog PawarIf the encode operation was un-successful, the input is still advanced by frame size so 150*c83a76b0SSuyog Pawarthat the fuzzer can proceed to feed the next frame. 151*c83a76b0SSuyog Pawar 152*c83a76b0SSuyog PawarThis ensures that the plugin tolerates any kind of input (empty, huge, 153*c83a76b0SSuyog Pawarmalformed, etc) and doesnt `exit()` on any input and thereby increasing the 154*c83a76b0SSuyog Pawarchance of identifying vulnerabilities. 155*c83a76b0SSuyog Pawar 156*c83a76b0SSuyog Pawar 157*c83a76b0SSuyog Pawar## References: 158*c83a76b0SSuyog Pawar * http://llvm.org/docs/LibFuzzer.html 159*c83a76b0SSuyog Pawar * https://github.com/google/oss-fuzz 160