aboutsummaryrefslogtreecommitdiff
path: root/fuzzer/README.md
blob: 8e29ec63aa53f37fa6f6aee46064eb5e2676bbc4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
# Fuzzer for libavc decoder

This describes steps to build avc_dec_fuzzer binary.

## Linux x86/x64

###  Requirements
- cmake (3.5 or above)
- make
- clang (6.0 or above)
  needs to support -fsanitize=fuzzer, -fsanitize=fuzzer-no-link

### Steps to build
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
```

### Steps to run
Create a directory CORPUS_DIR and copy some elementary h264 files to that folder
To run the fuzzer
```
$ ./avc_dec_fuzzer CORPUS_DIR
```

## Android

### Steps to build
Build the fuzzer
```
  $ SANITIZE_TARGET=address SANITIZE_HOST=address mmma -j$(nproc) \
    external/libavc/fuzzer
```

### Steps to run
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
```


# Fuzzer for libavc encoder

## Plugin Design Considerations
The fuzzer plugin for AVC is designed based on the understanding of the
codec and tries to achieve the following:

##### Maximize code coverage
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:
1. Frame Width (parameter name: `u4_wd`)
2. Frame Height (parameter name: `u4_ht`)
3. Input color format  (parameter name: `e_inp_color_fmt`)
4. Architecture type (parameter name: `e_arch`)
5. Rate control mode (parameter name: `e_rc_mode`)
6. Number of cores (parameter name: `u4_num_cores`)
7. Maximum B frames (parameter name: `u4_num_bframes`)
8. Encoder speed preset (parameter name: `u4_enc_speed_preset`)
9. enable constrained intra prediction (parameter name: `u4_constrained_intra_pred`)
10. enable intra 4x4 (parameter name: `u4_enable_intra_4x4`)
11. Qp for I frames (parameter name: `u4_i_qp`)
12. Qp for P frames (parameter name: `u4_p_qp`)
13. Qp for B frames (parameter name: `u4_b_qp`)
14. Target Bitrate (parameter name: `u4_target_bitrate`)
15. Intra refresh period in frames (parameter name: `u4_air_refresh_period`)
16. Enable half pel ME (parameter name: `u4_enable_hpel`)
17. Enable quarter pel ME (parameter name: `u4_enable_qpel`)
18. ME speed preset (parameter name: `u4_me_speed_preset`)
19. Adaptive intra refresh mode (parameter name: `e_air_mode`)
20. Disable deblock level (parameter name: `u4_disable_deblock_level`)
21. Max search range in X direction (parameter name: `u4_srch_rng_x`)
22. Max search range in Y direction (parameter name: `u4_srch_rng_y`)
23. I frame interval (parameter name: `u4_i_frm_interval`)
24. IDR frame interval (parameter name: `u4_idr_frm_interval`)
25. Enable mastering display color volume info (parameter name: `u1_sei_mdcv_params_present_flag`)
26. Enable content light level info (parameter name: `u1_sei_cll_params_present_flag`)
27. Enable ambient viewing environment info (parameter name: `u1_sei_ave_params_present_flag`)
28. Enable content color volume info (parameter name: `u1_sei_ccv_params_present_flag`)
29. Profile (parameter name: `e_profile`)
30. Enable aspect_ratio info (parameter name: `u1_aspect_ratio_info_present_flag`)
31. Enable NAL HRD parameters presence (parameter name: `u1_nal_hrd_parameters_present_flag`)
32. Enable VCL HRD parameters presence (parameter name: `u1_vcl_hrd_parameters_present_flag`)
33. Enable force IDR frame (parameter name: `mIsForceIdrEnabled`)
34. Enable dynamic bitrate change (parameter name: `mIsDynamicBitRateChangeEnabled`)
35. Enable dynamic framerate change (parameter name: `mIsDynamicFrameRateChangeEnabled`)
36. Force IDR frame number (parameter name: `mForceIdrInterval`)
37. Frame number for dynamic bitrate (parameter name: `mDynamicBitRateInterval`)
38. Frame number for dynamic framerate (parameter name: `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.

##### Maximize utilization of input data
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.

## Build

This describes steps to build avc_enc_fuzzer binary.

### Android

#### Steps to build
Build the fuzzer
```
  $ mm -j$(nproc) avc_enc_fuzzer
```

#### Steps to run
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
```

## References:
 * http://llvm.org/docs/LibFuzzer.html
 * https://github.com/google/oss-fuzz