Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright 2020 Google LLC |
2 | | // |
3 | | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | | // you may not use this file except in compliance with the License. |
5 | | // You may obtain a copy of the License at |
6 | | // |
7 | | // http://www.apache.org/licenses/LICENSE-2.0 |
8 | | // |
9 | | // Unless required by applicable law or agreed to in writing, software |
10 | | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | | // See the License for the specific language governing permissions and |
13 | | // limitations under the License. |
14 | | |
15 | | #include <errno.h> |
16 | | #include <stdint.h> |
17 | | #include <stdio.h> |
18 | | #include <stdlib.h> |
19 | | #include <string.h> |
20 | | |
21 | | #include "opusfile/config.h" |
22 | | #include "opusfile/include/opusfile.h" |
23 | | |
24 | | // Opusfile fuzzing wrapper to help with automated fuzz testing. It's based on |
25 | | // https://github.com/xiph/opusfile/blob/master/examples/opusfile_example.c |
26 | 6.06k | int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { |
27 | 6.06k | int ret, tmp; |
28 | 6.06k | OggOpusFile *of = op_open_memory(data, size, &ret); |
29 | 6.06k | if (!of) |
30 | 1.50k | return 0; |
31 | | |
32 | 4.55k | op_link_count(of); |
33 | | |
34 | 4.55k | int link_index = -1; |
35 | 4.55k | op_pcm_total(of, link_index); |
36 | 4.55k | op_raw_total(of, link_index); |
37 | 4.55k | op_pcm_tell(of); |
38 | 4.55k | op_raw_tell(of); |
39 | | |
40 | 4.55k | ogg_int64_t total_sample_count = 0; |
41 | 4.55k | const int pcm_size = 120 * 48 * 2; // 120ms/ch@48kHz is recommended |
42 | 4.55k | opus_int16 pcm[pcm_size]; |
43 | 375k | for (;;) { |
44 | 375k | ret = op_read_stereo(of, pcm, pcm_size); |
45 | 375k | if (ret < 0) { |
46 | 3.10k | break; |
47 | 3.10k | } |
48 | | |
49 | 372k | if (op_current_link(of) != link_index) { |
50 | 13.9k | link_index = op_current_link(of); |
51 | 13.9k | op_pcm_total(of, link_index); |
52 | 13.9k | op_raw_total(of, link_index); |
53 | 13.9k | op_pcm_tell(of); |
54 | 13.9k | op_raw_tell(of); |
55 | 13.9k | op_bitrate_instant(of); |
56 | 13.9k | tmp = op_head(of, link_index)->version; |
57 | | |
58 | 13.9k | const OpusTags *tags = op_tags(of, link_index); |
59 | 22.7k | for (int i = 0; i < tags->comments; ++i) { |
60 | | // Note: The compare also touches memory allocated for user_comments[i]. |
61 | | // This is a desired side effect and should be kept even if this |
62 | | // comparison is removed. |
63 | 8.78k | if (opus_tagncompare("METADATA_BLOCK_PICTURE", 22, |
64 | 8.78k | tags->user_comments[i]) == 0) { |
65 | 0 | OpusPictureTag pic; |
66 | 0 | if (opus_picture_tag_parse(&pic, tags->user_comments[i]) >= 0) { |
67 | 0 | opus_picture_tag_clear(&pic); |
68 | 0 | } |
69 | 0 | } |
70 | 8.78k | } |
71 | | |
72 | 13.9k | if (tags->vendor) { |
73 | 13.9k | tmp = tags->vendor[0]; |
74 | 13.9k | } |
75 | | |
76 | 13.9k | int binary_suffix_len; |
77 | 13.9k | opus_tags_get_binary_suffix(tags, &binary_suffix_len); |
78 | 13.9k | } |
79 | | |
80 | 372k | if (ret == 0) { |
81 | 1.45k | break; |
82 | 1.45k | } |
83 | | |
84 | 371k | total_sample_count += ret; |
85 | 371k | } |
86 | | |
87 | 4.55k | if (total_sample_count > 0) { |
88 | | // Try random-access PCM reads. The number of tests is arbitrary and the |
89 | | // offset is designed to be pseudo-random, but deterministic - this is |
90 | | // implemented using Lehmer RNG with a minor hack that probably breaks some |
91 | | // properties of the RNG (but that is acceptable). |
92 | 4.19k | ogg_int64_t rng_seed = 1307832949LL; |
93 | 138k | for (int i = 0; i < 32; ++i) { |
94 | | // Derive the next deterministic offset to test and iterate the RNG. |
95 | 134k | rng_seed = (rng_seed * 279470273LL); |
96 | 134k | const ogg_int64_t offset = rng_seed % total_sample_count; |
97 | 134k | rng_seed = rng_seed % 4294967291LL; |
98 | | |
99 | 134k | if (op_pcm_seek(of, offset) == 0) { |
100 | 84.5k | tmp = op_read_stereo(of, pcm, pcm_size); |
101 | 84.5k | } |
102 | 134k | } |
103 | 4.19k | } |
104 | | |
105 | 4.55k | op_free(of); |
106 | 4.55k | return 0; |
107 | 6.06k | } |