This describes steps to build avc_dec_fuzzer binary.
Clone libavc repository
$ git clone https://android.googlesource.com/platform/external/libavc
Create a directory inside libavc and change directory
$ cd libavc $ mkdir build $ cd build
Build libavc using cmake
$ CC=clang CXX=clang++ cmake ../ \ -DSANITIZE=fuzzer-no-link,address,signed-integer-overflow $ make
Build the fuzzer
$ clang++ -std=c++11 -fsanitize=fuzzer,address -I. -I../ -I../common \ -I../decoder -Wl,--start-group ../fuzzer/avc_dec_fuzzer.cpp \ -o ./avc_dec_fuzzer ./libavcdec.a -Wl,--end-group
Create a directory CORPUS_DIR and copy some elementary h264 files to that folder To run the fuzzer
$ ./avc_dec_fuzzer CORPUS_DIR
Build the fuzzer
$ SANITIZE_TARGET=address SANITIZE_HOST=address mmma -j$(nproc) \ external/libavc/fuzzer
Create a directory CORPUS_DIR and copy some elementary h264 files to that folder Push this directory to device.
To run on device
$ adb sync data $ adb shell /data/fuzz/avc_dec_fuzzer CORPUS_DIR
To run on host
$ $ANDROID_HOST_OUT/fuzz/avc_dec_fuzzer CORPUS_DIR
The fuzzer plugin for AVC is designed based on the understanding of the codec and tries to achieve the following:
The configuration parameters are not hardcoded, but instead selected based on incoming data. This ensures more code paths are reached by the fuzzer.
AVC supports the following parameters:
u4_wd
)u4_ht
)e_inp_color_fmt
)e_arch
)e_rc_mode
)u4_num_cores
)u4_num_bframes
)u4_enc_speed_preset
)u4_constrained_intra_pred
)u4_enable_intra_4x4
)u4_i_qp
)u4_p_qp
)u4_b_qp
)u4_target_bitrate
)u4_air_refresh_period
)u4_enable_hpel
)u4_enable_qpel
)u4_me_speed_preset
)e_air_mode
)u4_disable_deblock_level
)u4_srch_rng_x
)u4_srch_rng_y
)u4_i_frm_interval
)u4_idr_frm_interval
)u1_sei_mdcv_params_present_flag
)u1_sei_cll_params_present_flag
)u1_sei_ave_params_present_flag
)u1_sei_ccv_params_present_flag
)e_profile
)u1_aspect_ratio_info_present_flag
)u1_nal_hrd_parameters_present_flag
)u1_vcl_hrd_parameters_present_flag
)mIsForceIdrEnabled
)mIsDynamicBitRateChangeEnabled
)mIsDynamicFrameRateChangeEnabled
)mForceIdrInterval
)mDynamicBitRateInterval
)mDynamicFrameRateInterval
)Parameter | Valid Values | Configured Value |
---|---|---|
u4_wd | In the range 0 to 10239 | All the bits of 1st and 2nd byte of data |
u4_ht | In the range 0 to 10239 | All the bits of 3rd and 4th byte of data |
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 |
e_arch | 0. ARCH_ARM_NONEON 1. ARCH_NA | bit 0 and 1 of 6th byte of data |
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 |
u4_num_cores | 0. 0 1. 1 2. 2 3. 3 | bit 0 and 1 of 8th byte of data |
u4_num_bframes | In the range 0 to 7 | bit 0, 1 and 2 of 9th byte of data |
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 |
u4_constrained_intra_pred | 0. 0 1. 1 | bit 0 of 11th byte of data |
u4_enable_intra_4x4 | 0. 0 1. 1 | bit 0 of 12th byte of data |
u4_i_qp | In the range 4 to 51 | All the bits of 13th byte of data |
u4_p_qp | In the range 4 to 51 | All the bits of 14th byte of data |
u4_b_qp | In the range 4 to 51 | All the bits of 15th byte of data |
u4_target_bitrate | In the range 0 to 500000000 | All the bits of 16th and 17th byte of data |
u4_target_bitrate | In the range 0 to 255 | All the bits of 18th byte of data |
u4_air_refresh_period | In the range 1 to 256 | All the bits of 19th byte of data |
u4_air_refresh_period | In the range 1 to 256 | All the bits of 19th byte of data |
u4_enable_hpel | 0. 0 1. 1 | bit 0 of 20th byte of data |
u4_enable_qpel | 0. 0 1. 1 | bit 0 of 21st byte of data |
u4_me_speed_preset | 0. 0 1. 50 2. 75 3. 100 | All the bits of 22nd byte of data modulus 4 |
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 |
u4_disable_deblock_level | 0. 0 1. 1 2. 2 3. 3 | bit 0 and 1 of 24th byte of data |
u4_srch_rng_x | In the range 0 to 255 | All the bits of 25th byte of data |
u4_srch_rng_y | In the range 0 to 255 | All the bits of 26th byte of data |
u4_i_frm_interval | In the range 1 to 256 | All the bits of 27th byte of data |
u4_idr_frm_interval | In the range 1 to 256 | All the bits of 28th byte of data |
u1_sei_mdcv_params_present_flag | 0. 0 1. 1 | bit 0 of 29th byte of data |
u1_sei_cll_params_present_flag | 0. 0 1. 1 | bit 0 of 30th byte of data |
u1_sei_ave_params_present_flag | 0. 0 1. 1 | bit 0 of 31st byte of data |
u1_sei_ccv_params_present_flag | 0. 0 1. 1 | bit 0 of 32nd byte of data |
e_profile | 0. IV_PROFILE_BASE 1. IV_PROFILE_MAIN | bit 0 and 1 of 33th byte of data modulus 2 |
u1_aspect_ratio_info_present_flag | 0. 0 1. 1 | bit 0 of 34th byte of data |
u1_nal_hrd_parameters_present_flag | 0. 0 1. 1 | bit 0 of 35th byte of data |
u1_vcl_hrd_parameters_present_flag | 0. 0 1. 1 | bit 0 of 36th byte of data |
mIsForceIdrEnabled | 0. 0 1. 1 | bit 0 of 37th byte of data |
mIsDynamicBitRateChangeEnabled | 0. 0 1. 1 | bit 0 of 38th byte of data |
mIsDynamicFrameRateChangeEnabled | 0. 0 1. 1 | bit 0 of 39th byte of data |
mForceIdrInterval | In the range 0 to 7 | bit 0, 1 and 2 of 40th byte of data |
mDynamicBitRateInterval | In the range 0 to 7 | bit 0, 1 and 2 of 41st byte of data |
mDynamicFrameRateInterval | In the range 0 to 7 | bit 0, 1 and 2 of 42nd byte of data |
This also ensures that the plugin is always deterministic for any given input.
The plugin feeds the entire input data to the codec using a loop. If the encode operation was successful, the input is advanced by the frame size. If the encode 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.
This describes steps to build avc_enc_fuzzer binary.
Build the fuzzer
$ mm -j$(nproc) avc_enc_fuzzer
Create a directory CORPUS_DIR and copy some yuv files to that folder Push this directory to device.
To run on device
$ adb sync data $ adb shell /data/fuzz/arm64/avc_enc_fuzzer/avc_enc_fuzzer CORPUS_DIR
To run on host
$ $ANDROID_HOST_OUT/fuzz/x86_64/avc_enc_fuzzer/avc_enc_fuzzer CORPUS_DIR